1 В избранное 0 Ответвления 0

OSCHINA-MIRROR/wizardforcel-sklearn-cb

Присоединиться к Gitlife
Откройте для себя и примите участие в публичных проектах с открытым исходным кодом с участием более 10 миллионов разработчиков. Приватные репозитории также полностью бесплатны :)
Присоединиться бесплатно
Клонировать/Скачать
2.md 79 КБ
Копировать Редактировать Web IDE Исходные данные Просмотреть построчно История
Отправлено 06.03.2025 03:36 55c0d1d

Вторая глава Обработка линейных моделей

Автор: Trent Hauck

Переводчик: muxuezi

Лицензия: CC BY-NC-SA 4.0

В этой главе рассматриваются следующие темы:

  1. Линейная регрессия
  2. Оценка модели линейной регрессии
  3. Коррекция недостатков линейной регрессии с помощью岭回归
  4. Оптимизация параметра岭回归
  5. Регуляризация LASSO
  6. Регуляризация LARS
  7. Обработка задач классификации с использованием линейных методов — логистическая регрессия
  8. Байесовская岭回归
  9. Учёба от ошибок с помощью градиентного бустинга

Введение

Линейные модели являются основой статистики и машинного обучения. Множество методов используют линейные комбинации переменных для описания отношений между данными. Часто требуется много усилий для выполнения различных преобразований данных, чтобы они могли быть представлены в виде линейной комбинации.

В этой главе мы рассмотрим модели от простого линейного аппроксиматора до классификаторов, а также байесовскую岭回归.# 2.1 Линейная регрессия

Начнем работу с созданием модели! Мы начнем с самого простого — линейной регрессии. Линейная регрессия является одной из самых ранних и базовых моделей — она аппроксимирует данные прямой линией.

Подготовка

Датасет boston отлично подходит для демонстрации линейной регрессии. Датасет boston содержит медианную стоимость домов в Бостоне. Также есть несколько факторов, которые могут влиять на цену дома, такие как уровень преступности (crime rate).

Сначала загрузим данные:

from sklearn import datasets
boston = datasets.load_boston()

Как это сделать...

На самом деле использование линейной регрессии из scikit-learn очень просто, его API аналогично API других моделей.

Сначала импортируем класс LinearRegression и создаем объект:

from sklearn.linear_model import LinearRegression
lr = LinearRegression()

Теперь передаем признаки и целевые значения в метод fit класса LinearRegression:

lr.fit(boston.data, boston.target)

Линейная регрессия(copy_X=True, fit_intercept=True, n_jobs=1, normalize=False)

2.2 Оценка модели линейной регрессии

В этом разделе мы рассмотрим качество аппроксимации данных моделью линейной регрессии. В предыдущем разделе мы обучили модель на данных, но не уделили особого внимания качеству обучения. После того как обучение завершено, первым вопросом, который следует задать, является "Какова эффективность обучения?" Этот раздел ответит на этот вопрос.## Подготовка

Мы продолжаем использовать объект lr и набор данных boston, использованные в предыдущем разделе. Объект lr уже обучен на данных, поэтому теперь доступно множество методов для его использования.

from sklearn import datasets
boston = datasets.load_boston()
from sklearn.linear_model import LinearRegression
lr = LinearRegression()
lr.fit(boston.data, boston.target)
Линейная регрессия(copy_X=True, fit_intercept=True, n_jobs=1, normalize=False)
predictions = lr.predict(boston.data)

Как это сделать...

Мы можем просмотреть некоторые простые метрики и графики. Давайте посмотрим на график остатков, представленный в предыдущем разделе:

%matplotlib inline
from matplotlib import pyplot as plt
f, ax = plt.subplots(figsize=(7, 5))
f.tight_layout()
ax.hist(boston.target - predictions, bins=40, label='Остатки линейной регрессии', color='b', alpha=.5);
ax.set_title("Гистограмма остатков")
ax.legend(loc='best');

png

Если вы используете IPython Notebook, то используйте команду %matplotlib inline для отображения графиков Matplotlib прямо в браузере. Если нет, то используйте f.savefig('myfig.png') для сохранения графика для последующего использования.

Библиотека для построения графиков — Matplotlib, которая не является основной темой данной книги, но имеет отличные возможности для визуализации.Как и раньше, ошибки распределены нормально с нулевым средним значением. Остатки представляют собой ошибки, поэтому этот график также должен приближаться к нормальному распределению. Похоже, что модель хорошо обучена, хотя немного смещена. Давайте посчитаем среднее значение остатков; оно должно быть очень близко к нулю:

mean_residuals = np.mean(residuals)
print("Среднее значение остатков:", mean_residuals)
``````python
import numpy as np
np.mean(boston.target - predictions)

Выходит:

6.0382090193051989e-16

Другой полезный график — график Q-Q (квантиль-квантиль), который можно построить с помощью Scipy, поскольку он предоставляет встроенную функциональность для построения таких графиков:

from scipy.stats import probplot
f = plt.figure(figsize=(7, 5))
ax = f.add_subplot(111)
probplot(boston.target - predictions, plot=ax);
```![png](img/2-2-2.png)

На этом графике наклоненные данные более четко видны по сравнению с тем, что мы видели ранее.

Можно также рассмотреть другие метрики аппроксимации, самыми распространенными являются среднеквадратичная ошибка (Mean Squared Error, MSE) и средняя абсолютная ошибка (Mean Absolute Deviation, MAD). Давайте реализуем эти две метрики на Python. Впоследствии мы будем использовать встроенные метрики scikit-learn для оценки качества регрессионной модели.


```python
def MSE(target, predictions):
    squared_deviation = np.power(target - predictions, 2)
    return np.mean(squared_deviation)
MSE(boston.target, predictions)
21.897779217687496
def MAD(target, predictions):
    absolute_deviation = np.abs(target - predictions)
    return np.mean(absolute_deviation)
MAD(boston.target, predictions)
3.2729446379969396

Как это работает...

Формула вычисления MSE:

$$\frac{1}{n} \sum_{i=1}^{n} (\hat y_i - y_i)^2$$ Вычисление среднего значения квадратического отклонения между прогнозируемым значением и фактическим значением. Это то же самое, что и цель при поиске наилучшего коэффициента корреляции. Теорема Гаусса-Маркова уже доказала, что коэффициенты линейной регрессии являются наилучшим линейным несмещенным оценщиком (BLUE), если условием является то, что ошибочные переменные не коррелированы, имеют нулевое среднее значение и одинаковую дисперсию. В разделе "Исправление недостатков линейной регрессии с помощью岭回归" мы увидим, что происходит, когда наши коэффициенты корреляции являются смещенными оценками.

В разделе "Исправление недостатков линейной регрессии с помощью岭回归" заменим "岭回归" на "ridge regression":

