6 Полиномиальная регрессия и обобщение модели

машинное обучение

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

1 Алгоритм полиномиальной регрессии

1.1 Анализ

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

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

import numpy as np 
import matplotlib.pyplot as plt

# 模拟数据集
x = np.random.uniform(-3, 3, size=100)
X = x.reshape(-1, 1)
y = 0.5 * x**2 + x + 2 + np.random.normal(0, 1, 100)

plt.scatter(x, y)
plt.show()

Распределение данных показано на рисунке ниже:

  1. Если используется алгоритм линейной регрессии, то:
from sklearn.linear_model import LinearRegression

lin_reg = LinearRegression()
lin_reg.fit(X, y)
y_predict = lin_reg.predict(X)

plt.scatter(x, y)
plt.plot(x, y_predict, color='r')
plt.show()

Как показано на рисунке ниже, видно, что степень подгонки не очень хорошая.

  1. Добавить полиномиальную функцию
X2 = np.hstack([X, X**2]) # 添加了x^2的特征
lin_reg2 = LinearRegression()
lin_reg2.fit(X2, y)
y_predict2 = lin_reg2.predict(X2)

# 可以求出系数
lin_reg2.coef_  #array([ 0.99870163,  0.54939125])
lin_reg2.intercept_  # 1.8855236786516001

plt.scatter(x, y)
plt.plot(np.sort(x), y_predict2[np.argsort(x)], color='r')
plt.show()

График после подгонки выглядит следующим образом, полиномиальная подгонка лучше

1.2 Полиномиальная регрессия в scikit-learn

scikit-learn предоставляет класс PolynomialFeatures для полиномиальной регрессии.

from sklearn.preprocessing import PolynomialFeatures
poly = PolynomialFeatures(degree=2)
poly.fit(X)
X2 = poly.transform(X)
X2.shape #(100, 3)

# 使用线性回归算法
lin_reg2 = LinearRegression()
lin_reg2.fit(X2, y)
y_predict2 = lin_reg2.predict(X2)

lin_reg2.coef_ # array([ 0.        ,  0.9460157 ,  0.50420543])
lin_reg2.intercept_ # 2.1536054095953823

Степень параметра в методе построения PolynomialFeatures указывает, сколько полиномов можно построить, например:

Если функция толькоx_1, степень = 2, означаетx_1Наибольший полином имеет степень 2, соответственно1,x_1,x_1^2, эта функция становится 3

Если функция имеетx_1,x_2Два, степень = 3, означаетx_1,x_2Наибольший полином имеет степень 3, соответственно1,x_1,x_2, x_1^2,x_2^2,x_1x_2,x_1^3,x_2^3,x_1^2x_2,x_1x_2^2, эта функция становится 10

Таким образом, процесс использования полиномов можно обобщить в виде следующих шагов:

  1. Используйте PolynomialFeatures(степень=?) для сопоставления полиномов, чтобы сгенерировать объекты X, содержащие полиномы.
  2. Нормализуйте данные, потому что, если степень очень велика, например, 100, 10 и 10, разница в 100-й степени очень велика, поэтому данные необходимо нормализовать.
  3. Наконец, алгоритм линейной регрессии используется для получения значения коэффициента, который является окончательной моделью.

1.3 Pipeline

Для шагов, описанных выше, в scikit_learn есть класс, который был инкапсулирован для нас, а именно Pipeline.

x = np.random.uniform(-3, 3, size=100)
X = x.reshape(-1, 1)
y = 0.5 * x**2 + x + 2 + np.random.normal(0, 1, 100)

from sklearn.pipeline import Pipeline
from sklearn.preprocessing import StandardScaler

# 三步合成在一起了
poly_reg = Pipeline([
    ("poly", PolynomialFeatures(degree=2)),
    ("std_scaler", StandardScaler()),
    ("lin_reg", LinearRegression())
])

poly_reg.fit(X, y)
y_predict = poly_reg.predict(X)

2 Переоснащение и недооснащение

2.1 Введение проблемы

Давайте сделаем несколько фотографий:

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

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

Если вы используете полиномиальную регрессию и степень равна 100, произойдет переобучение.

对训练结果进行拟合

Использование этой модели для прогнозирования тестового набора дает:

对测试集进行预测

2.2 Значение данных испытаний

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

Алгоритмы машинного обучения решают большую часть проблемы переобучения.

Следующий рисунок может ясно показать взаимосвязь между сложностью модели и точностью модели.

2.3 Кривая обучения

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

Принцип метода: с увеличением выборки распределение ошибки обучения и ошибки теста

