Полиномиальная регрессия с помощью Scikit Learn: что вы должны знать

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

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

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

С помощью scikit learn можно создать его в конвейере, объединяющем эти два шага (Polynomialfeatures и LinearRegression). Я покажу код ниже. И давайте посмотрим на пример с некоторыми простыми игрушечными данными, всего 10 баллов. Давайте также примем градус равным 9. Окончательный результат вы можете увидеть ниже.

Вы видите что-то не так?

Ну по идее это неправильно! Для 10 точек полином 9-й степени должен идеально соответствовать им!

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

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

Создание некоторых игрушечных данных

import pandas as pd
xdic={'X': {11: 300, 12: 170, 13: 288, 14: 360, 15: 319, 16: 330, 17: 520, 18: 345, 19: 399, 20: 479}}
ydic={'y': {11: 305000, 12: 270000, 13: 360000, 14: 370000, 15: 379000, 16: 405000, 17: 407500, 18: 450000, 19: 450000, 20: 485000}}
X=pd.DataFrame.from_dict(xdic)
y=pd.DataFrame.from_dict(ydic)
import numpy as np
X_seq = np.linspace(X.min(),X.max(),300).reshape(-1,1)

Создание модели

from sklearn.preprocessing import PolynomialFeatures
from sklearn.pipeline import make_pipeline
from sklearn.linear_model import LinearRegression
degree=9
polyreg=make_pipeline(PolynomialFeatures(degree),LinearRegression())
polyreg.fit(X,y)

Создание сюжета

import matplotlib.pyplot as plt
plt.figure()
plt.scatter(X,y)
plt.plot(X_seq,polyreg.predict(X_seq),color="black")
plt.title("Polynomial regression with degree "+str(degree))
plt.show()

Вы не должны этого делать!

Прежде чем говорить о разнице между полиномиальной регрессией и полиномиальной интерполяцией. Давайте сначала поговорим об ответе, который я получил от команды scikit learn: вы не должны этого делать, расширение до полинома 9-й степени - нонсенс. Scikit learn создан для практических случаев использования и работает с представлениями конечной точности, а не с теоретическими представлениями.

Да, они совершенно правы! Вы только посмотрите на цифры, насколько они стали большими: 1e24!

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

Хорошо, хорошо, я знаю, некоторые из вас не уверены, что результат неправильный, или, может быть, невозможно обрабатывать большие числа, давайте посмотрим с другим пакетом, numpy!

Но у polyfit это хорошо

Для того же примера у polyfit от numpy нет проблем с поиском модели. Вы можете увидеть сюжет и код ниже.

coefs = np.polyfit(X.values.flatten(), y.values.flatten(), 9)
plt.figure()
plt.plot(X_seq, np.polyval(coefs, X_seq), color="black")
plt.title("Polyfit degree "+str(degree))
plt.scatter(X,y)
plt.show()

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

Потому что, когда я расспрашивал, я получил несколько таких ответов (но они неточные или неправильные):

polyfit делает совсем другое. Он выполняет одномерное полиномиальное соответствие некоторого вектора x вектору y. Здесь мы выполняем полиномиальное расширение некоторого пространства признаков X, чтобы представить члены взаимодействия высокого порядка (эквивалентные обучению с полиномиальным ядром) для многомерной подгонки.

Хорошо, что такое полиномиальная интерполяция?

Что такое полиномиальная интерполяция

Что ж, для такого рода вопросов Википедия - хороший источник.

В численном анализе полиномиальная интерполяция - это интерполяция заданного набора данных полиномом наименьшей степени, который проходит через точки набора данных.

И у нас есть доказанный результат: для n + 1 различных точек x_0, x_0,…, x_n и соответствующих значений y_0, y_1,…, y_n существует уникальный многочлен степени не выше n, который интерполирует данные (x_0, y_0),…, (x_n, y_n).

Возвращаясь к нашему примеру: есть 10 точек, и мы пытаемся найти многочлен 9-й степени. Так что технически мы выполняем полиномиальную интерполяцию. И polyfit нашел этот уникальный многочлен! чего нельзя сказать о конвейере полиномиальной регрессии scikit learn!

И именно поэтому некоторые из вас думают: polyfit отличается от конвейера полиномиальной регрессии scikit learn!

А теперь подожди!

В polyfit есть аргумент, называемый степень. Таким образом, вы можете изменить степень, давайте попробуем с 5.

Да, с помощью polyfit можно выбрать степень полинома, и мы выполняем с ним полиномиальную регрессию. А степень 9, выбранная пользователем, является частным случаем полиномиальной интерполяции.

И это обнадеживает, потому что линейная регрессия пытается минимизировать квадратичную ошибку. И мы знаем, что если имеется 10 точек, и мы пытаемся найти полином степени 9, то ошибка может быть 0 (не может быть меньше!) Из-за теоремы о полиномиальной интерполяции.

Для тех, кто все еще сомневается, есть официальный документ для polyfit: Подгонка полинома наименьших квадратов. Подгоните многочлен p(x) = p[0] * x**deg + ... + p[deg] степени deg к точкам (x, y). Возвращает вектор коэффициентов p, который минимизирует квадратичную ошибку в порядке deg, deg-1,… 0. .

Хорошо, пора вернуться к нашему конвейеру полиномиальной регрессии в scikit learn. Итак, в чем разница? Действительно ли существуют две разные полиномиальной регрессии (или подгонки), использующие оба метода наименьших квадратов, но использующие их по-разному?

Я нашел этот ответ, но пока не понимаю.

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

Эффект масштабирования функций

Во время копания следует упомянуть еще одно важное преобразование функций: масштабирование функций.

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

И да, конвейер полиномиальной регрессии scikit learn с масштабированием функций кажется эквивалентом polyfit! по сюжету (особо не проверял, но визуально они одинаковые).

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

from sklearn.preprocessing import PolynomialFeatures
from sklearn.pipeline import make_pipeline
from sklearn.linear_model import LinearRegression
from sklearn import preprocessing
scaler = preprocessing.StandardScaler()
degree=9
polyreg_scaled=make_pipeline(PolynomialFeatures(degree),scaler,LinearRegression())
polyreg_scaled.fit(X,y)

Теперь мы не ответили на наши предыдущие вопросы, и у нас есть еще вопросы: влияет ли масштабирование функций на линейную регрессию?

Что ж, ответ - нет.

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

X=pd.DataFrame.from_dict(xdic)/1000

Правильно, вы просто разделите предикторы на 1000. Теперь вы знаете, что влияние на модель линейной регрессии только пропорционально, но на практике разница огромна.

Вот почему мы можем сделать вывод, что начальные цифры слишком велики для scikit learn.

Заключение

В конце концов, мы можем сказать, что конвейер полиномиальной регрессии scikit learn (с масштабированием или без него) должен быть эквивалентен polyfit numpy, но разница в обработке больших чисел может привести к другим результатам.

И лично я считаю, что scikit learn в этом случае должен выдавать ошибку или, по крайней мере, предупреждение.

Очень хотелось бы узнать ваше мнение!