Вычисление среднего значения квадратического отклонения между прогнозируемым значением и фактическим значением. Это то же самое, что и цель при поиске наилучшего коэффициента корреляции. Теорема Гаусса-Маркова уже доказала, что коэффициенты линейной регрессии являются наилучшим линейным несмещенным оценщиком (BLUE), если условием является то, что ошибочные переменные не коррелированы, имеют нулевое среднее значение и одинаковую дисперсию. В разделе "Исправление недостатков линейной регрессии с помощью ridge regression" мы увидим, что происходит, когда наши коэффициенты корреляции являются смещенными оценками.MAD представляет собой среднюю абсолютную ошибку, её формула следующая:

$$\frac{1}{N} \sum_{i=1}^{N} |\hat{y}_t - y_i|$$

При линейной регрессии MAD обычно не используется, но стоит обратить внимание. Почему? Поскольку можно увидеть каждую метрику отдельно и понять, какая из них важнее. Например, используя MSE, большие ошибки получают большее наказание, так как они увеличиваются путём возведения в квадрат.

Ещё есть больше...

Ещё одним моментом, который следует отметить, является то, что коэффициенты корреляции являются случайными величинами, поэтому они имеют распределение. Давайте воспользуемся методом бутстрapping (повторного выбора), чтобы посмотреть на распределение коэффициентов корреляции преступности. Бутстрapping — это распространённый способ обучения параметрам оценки неопределённости:

n_bootstraps = 1000
len_boston = len(boston.target)
subsample_size = np.int(0.5 * len_boston)
subsample = lambda: np.random.choice(
    np.arange(0, len_boston),
    size=subsample_size,
)
coefs = np.ones(n_bootstraps)  # начальное значение коэффициентов установлено равным 1
for i in range(n_bootstraps):
    subsample_idx = subsample()
    subsample_X = boston.data[subsample_idx]
    subsample_y = boston.target[subsample_idx]
    lr.fit(subsample_X, subsample_y)
    coefs[i] = lr.coef_[0]

Можно заметить распределение коэффициентов корреляции в виде гистограммы:

f = plt.figure(figsize=(7, 5))
ax = f.add_subplot(111)
ax.hist(coefs, bins=50, color='b', alpha=.5)
ax.set_title("Гистограмма распределения lr.coef_[0]");
```![png](img/2-2-3.png)

Также мы хотели бы взглянуть на доверительный интервал после повторных экспериментов:

```python
np.percentile(coefs, [2.5, 97.5])

Доверительный интервал указывает, что уровень преступности фактически не влияет на стоимость недвижимости, так как ноль находится внутри доверительного интервала, что свидетельствует о том, что уровень преступности может быть не связан с стоимостью недвижимости.

Замечательно, что метод бутстрapping позволяет получить более точные оценки коэффициентов корреляции, поскольку среднее значение, полученное с помощью этого метода, быстрее сходится к истинному среднему значению.

2.3 Улучшение линейной регрессии с помощью岭回归

В этом разделе будет рассмотрена岭回归。С ней отличается от линейной регрессии тем, что она вводит параметр регуляризации для "сужения" коэффициентов корреляции. Когда данные содержат мультиколлинеарность,岭回归 становится особенно полезной.

Подготовка

Предположим, что мы загружаем набор данных с низким рангом (low effective rank) для сравнения岭回归 и линейной регрессии. Ранг — это количество линейно независимых групп в матрице, полный ранг означает, что для матрицы размером $m \times n$, число линейно независимых групп равно $\text{min}(m,n)$.

Как это сделать...

Сначала создадим набор данных с тремя признаками с использованием make_regression, но его ранг равен двум, поэтому среди трёх признаков два имеют зависимость друг от друга.

from sklearn.datasets import make_regression
reg_data, reg_target = make_regression(n_samples=2000, n_features=3, effective_rank=2, noise=10)
```Сначала обучим обычную линейную регрессию:

```python
import numpy as np
from sklearn.linear_model import LinearRegression
lr = LinearRegression()

def fit_2_regression(lr):
    n_bootstraps = 1000
    coefs = np.ones((n_bootstraps, 3))
    len_data = len(reg_data)
    subsample_size = np.int(0.75 * len_data)
    subsample = lambda: np.random.choice(np.arange(0, len_data), size=subsample_size)

    for i in range(n_bootstraps):
        subsample_idx = subsample()
        subsample_X = reg_data[subsample_idx]
        subsample_y = reg_target[subsample_idx]
        lr.fit(subsample_X, subsample_y)
        coefs[i][0] = lr.coef_[0]
        coefs[i][1] = lr.coef_[1]
        coefs[i][2] = lr.coef_[2]
    %matplotlib inline
    import matplotlib.pyplot as plt
    f, axes = plt.subplots(nrows=3, sharey=True, sharex=True, figsize=(7, 5))
    f.tight_layout()
    
    for i, ax in enumerate(axes):
        ax.hist(coefs[:, i], color='b', alpha=.5)
        ax.set_title("Коэффициент {}".format(i))
        
    return coefs

coefs = fit_2_regression(lr)

png

Теперь снова обучим данные с помощью Ridge и сравним результаты:

from sklearn.linear_model import Ridge
coefs_r = fit_2_regression(Ridge())

png

Результаты двух алгоритмов регрессии кажутся похожими, но это не так. Коэффициенты корреляции при использовании метода Ridge ближе к нулю. Давайте рассмотрим разницу между коэффициентами корреляции обоих методов:

np.mean(coefs - coefs_r, axis=0)

Среднее значение показывает, что коэффициенты корреляции линейной регрессии значительно выше, чем у Ridge. Разница средних значений указывает на скрытую дисперсию в коэффициентах корреляции линейной регрессии. Но какова же польза от использования Ridge? Давайте посмотрим на дисперсию коэффициентов корреляции:```python np.var(coefs, axis=0)




```python
np.var(coefs_r, axis=0)

Дисперсия коэффициентов корреляции при использовании Ridge также значительно меньше. Это известная концепция в машинном обучении — баланс между смещением и дисперсией (Bias-Variance Trade-off). В следующем разделе мы рассмотрим, как настраивать параметры регуляризации Ridge, что является ключевой частью этого баланса.

Как это работает...

Перед тем как рассматривать параметры регуляризации, давайте ещё раз сравним Ridge и линейную регрессию. Как было упомянуто ранее, цель линейной регрессии заключается в минимизации $ {\begin{Vmatrix} \hat y - X \beta \end{Vmatrix}}^2 $.

Цель Ridge заключается в минимизации $ {\begin{Vmatrix} \hat y - X \beta \end{Vmatrix}}^2 + {\begin{Vmatrix} \Gamma X \end{Vmatrix}}^2 $,

где $\Gamma$ представляет собой параметр alpha в Ridge, который равен единичному масштабированному матрице. Пример использует значение по умолчанию. Мы можем вывести параметры Ridge следующим образом:

Ridge()
```Решение для коэффициентов корреляции Ridge имеет вид:
$$\beta = {(X^TX + \Gamma^T \Gamma)}^{-1}X \hat{y}$$
Первая половина формулы имеет то же решение, как и для коэффициента корреляции в линейной регрессии, но с добавлением одного члена $(\Gamma^T \Gamma)$. Матрица $A$, при умножении которой на саму себя и транспонированную версию ($AA^T$), даёт симметричную матрицу, которая является положительно полуопределенной (для любого ненулевого вектора $x$ выполняется условие $x^TAx \geq 0$). Это эквивалентно увеличению большого числа в знаменателе целевой функции линейной регрессии, что приводит к тому, что коэффициент корреляции стремится к нулю. Такое объяснение довольно грубое; для более глубокого понимания рекомендую обратиться к связи SVD (разложение матрицы по сингулярным значениям) и Ridge Regression.```markdown
Первая половина формулы имеет такое же решение, как и для коэффициента корреляции в линейной регрессии, но с добавлением одного члена (\(\Gamma^T \Gamma\)). Матрица \(A\), при умножении которой на саму себя и транспонированную версию (\(AA^T\)), даёт симметричную матрицу, которая является положительно полуопределенной (для любого ненулевого вектора \(x\) выполнено условие \(x^TAx \ge 0\)). Это эквивалентно увеличению большого числа в знаменателе целевой функции линейной регрессии, что приводит к тому, что коэффициент корреляции стремится к нулю. Такое объяснение довольно грубое; для более глубокого понимания рекомендую обратиться к связи SVD (разложение матрицы по сингулярным значениям) и岭回归

# 2.4 Оптимизация параметров岭回归

Когда вы используете модель岭回归 для моделирования, следует учитывать параметр `alpha` в классе `Ridge`.

Например, использование OLS (обычного метода наименьших квадратов) может показать некоторые отношения между двумя переменными; однако после регуляризации с помощью параметра `alpha`, эти отношения могут исчезнуть. При принятии решений важно учитывать эти зависимости.
Первая половина формулы имеет такое же решение, как и для коэффициента корреляции в линейной регрессии, но с добавлением одного члена (\(\Gamma^T \Gamma\)). Матрица \(A\), при умножении которой на саму себя и транспонированную версию (\(AA^T\)), даёт симметричную матрицу, которая является положительно полуопределенной (для любого ненулевого вектора \(x\) выполнено условие \(x^TAx \ge 0\)). Это эквивалентно увеличению большого числа в знаменателе целевой функции линейной регрессии, что приводит к тому, что коэффициент корреляции стремится к нулю. Такое объяснение довольно грубое; для более глубокого понимания рекомендую обратиться к связи SVD (разложение матрицы по сингулярным значениям) и岭回归。

# 2.4 Оптимизация параметров岭回归

Когда вы используете модель岭回归 для моделирования, следует учитывать параметр `alpha` в классе `Ridge`.

Например, использование OLS (обычного метода наименьших квадратов) может показать некоторые отношения между двумя переменными; однако после регуляризации с помощью параметра `alpha`, эти отношения могут исчезнуть. При принятии решений важно учитывать эти зависимости.
Первая половина формулы имеет такое же решение, как и для коэффициента корреляции в линейной регрессии, но с добавлением одного члена (\(\Gamma^T \Gamma\)). Матрица \(A\), при умножении которой на саму себя и транспонированную версию (\(AA^T\)), даёт симметричную матрицу, которая является положительно полуопределенной (для любого ненулевого вектора \(x\) выполнено условие \(x^TAx \ge 0\)). Это эквивалентно увеличению большого числа в знаменателе целевой функции линейной регрессии, что приводит к тому, что коэффициент корреляции стремится к нулю. Такое объяснение довольно грубое; для более глубокого понимания рекомендую обратиться к связи SVD (разложение матрицы по сингулярным значениям) и岭回归。

# 2.4 Оптимизация параметров岭回归

Когда вы используете модель岭回归 для моделирования, следует учитывать параметр `alpha` в классе `Ridge`.

Например, использование OLS (обычного метода наименьших квадратов) может показать некоторые отношения между двумя переменными; однако после регуляризации с помощью параметра `alpha`, эти отношения могут исчезнуть. При принятии решений важно учитывать эти зависимости.
Первая половина формулы имеет такое же решение, как и для коэффициента корреляции в линейной регрессии, но с добавлением одного члена (\(\Gamma^T \Gamma\)). Матрица \(A\), при умножении которой на саму себя и транспонированную версию (\(AA^T\)), даёт симметричную матрицу, которая является положительно полуопределенной (для любого ненулевого вектора \(x\) выполнено условие \(x^TAx \ge 0\)). Это эквивалентно увеличению большого числа в знаменателе целевой функции линейной регрессии, что приводит к тому, что коэффициент корреляции стремится к нулю. Такое объяснение довольно грубое; для более глубокого понимания рекомендую обратиться к связи SVD (разложение матрицы по сингулярным значениям) и岭回归。

# 2.4 Оптимизация параметров岭回归

Когда вы используете модель岭回归 для моделирования, следует учитывать параметр `alpha` в классе `Ridge`.

Например, использование OLS (обычного метода наименьших квадратов) может показать некоторые отношения между двумя переменными; однако после регуляризации с помощью параметра `alpha`, эти отношения могут исчезнуть. При принятии решений важно учитывать эти зависимости.
Первая половина формулы имеет такое же решение, как и для коэффициента корреляции в линейной регрессии, но с добавлением одного члена (\(\Gamma^T \Gamma\)). Матрица \(A\), при умножении которой на саму себя и транспонированную версию (\(AA^T\)), даёт симметричную матрицу, которая является положительно полуопределенной (для любого ненулевого вектора \(x\) выполнено условие \(x^TAx \ge 0\)). Это эквивалентно увеличению большого числа в знаменателе целевой функции линейной регрессии, что приводит к тому, что коэффициент корреляции стремится к нулю. Такое объяснение довольно грубое; для более глубокого понимания рекомендую обратиться к связи SVD (разложение матрицы по сингулярным значениям) и岭回归。

# 2.4 Оптимизация параметров岭回归

Когда вы используете модель岭回归 для моделирования, следует учитывать параметр `alpha` в классе `Ridge`.

Например, использование OLS (обычного метода наименьших квадратов) может показать некоторые отношения между двумя переменными; однако после регуляризации с помощью параметра `alpha`, эти отношения могут исчезнуть. При принятии решений важно учитывать эти зависимости.
```<!-- TEASER_END -->

## Подготовка

Это наш первый пример оптимизации параметров модели, который обычно выполняется с использованием кросс-валидации. В последующих разделах будут рассмотрены более простые способы выполнения этой задачи, но здесь мы будем делать это шаг за шагом для оптимизации岭回归.

В библиотеке scikit-learn параметр $\Gamma$ в岭回归 является параметром `alpha`. Таким образом, вопрос заключается в том, какой параметр `alpha` является оптимальным. Сначала создаем набор данных для регрессии:

```python
from sklearn.datasets import make_regression
reg_data, reg_target = make_regression(n_samples=100, n_features=2, effective_rank=1, noise=10)

Как это сделать...