def plot_learning_curve(algo, X_train, X_test, y_train, y_test):
    train_score = [] #训练误差
    test_score = [] #测试误差
    for i in range(1, len(X_train)+1):
        algo.fit(X_train[:i], y_train[:i])
    
        y_train_predict = algo.predict(X_train[:i])
        train_score.append(mean_squared_error(y_train[:i], y_train_predict))
    
        y_test_predict = algo.predict(X_test)
        test_score.append(mean_squared_error(y_test, y_test_predict))
    
    # 分别绘制训练误差与测试误差    
    plt.plot([i for i in range(1, len(X_train)+1)], 
                               np.sqrt(train_score), label="train")
    plt.plot([i for i in range(1, len(X_train)+1)], 
                               np.sqrt(test_score), label="test")
    plt.legend()
    plt.axis([0, len(X_train)+1, 0, 4])
    plt.show()

Кривая обучения для линейной регрессии:plot_learning_curve(LinearRegression(), X_train, X_test, y_train, y_test)

Кривая обучения для полиномиальной регрессии со степенью = 2:

Кривая обучения для полиномиальной регрессии со степенью = 20:

Давайте сравним недообучение, переоснащение и лучший случай

1. Подгонка Ошибки слишком велики как для обучающих, так и для тестовых наборов данных.

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

2.4 Перекрестная проверка

Мы разделяем данные на обучающие данные и тестовые данные и оцениваем качество модели по набору тестовых данных. Если происходит переобучение, давайте настроим параметры, а затем оценим качество модели по набору тестовых данных.

Вопрос 1:

Мы вращались вокруг набора тестовых данных и корректировали параметры набора тестовых данных много раз.Если набор тестовых данных переобучен, что нам делать?

Решение. Он разделен на три части: обучающие данные, проверочные данные и тестовые данные: Данные обучения и данные проверки участвуют в процессе настройки параметров, в то время как тестовые данные не участвуют в процессе настройки параметров, что эквивалентно данным черного ящика.

Вопрос 2: Случайно?

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

Решение: выполнить перекрестную проверку, разделить данные на K частей и в результате скорректировать параметры среднего значения K моделей.

from sklearn.model_selection import cross_val_score

knn_clf = KNeighborsClassifier()
cross_val_score(knn_clf, X_train, y_train, cv=5) # 5份的准确率分别为array([ 0.99543379,  0.96803653,  0.98148148,  0.96261682,  0.97619048])

Просмотрите поиск по сетке, GridSearchCV, где CV означает перекрестную проверку:

from sklearn.model_selection import GridSearchCV

param_grid = [
    {
        'weights': ['distance'],
        'n_neighbors': [i for i in range(2, 11)], 
        'p': [i for i in range(1, 6)]
    }
]

grid_search = GridSearchCV(knn_clf, param_grid, verbose=1)
grid_search.fit(X_train, y_train)

grid_search.best_score_ #0.98237476808905377,找到的是交叉验证平均后的数值
grid_search.best_params_ # {'n_neighbors': 2, 'p': 2, 'weights': 'distance'}

best_knn_clf = grid_search.best_estimator_ # 获取交叉验证后最好的模型
best_knn_clf.score(X_test, y_test) # 0.98052851182197498,平均后的模型

Недостатки: обучение k моделей каждый раз, что эквивалентно снижению общей производительности в k раз.

2.5 Компромисс дисперсии смещения

Смещение: не по центру Дисперсия: Разброс в центральной точке

Ошибка модели = смещение + отклонение + неизбежная ошибка

Основные причины предвзятости: недообучение, неверные предположения о самой проблеме Например: нелинейные данные с использованием линейной регрессии

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

  • Некоторые алгоритмы по своей сути являются алгоритмами с высокой дисперсией: например, kNN

  • Алгоритмы непараметрического обучения обычно представляют собой алгоритмы с высокой дисперсией. потому что никаких предположений о данных не делается

  • Некоторые алгоритмы по своей сути являются алгоритмами с высоким смещением. как линейная регрессия

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

  • Большинство алгоритмов имеют соответствующие параметры для настройки смещения и дисперсии.

Например, k для kNN, чем больше k, тем проще модель, тем больше отклонение и меньше дисперсия; чем меньше k, тем сложнее модель, тем меньше отклонение и больше дисперсия.

Например, полиномиальная регрессия в линейной регрессии, чем меньше степень, тем больше отклонение и меньше дисперсия. Чем больше степень, тем сложнее модель, тем меньше систематическая ошибка и больше дисперсия.

  • Смещение и дисперсия часто противоречат друг другу, уменьшение смещения увеличивает дисперсию, а уменьшение дисперсии увеличивает смещение.

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

Общие средства борьбы с высокой дисперсией:

  1. Уменьшить сложность модели
  2. Уменьшение размерности данных, шумоподавление (PCA)
  3. Увеличьте количество выборок (нейронная сеть, глубокое обучение, только когда масштаб данных будет достаточно большим, эффект будет хорошим)
  4. Использовать набор проверки
  5. регуляризация модели