В модуле linear_models есть объект RidgeCV, представляющий кросс-валидацию岭回归. Этот процесс похож на метод leave-one-out (LOOCV). Он состоит в том, чтобы при обучении оставить одну выборку и использовать её для тестирования.

import numpy as np
from sklearn.linear_model import RidgeCV
rcv = RidgeCV(alphas=np.array([.1, .2, .3, .4]))
rcv.fit(reg_data, reg_target)

После обучения модели, параметр alpha будет оптимальным значением:

rcv.alpha_

Здесь значение 0.1 является оптимальным. Чтобы найти более точное значение рядом с 0.1, можно использовать следующий подход:

rcv = RidgeCV(alphas=np.array([.08, .09, .1, .11, .12]))
rcv.fit(reg_data, reg_target)
```    RidgeCV(alphas=array([ 0.08,  0.09,  0.1 ,  0.11,  0.12]), cv=None,
            fit_intercept=True, gcv_mode=None, normalize=False, scoring=None,
            store_cv_values=False)




```python
rcv.alpha_
0.080000000000000002

Можно продолжать этот процесс до достижения желаемой точности. Здесь демонстрация ограничивается указанными значениями, но в дальнейшем будут рассмотрены более эффективные методы.## Как это работает...

Приведенный выше пример довольно прост, но давайте рассмотрим причины такого подхода и как определить оптимальное значение. На каждом шаге кросс-валидации качество модели оценивается с помощью ошибки на тестовых данных. По умолчанию используется квадратичная ошибка. Подробнее см. раздел Еще подробнее....

Можно заставить объект RidgeCV хранить данные кросс-валидации, чтобы визуализировать весь процесс:

alphas_to_test = np.linspace(0.0001, 0.05)
rcv3 = RidgeCV(alphas=alphas_to_test, store_cv_values=True)
rcv3.fit(reg_data, reg_target)
RidgeCV(alphas=array([ 0.0001 ,  0.00112,  0.00214,  0.00316,  0.00417,  0.00519,
        0.00621,  0.00723,  0.00825,  0.00927,  0.01028,  0.0113 ,
        0.01232,  0.01334,  0.01436,  0.01538,  0.01639,  0.01741,
        0.01843,  0.01945,  0.02047,  0.02149,  0.0225 ,  0.02352,
        0.02454,  0.02556...4185,
        0.04287,  0.04389,  0.04491,  0.04593,  0.04694,  0.04796,
        0.04898,  0.05   ]),
    cv=None, fit_intercept=True, gcv_mode=None, normalize=False,
    scoring=None, store_cv_values=True)

Вы заметите, что мы проверяем значения от 0.0001 до 0.05, используя 50 точек. Поскольку мы установили store_cv_values равным True, мы можем видеть результаты для каждого значения альфа:```python rcv3.cv_values_.shape





(100, 50)



Используя набор данных из 100 образцов, мы получаем 50 различных значений `alpha`. Мы можем увидеть 50 значений ошибки, минимальное среднее значение ошибки соответствует оптимальному значению `alpha`:


```python
smallest_idx = rcv3.cv_values_.mean(axis=0).argmin()
alphas_to_test[smallest_idx]
0.014357142857142857

Теперь вопрос сводится к тому, "Подтверждает ли RidgeCV наш выбор?" Можно получить значение alpha следующим образом:

rcv3.alpha_
0.014357142857142857

Для более наглядной визуализации можно построить график зависимости ошибки от значений alpha. Нарисуем графики для 50 проверенных значений alpha:

%matplotlib inline
import matplotlib.pyplot as plt
f, ax = plt.subplots(figsize=(7, 5))
ax.set_title("Различные значения $\\alpha$")

xy = (alphas_to_test[smallest_idx], rcv3.cv_values_.mean(axis=0)[smallest_idx])
xytext = (xy[0] + .01, xy[1] + .1)

ax.annotate('Выбранное $\\alpha$', xy=xy, xytext=xytext,
            arrowprops=dict(facecolor='black', shrink=0, width=0)
            )
ax.plot(alphas_to_test, rcv3.cv_values_.mean(axis=0));
```![png](img/2-4-1.png)


## Есть ещё больше...


Если мы хотим использовать другие функции ошибок для создания пользовательских метрик, это тоже возможно. Ранее мы рассматривали MAD (среднее абсолютное отклонение) как одну такую функцию. Мы можем использовать её для оценки модели. В первую очередь нам нужно определить функцию потерь:


```python
def MAD(target, prediction):
    absolute_deviation = np.abs(target - prediction)
    return absolute_deviation.mean()
```После того как мы определили функцию потерь, мы можем воспользоваться функцией `make_scorer` из модуля `sklearn`. Это позволяет стандартизировать нашу пользовательскую функцию, чтобы объекты scikit-learn могли её использовать. Кроме того, поскольку это функция потерь, а не метрика качества, которая должна максимизироваться, то нам нужно преобразовать задачу минимизации в задачу максимизации с помощью `sklearn`:

```python
import sklearn
MAD = sklearn.metrics.make_scorer(MAD, greater_is_better=False)
rcv4 = RidgeCV(alphas=alphas_to_test, store_cv_values=True, scoring=MAD)
rcv4.fit(reg_data, reg_target)
smallest_idx = rcv4.cv_values_.mean(axis=0).argmin()
alphas_to_test[smallest_idx]
0.05

2.5 Лассо регуляризация

Метод лассо (least absolute shrinkage and selection operator, минимальное абсолютное сжатие и оператор выбора) очень похож на метод регрессии с岭回归和LARS(最小角度回归)。与岭回归一样,它也通过添加惩罚项来解决特征之间的多重共线性问题。与LARS类似,它可以用于参数选择,并且通常会产生稀疏的相关系数向量。

Подготовка

Регрессия с岭回归并不是万能药。有时需要使用LASSO回归进行建模。本主题将使用不同的损失函数,因此需要相应的评估方法。

Как это сделать...

Сначала создаем набор данных с помощью функции make_regression:

from sklearn.datasets import make_regression
reg_data, reg_target = make_regression(n_samples=200, n_features=50 Yöntemleri, n_informative=5, noise=5)

Затем импортируем объект lasso:

from sklearn.linear_model import Lasso
lasso = Lasso()
```Объект `lasso` имеет множество параметров, но наиболее важным является параметр `alpha`, который используется для настройки штрафной функции лассо. Этот параметр будет подробно рассмотрен в разделе **Как это работает...**. Сейчас мы используем значение по умолчанию `1`. Также, как и в случае с岭回归, если установить его равным `0`, то `lasso` становится обычной линейной регрессией:

岭回归 -> регрессия```python
lasso.fit(reg_data, reg_target)

Рассмотрим ещё раз количество ненулевых коэффициентов корреляции:

import numpy as np
np.sum(lasso.coef_ != 0)
9
lasso_0 = Lasso(0)
lasso_0.fit(reg_data, reg_target)
np.sum(lasso_0.coef_ != 0)
d:\programfiles\Miniconda3\lib\site-packages\IPython\kernel\__main__.py:2: UserWarning: With alpha=0, this algorithm does not converge well. You are advised to use the LinearRegression estimator
  from IPython.kernel.zmq import kernelapp as app
d:\programfiles\Miniconda3\lib\site-packages\sklearn\linear_model\coordinate_descent.py:432: UserWarning: Coordinate descent with alpha=0 may lead to unexpected results and is discouraged.
  positive
  
500

Как мы и ожидали, если использовать линейную регрессию, ни один коэффициент корреляции не становится равным нулю. Кроме того, если вы запустите этот код, scikit-learn выдаст предупреждение, как показано выше.

Как это работает...

Для линейной регрессии мы минимизируем сумму квадратов остатков. В случае регрессии LASSO мы также минимизируем сумму квадратов остатков, но добавляем штраф, который приводит к сжатости данных. Это можно представить следующим образом:

$$ \sum e_i + \lambda \left| \beta \right|_1 $$

Ещё одно выражение для минимизации суммы квадратов остатков:

$$ RSS(\beta), где \left| \beta \right|_1 < \beta $$Это ограничение делает данные сжатыми. Ограничение в регрессии LASSO создаёт гиперкуб, где коэффициенты корреляции являются осями, что означает, что большинство точек находятся на вершинах, где коэффициенты корреляции равны нулю. В то время как в регрессии Ridge ограничение представляет собой гиперплоскость, так как его ограничение является нормой L2, которая имеет одно ограничение, но даже при наличии ограничений коэффициенты корреляции никогда не становятся равными нулю.### Кросс-валидация LASSO

В вышеприведённой формуле выбор правильного значения (\lambda) (или alpha в Lasso scikit-learn, хотя в книге используется (\lambda)) является ключевым моментом. Мы можем установить его самостоятельно или получить оптимальное значение через кросс-валидацию:

from sklearn.linear_model import LassoCV
lassocv = LassoCV()
lassocv.fit(reg_data, reg_target)

Атрибут lassocv позволяет определить наиболее подходящее значение (\lambda):

lassocv.alpha_

Вы можете заметить вычисленные коэффициенты корреляции:

lassocv.coef_[:5]

После применения ближайших параметров lassocv имеет 29 ненулевых коэффициентов корреляции:

np.sum(lassocv.coef_ != 0)

Выбор признаков с помощью LASSO

LASSO часто используется для выбора признаков для других методов. Например, вы можете использовать регрессию LASSO для получения подходящих признаков, а затем использовать эти признаки в других алгоритмах.

Для получения нужных признаков вам потребуется создать вектор столбцов с ненулевыми коэффициентами корреляции, а затем применить этот вектор к другому алгоритму:

mask = lassocv.coef_ != 0
new_reg_data = reg_data[:, mask]
new_reg_data.shape

2.6 Линейная регрессия минимального угла (LARS)Если бы Bradley Efron, Trevor Hastie, Iain Johnstone и Robert Tibshirani не открыли его [1], то однажды кто-то мог бы придумать LARS (Least Angle Regression, линейная регрессия минимального угла), используя вдохновение от метода Гаусса-Жордана (гауссовское исключение), представленного Gilbert Strangом.

Подготовка

LARS — это метод регрессии, предназначенный для решения задач высокой размерности, когда $p >> n$, где $p$ представляет количество колонок или признаков, а $n$ — количество образцов данных.

Как это сделать...

Сначала импортируем необходимые объекты. В данном случае мы используем набор данных, содержащий 200 образцов и 500 признаков. Мы также установили низкий уровень шума и небольшое количество информативных признаков:

import numpy as np
from sklearn.datasets import make_regression
reg_data, reg_target = make_regression(n_samples=200, n_features=500, n_informative=10, noise=2)

Имея 10 информативных признаков, нам следует установить 10 ненулевых коэффициентов корреляции для LARS. Хотя мы можем не знать точное количество информативных признаков заранее, но для эксперимента это вполне приемлемо:

from sklearn.linear_model import Lars
lars = Lars(n_nonzero_coefs=10)
lars.fit(reg_data, reg_target)

Можно проверить сумму ненулевых коэффициентов корреляции LARS:

np.sum(lars.coef_ != 0)

Результат:

10

Проблема заключается в том, почему меньшее количество признаков становится более эффективным. Чтобы это показать, обучим две модели LARS с половиной количества признаков — одна модель будет иметь 12 ненулевых коэффициентов корреляции, а другая — значение по умолчанию. Мы используем 12, поскольку у нас есть некоторое представление о количестве важных признаков, но мы можем не точно знать его.```python train_n = 100 lars_12 = Lars(n_nonzero_coefs=12) lars_12.fit(reg_data[:train_n], reg_target[:train_n])

lars_500 = Lars() # По умолчанию равно 500 lars_500.fit(reg_data[:train_n], reg_target[:train_n])


Теперь давайте посмотрим, как эти модели работают на данных обучения:

```python
np.mean(np.power(reg_target[train_n:] - lars.predict(reg_data[train_n:]), 2))

np.mean(np.power(reg_target[train_n:] - lars_12.predict(reg_data[train_n:]), 2))

np.mean(np.power(reg_target[train_n:] - lars_500.predict(reg_data[train_n:]), 2))

Просмотрите эту группу результатов; ошибки тестового набора значительно выше. Проблема переобучения заключается именно здесь; обычно сложно найти модель, которая хорошо аппроксимирует тренировочный набор при большом количестве признаков, но переобучение является ещё большим проблемой.

Как это работает...

LARS выбирает характеристики, повторно выбрав те, которые связаны с изменениями остатка. Графически говоря, связь фактически представляет собой минимальный угол между характеристикой и остатками; отсюда и название LARS.

После выбора первой характеристики, LARS продолжает двигаться в направлении минимального угла до тех пор, пока следующая характеристика не станет так же сильно связана с остатками. Затем LARS начинает двигаться в направлении углов, образованных двумя характеристиками вместе. Это можно наглядно представить на графике:

%matplotlib inline
import matplotlib.pyplot as plt
```def unit(*args):
    squared = map(lambda x: x**2, args)
    distance = sum(squared) ** (0.5)
    return map(lambda x: x / distance, args)


```f, ax = plt.subplots(nrows=3, figsize=(5, 10))
plt.tight_layout()
ax[0].set_ylim(0, 1.1)
ax[0].set_xlim(0, 1.1)

x, y = unit(1, 0.02)
ax[0].arrow(0, 0, x, y, edgecolor='black', facecolor='black')
ax[0].text(x + .05, y + .05, r"$x_1$")

x, y = unit(.5, 1)
ax[0].arrow(0, 0, x, y, edgecolor='black', facecolor='black')
ax[0].text(x + .05, y + .05, r"$x_2$")

x, y = unit(1, .45)
ax[0].arrow(0, 0, x, y, edgecolor='black', facecolor='black')
ax[0].text(x + .05, y + .05, r"$y$")

ax[0].set_title("Без шагов")