3 Регуляризация модели

Регуляризация модели: ограничить размер параметров

Некоторые уклоны будут очень большими, как показано на изображении ниже.

3.1 Цели

Мы не можем просить J(θ), но также учитываем последнее. Обратите внимание, что в настоящее время θ0 не требуется, потому что точка пересечения не влияет на общий эффект модели.

где α также является гиперпараметром

3.2 Регрессия хребта

# 绘制图形方法
def plot_model(model):
    X_plot = np.linspace(-3, 3, 100).reshape(100, 1)
    y_plot = model.predict(X_plot)

    plt.scatter(x, y)
    plt.plot(X_plot[:,0], y_plot, color='r')
    plt.axis([-3, 3, 0, 6])
    plt.show()

np.random.seed(42)
x = np.random.uniform(-3.0, 3.0, size=100)
X = x.reshape(-1, 1)
y = 0.5 * x + 3 + np.random.normal(0, 1, size=100)
X_train, X_test, y_train, y_test = train_test_split(X, y)

poly_reg = PolynomialRegression(degree=20)
poly_reg.fit(X_train, y_train)
y_poly_predict = poly_reg.predict(X_test)
mean_squared_error(y_test, y_poly_predict) # 167.94010867293571
plot_model(poly_reg)

При переоснащении результирующая кривая показана на следующем рисунке.

После использования Ridge Regression Ridge:

from sklearn.linear_model import Ridge

def RidgeRegression(degree, alpha):
    return Pipeline([
        ("poly", PolynomialFeatures(degree=degree)),
        ("std_scaler", StandardScaler()),
        ("ridge_reg", Ridge(alpha=alpha))
    ])

ridge1_reg = RidgeRegression(20, 0.0001)
ridge1_reg.fit(X_train, y_train)

y1_predict = ridge1_reg.predict(X_test)
mean_squared_error(y_test, y1_predict) # 1.3233492754051845
plot_model(ridge1_reg)

Кривая значительно сглажена, и ошибка также значительно уменьшена.

Если а очень большое

ridge4_reg = RidgeRegression(20, 10000000)
ridge4_reg.fit(X_train, y_train)

y4_predict = ridge4_reg.predict(X_test)
mean_squared_error(y_test, y4_predict) # 1.8408455590998372
plot_model(ridge4_reg)

В итоге получается прямая линия, потому что в этой точке все тэты равны 0.

3.3 ЛАССО-регрессия

Итак, каковы различия и преимущества по сравнению с гребневой регрессией? Давайте сначала посмотрим на эффект от использования LASSO

from sklearn.linear_model import Lasso

def LassoRegression(degree, alpha):
    return Pipeline([
        ("poly", PolynomialFeatures(degree=degree)),
        ("std_scaler", StandardScaler()),
        ("lasso_reg", Lasso(alpha=alpha))
    ])
lasso1_reg = LassoRegression(20, 0.01)
lasso1_reg.fit(X_train, y_train)

y1_predict = lasso1_reg.predict(X_test)
mean_squared_error(y_test, y1_predict) # 1.1496080843259966
plot_model(lasso1_reg)

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

А при α = 0,1

А когда α = 1

Сравните Ридж с ЛАССО:

  • При использовании Ridge коэффициентов много, значения небольшие и стремятся к 0, но не к 0

  • Использование LASSO, как правило, является частью θ=0, поэтому его можно использовать в качестве селектора функций.

объяснять: Ridge выполняет градиентный спуск только для последнего элемента, как показано на рисунке ниже, каждый шаг θ имеет значение

LASSO выполняет метод градиентного спуска на последнем элементе, как показано на рисунке ниже, сначала по определенному направлению, находит ось, а затем идет к началу координат по этой оси. И когда определенная ось равна 0, это сделает многие θ=0.

Но LASSO может перепутать некоторые полезные функции с 0 Так что с точки зрения точности Ридж будет точнее. Если функций много, LASSO может уменьшить их. Расчет Ridge будет очень большим.

3.4 Эластичная сетка L1, L2

На самом деле, есть еще регулярный член L0, то есть старайтесь, чтобы количество θ было как можно меньше

Фактически он заменен на L1, потому что оптимизация регулярности L0 является NP-сложной задачей.

Эластичная сеть: сочетание L1 и L2

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

4 Резюме

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

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

Чтобы уменьшить дисперсию, вводится понятие регуляризации и соответственно объясняются различия, преимущества и недостатки регуляризации Риджа и LASSO.



Отказ от ответственности: эта статья является моими заметками об исследовании, а курс взят из MOOC: Python3 Introduction to Machine Learning Classic Algorithms and Applications. Я также хотел бы поблагодарить г-на Бобо за его прекрасное объяснение.

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

AI探索之路