# Шаг 1
ax[1].set_title("Шаг 1")
ax[1].set_ylim(0, 1.1)
ax[1].set_xlim(0, 1.1)

x, y = unit(1, 0.02)
ax[1].arrow(0, 0, x, y, edgecolor='black', facecolor='black')
ax[1].text(x + .05, y + .05, r"$x_1$")

x, y = unit(.5, 1)
ax[1].arrow(0, 0, x, y, edgecolor='black', facecolor='black')
ax[1].text(x + .05, y + .05, r"$x_2$")

x, y = unit(.5, 1)
ax[1].arrow(.5, 0.01, x, y, ls='dashed', edgecolor='black', facecolor='black')
ax[1].text(x + .5 + .05, y + .01 + .05, r"$x_2$")

ax[1].arrow(0, 0, .47, .01, width=.0015, edgecolor='black', facecolor='black')
ax[1].text(.47 - .15, .01 + .03, "Шаг 1")

x, y = unit(1, .45)
ax[1].arrow(0, 0, x, y, edgecolor='black', facecolor='black')
ax[1].text(x + .05, y + .05, r"$y$")

# Шаг 2
ax[2].set_title("Шаг 2")
ax[2].set_ylim(0, 1.1)
ax[2].set_xlim(0, 1.1)

x, y = unit(1, 0.02)
ax[2].arrow(0, 0, x, y, edgecolor='black', facecolor='black')
ax[2].text(x + .05, y + .05, r"$x_1$")

x, y = unit(.5, 1)
ax[2].arrow(0, 0, x, y, edgecolor='black', facecolor='black')
ax[2].text(x + .05, y + .05, r"$x_2$")

x, y = unit(.5, 1)
ax[2].arrow(.5, 0.01, x, y, ls='dashed', edgecolor='black', facecolor='black')
ax[2].text(x + .5 + .05, y + .01 + .05, r"$x_2$")

ax[2].arrow(0, 0, .47, .01, width=.0015, edgecolor='black', facecolor='black')
ax[2].text(.47 - .15, .01 + .03, "Шаг 1")

## Шаг 2
x, y = unit(1, .45)
ax[2].arrow(.5, .02, .4, .35, width=.0015, edgecolor='black', facecolor='black')
ax[2].text(x, y - .1, "Шаг 2")

x, y = unit(1, .45)
ax[2].arrow(0, 0, x, y, edgecolor='black', facecolor='black')
ax[2].text(x + .05, y + .05, r"$y$");
```![png](img/2-6-1.png)

Конкретный процесс состоит в том, что мы перемещаем \( x2 \) в направлении \( x1 \) до точки, где скалярное произведение между \( x1 \) и \( y \) равно скалярному произведению между \( x1 \) и \( y \). После достижения этой точки мы продолжаем движение в направлении, образованном половиной угла между \( x1 \) и \( x2 \).

## Есть ещё больше...

Как и в случае использования кросс-валидации для оптимизации модели линейной регрессии, мы можем применять кросс-валидацию к LARS:

```python
from sklearn.linear_model import LarsCV
lcv = LarsCV()
lcv.fit(reg_data, reg_target)
d:\Miniconda3\lib\site-packages\sklearn\linear_model\least_angle.py:285: ConvergenceWarning: Regressors in active set degenerate. Dropping a regressor, после 168 итераций, то есть при alpha=2.278e-02, с активным набором из 132 регрессоров, и минимальным элементом холецкого разложения равным 6.144e-08
  ConvergenceWarning)
d:\Miniconda3\lib\site-packages\sklearn\linear_model\least_angle.py:285: ConvergenceWarning: Regressors in active set degenerate. Dropping a regressor, после 168 итераций, то есть при alpha=2.105e-02, с активным набором из 132 регрессоров, и минимальным элементом холецкого разложения равным 9.771e-08
  ConvergenceWarning)



LarsCV(copy_X=True, cv=None, eps=2.2204460492503131e-16, fit_intercept=True,
       max_iter=500, max_n_alphas=1000, n_jobs=1, normalize=True,
       precompute='auto', verbose=False)

Кросс-валидация помогает нам определить оптимальное количество ненулевых коэффициентов корреляции. Валидация показывает следующее:

np.sum(lcv.coef_ != 0)
```    43



Честно говоря, пока не до конца понял суть LARS, но обязательно вернусь к этому вопросу позже и переведу оригинальный текст.

[1] Efron, Bradley; Hastie, Trevor; Johnstone, Iain и Tibshirani, Robert (2004). "[Метод наименьшего угла](http://web.stanford.edu/~hastie/Papers/LARS/LeastAngle_2002.pdf)". Annals of Statistics 32(2): c. 407499. doi:10.1214/009053604000000067. MR 2060166.


# 2.7 Обработка задач классификации с помощью линейных методов — логистическая регрессия

На самом деле, линейные модели также могут использоваться для решения задач классификации. Для этого линейная модель обучается на данных, представляющих собой распределение вероятностей определённого типа, а затем применяется функция порогового значения для определения принадлежности объекта к одной из категорий.

<!-- TEASER_END -->

## Подготовка

Здесь используется классический логистический функционал. Очень простая функция:

$$f(x) = \frac{1}{1 + e^{-t}}$$

Его графическое представление показано ниже:

```python
import numpy as np
%matplotlib inline
import matplotlib.pyplot as plt
f, ax = plt.subplots(figsize=(10, 5))
rng = np.linspace(-5, 5)
log_f = np.apply_along_axis(lambda x:1 / (1 + np.exp(-x)), 0, rng)
ax.set_title("Логистическая функция между [-5, 5]")
ax.plot(rng, log_f);

png

Давайте создадим набор данных с помощью метода make_classification, чтобы выполнить классификацию:

from sklearn.datasets import make_classification
X, y = make_classification(n_samples=1000, n_features=4)

Как это сделать...Использование объекта LogisticRegression аналогично использованию других линейных моделей:

from sklearn.linear_model import LogisticRegression
lr = LogisticRegression()

Мы будем использовать первые 200 данных в качестве тренировочного набора, а последние 200 — как тестовый набор. Поскольку это случайный набор данных, использование последних 200 данных допустимо. Однако если вы работаете с данными, имеющими некоторую структуру (например, ваш набор данных представляет собой временной ряд), то такой подход был бы неправильным.

X_train = X[:-200]
X_test = X[-200:]
y_train = y[:-200]
y_test = y[-200:]

В более поздних разделах этой книги мы подробнее рассмотрим кросс-валидацию. Здесь нам достаточно просто обучить модель логистической регрессией. Мы будем обращать внимание на прогнозы, сделанные на основе тренировочного набора, так же как и на основе тестового набора. Часто полезно сравнивать правильность прогнозов на двух наборах данных; обычно вы получаете лучшие результаты на тренировочном наборе, а также важно знать процент ошибок модели при прогнозировании на тестовом наборе.

lr.fit(X_train, y_train)
y_train_predictions = lr.predict(X_train)
y_test_predictions = lr.predict(X_test)

Теперь, когда у нас есть прогнозы, давайте посмотрим, насколько они точны. В данном случае мы просто посмотрим на долю правильных ответов; далее мы подробно рассмотрим методы оценки производительности классификаторов.Вычисление простое: число правильных ответов делится на общее количество примеров:

(y_train_predictions == y_train).sum().astype(float) / y_train.shape[0]
(y_test_predictions == y_test).sum().astype(float) / y_test.shape[0]

Как видно, правильность прогнозов на тестовом наборе почти такая же, как и на тренировочном наборе. Однако в реальной жизни часто бывает заметна большая разница.

Теперь вопрос заключается в том, как преобразовать логистическую функцию в метод классификации. Сначала линейная регрессия стремится найти линейное уравнение, которое аппроксимирует среднее значение зависимой переменной Y при данном значении независимых переменных X, то есть E(Y|X) = xβ. Здесь значения Y представляют собой вероятность того или иного типа события. Таким образом, задача классификации сводится к решению E(p|X) = xβ. Затем, если пороговое значение определено, будет выполнено Logit(p) = Xβ. Эта идея может быть расширена до различных видов регрессий, таких как процесс Пуассона (Poisson).

ДополнительноДальше вы обязательно встретите следующие случаи. Одним из них является ситуация, когда один тип имеет различный вес по сравнению с другими; например, один тип может иметь очень высокий вес, равный 99 %. Такое случается часто в задачах классификации. Классическим примером является детекция мошенничества с кредитными картами, где большинство транзакций являются легитимными, но затраты на различные типы ошибочных классификаций могут сильно отличаться.Предположим, что мы хотим создать задачу классификации, где тип y имеет невзвешенный вес 95%, и посмотрим, как базовая модель логистической регрессии справится с такой задачей:

X, y = make_classification(n_samples=5000, n_features=4, weights=[.95])
sum(y) / (len(y) * 1.) # проверка невзвешенного типа
X_train = X[:-500]
X_test = X[-500:]
y_train = y[:-500]
y_test = y[-500:]

lr.fit(X_train, y_train)
y_train_predictions = lr.predict(X_train)
y_test_predictions = lr.predict(X_test)

Теперь давайте посмотрим, как наша модель обучилась:

(y_train_predictions == y_train).sum().astype(float) / y_train.shape[0]
(y_test_predictions == y_test).sum().astype(float) / y_test.shape[0]
(y_test[y_test == 1] == y_test_predictions[y_test == 1]).sum().astype(float) / y_test[y_test == 1].shape[0]

Результаты выглядят неплохо, но это говорит о том, что если мы предсказываем транзакцию как нормальную (или тип 0), то у нас около 95% шансов правильно предсказать. Однако, если мы захотим посмотреть, как модель предсказывает тип 1, то результаты могут оказаться хуже.

Если мы больше заботимся о фальшивых транзакциях по сравнению с обычными, то это зависит от бизнес-правил, и мы можем изменить вес правильных и неправильных предсказаний.Обычно вес фальшивых транзакций относительно обычных пропорционален обратному отношению между весами типов в тренировочном наборе данных. Но поскольку нам важнее качество предсказания фальшивых транзакций, давайте используем метод переобучения (oversampling) для представления этих весов.

lr = ЛогистическаяРегрессия(class_weight={0: .15, 1: .85})
lr.fit(X_train, y_train)
lr = логистическая_регрессия(class_weight={0: .15, 1: .85})
lr.fit(X_train, y_train)
```    Логистическая регрессия (C=1.0, class_weight={0: 0.15, 1: 0.85}, dual=False,
              fit_intercept=True, intercept_scaling=1, max_iter=100,
              multi_class='ovr', penalty='l2', random_state=None,
              solver='liblinear', tol=0.0001, verbose=0)



Давайте снова сделаем прогноз:


```python
y_train_predictions = lr.predict(X_train)
y_test_predictions = lr.predict(X_test)
(y_test[y_test==1] == y_test_predictions[y_test==1]).sum().astype(float) / y_test[y_test==1].shape[0]
0.7083333333333334

Но какой ценой? Давайте посмотрим:

(y_test_predictions == y_test).sum().astype(float) / y_test.shape[0]
0.94

Как видите, точность снизилась на 3%. Подходит ли это вам, зависит от вашего вопроса. Если стоимость ошибочной оценки очень высока, то она может компенсировать затраты на её выявление.

2.8 Байесовская регрессия с ограничением

В разделе "Улучшение линейной регрессии с помощью岭回归" мы рассмотрели ограничения оптимизации в Ridge Regression. Мы также представили байесовское объяснение априорного распределения коэффициентов корреляции, которое сильно влияет на априорное распределение, обычно имеющее среднее значение 0.

Теперь давайте продемонстрируем, как использовать эту интерпретацию с помощью scikit-learn.

Подготовка

Байесовская версия Ridge Regression и Lasso Regression могут быть интерпретированы с точки зрения байесовской теории, что противоположно частотному подходу. Scikit-learn реализует только байесовскую версию Ridge Regression, но в разделе "Как это работает..." мы сравним эти две методики.Сначала создадим набор данных для регрессии:

from sklearn.datasets import make_regression
X, y = make_regression(n_samples=1000, n_features=10, n_informative=2, noise=20)

Как это сделать...

Мы можем загрузить байесовскую версию Ridge Regression и обучить модель:

from sklearn.linear_model import BayesianRidge
br = BayesianRidge()

Есть два набора коэффициентов корреляции — alpha_1 / alpha_2 и lambda_1 / lambda_2. Здесь alpha_* являются гиперпараметрами $\alpha$ априорного распределения, а lambda_* — гиперпараметрами $\lambda$ априорного распределения.

Сначала обучим модель без изменения параметров:

br.fit(X, y)
br.coef_
array([-1.39241213,  0.14671513, -0.08150797, 37.50250891,
        0.21850082, -0.78482779, -0.26717555, -0.71319956,
        0.7926308 ,  5.74658302])

Теперь мы будем корректировать гиперпараметры, обратив внимание на изменения коэффициентов корреляции:

br_alphas = BayesianRidge(alpha_1=10, lambda_ Yöntem=10)
br_alphas.fit(X, y)
br_alphas.coef_
array([ -1.38807423,   0.14050794,  -0.08309391,  37.3032803 ,
         0.2254332 ,  -0.77031801,  -0.27005478,  -0.71632657,
         0.78501276,   5.71928608])

Как это работает...

Поскольку используется байесовская регрессия с岭回归,мы предполагаем, что априорное распределение ошибок и параметра $\alpha$ имеют $\Gamma$-распределение.

$\Gamma$-распределение представляет собой очень гибкую вероятностную функцию. Различные формы параметров и масштабов $\Gamma$-распределения приводят к различным формам. 1e-06 является значением по умолчанию для параметра формы в scikit-learn для BayesianRidge.

import matplotlib.pyplot as plt
%matplotlib inline

from scipy.stats import gamma
import numpy as np

form = lambda x, y: "loc={}, scale={}".format(x, y)
g = lambda x, y=1e-06, z=1e-06: gamma.pdf(x, y, z)
g2 = lambda x, y=1e-06, z=1: gamma.pdf(x, y, z)
g3 = lambda x, y=1e-06, z=2: gamma.pdf(x, y, z)
rng = np.linspace(0, 5)
f, ax = plt.subplots(figsize=(8, 5))
```ax.plot(rng, list(map(g, rng)), label=form(1e-06, 1e-06), color='r')
ax.plot(rng, list(map(g2, rng)), label=form(1e-06, 1), color='g')
ax.plot(rng, list(map(g3, rng)), label=form(1e-06, 2), color='b')
ax.set_title("Различные формы распределения Гамма")
ax.legend();

Вы заметите, что коэффициенты корреляций в конечном итоге сжимаются до нуля, особенно когда значение параметра формы очень маленькое.

Дополнительно...

Как я уже упомянул ранее, существует также байесовское объяснение лассо-регрессии. Мы рассматриваем предположительное распределение как функцию от коэффициентов корреляций; они сами являются случайными величинами. Для лассо-регрессии мы выбираем распределение, которое может порождать ноль, например двойное экспоненциальное распределение (Double Exponential Distribution, также известное как Laplace distribution).

from scipy.stats import laplace
form = lambda x, y: "loc={}, scale={}".format(x, y)
g = lambda x: laplace.pdf(x)
rng = np.linspace(-5, 5)
f, ax = plt.subplots(figsize=(8, 5))

ax.plot(rng, list(map(g, rng)), color='r')
ax.set_title("Пример двойного экспоненциального распределения");
```![png](img/2-8-2.png)

Обратите внимание на вершину в точке x = 0. Это приведёт к корреляционному коэффициенту ошибок, равному нулю. Управление гиперпараметрами может также создать ситуации с корреляционным коэффициентом, равным нулю, что зависит от конкретной задачи.

# 2.10 Обучение с использованием градиентного бустингаГрадиентный бустинг регрессии (Gradient Boosting Regression, GBR) представляет собой метод обучения, основанный на анализе ошибок модели. В основе этого подхода лежит идея объединения множества слабых моделей для создания более мощной модели. Две важные особенности следует отметить:

- Каждая слабая модель имеет ограниченную производительность, но их совместное использование позволяет достичь высокой точности.
- Эти модели применяются последовательно, то есть каждая следующая модель обучается на ошибках предыдущей.

<!-- TEASER_END -->

## Подготовка

Для демонстрации GBR используем базовый набор данных для регрессии.


```python
import numpy as np
from sklearn.datasets import make_regression
X, y = make_regression(n_samples=1000, n_features=2, noise=10)

Как это сделать...

GBR можно рассматривать как интегрированную модель, так как он представляет собой интеграцию нескольких слабых моделей для создания более мощной модели.

from sklearn.ensemble import GradientBoostingRegressor as GBR
gbr = GBR()
gbr.fit(X, y)
gbr_preds = gbr.predict(X)

Очевидно, здесь используется несколько моделей, но сейчас мы рассмотрим простую реализацию. Теперь сравним её с базовой моделью регрессии.

from sklearn.linear_model import LinearRegression
lr = LinearRegression()
lr.fit(X, y)
lr_preds = lr.predict(X)
```Сравнивая эти две модели, давайте посмотрим, как GBR работает лучше линейной регрессии. Для создания графиков можно использовать ту же процедуру, которая была описана в главе о нормальном распределении случайных процессов. Начнём с вычислений ошибок:```python
gbr_residuals = y - gbr_preds
lr_residuals = y - lr_preds
%matplotlib inline
from matplotlib import pyplot as plt
f, ax = plt.subplots(figsize=(7, 5))
f.tight_layout()
ax.hist(gbr_residuals, bins=20, label='GBR ошибки', color='b', alpha=.5);
ax.hist(lr_residuals, bins=20, label='ЛР ошибки', color='r', alpha=.5);
ax.set_title("Ошибки GBR против ЛР")
ax.legend(loc='best');

png

Похоже, что GBR лучше всего подходит для прогнозирования, хотя различия могут быть незначительными. Давайте сравним их с помощью доверительного интервала (confidence interval, CI) на уровне 95%.

np.percentile(gbr_residuals, [2.5, 97.5])
np.percentile(lr_residuals, [2.5, 97.5])

Доверительный интервал GBR меньше, данные более сконцентрированы, поэтому его прогнозирующая способность лучше; мы также можем внести некоторые изменения в алгоритм GBR для улучшения качества модели. Ниже приведён пример демонстрации этого процесса, а затем будет рассмотрена методика оптимизации:

n_estimators = np.arange(100, 1100, 350)
gbrs = [GBR(n_estimators=n_estimator) for n_estimator in n_estimators]
residuals = {}
for i, gbr in enumerate(gbrs):
    gbr.fit(X, y)
    residuals[gbr.n_estimators] = y - gbr.predict(X)
f, ax = plt.subplots(figsize=(7, 5))
f.tight_layout()
colors = {800:'r', 450:'g', 100:'b'}
for k, v in residuals.items():
    ax.hist(v, bins=20, label='n_estimators: %d' % k, color=colors[k], alpha=.5);
ax.set_title("Остатки при различных количествах оценщиков")
ax.legend(loc='best');

График выглядит немного запутанным, но всё же можно заметить, что с увеличением количества оценщиков, ошибка снижается. Однако это не всегда так. Во-первых, мы не провели кросс-валидацию, во-вторых, с увеличением количества оценщиков время обучения также возрастает. В данном случае это ещё не проблема, но если объём данных увеличится в два или три раза, то вопрос становится более актуальным.## Как это работает...

В примере выше первый параметр n_estimators указывает количество используемых алгоритмов обучения в GBR. Обычно, если ваше оборудование имеет лучшие характеристики, вы можете установить значение n_estimators больше, что улучшит качество модели. Также стоит отметить несколько других параметров.

Перед тем как оптимизировать остальные параметры, рекомендуется сначала настроить параметр max_depth. Поскольку каждый алгоритм обучения представляет собой дерево решений, параметр max_depth определяет количество уровней, которое генерируется деревом. Выбор правильного количества уровней может лучше подогнать модель под данные, а слишком большое количество уровней может привести к переобучению.

Параметр loss определяет функцию потерь, которая напрямую влияет на ошибку. По умолчанию используется значение ls, что означает метод наименьших квадратов (least squares). Есть также другие варианты, такие как минимальная абсолютная величина ошибки, Huber loss и функции потерь для квартилей (quantiles).

Опубликовать ( 0 )

Вы можете оставить комментарий после Вход в систему

1
https://api.gitlife.ru/oschina-mirror/wizardforcel-sklearn-cb.git
git@api.gitlife.ru:oschina-mirror/wizardforcel-sklearn-cb.git
oschina-mirror
wizardforcel-sklearn-cb
wizardforcel-sklearn-cb
master