You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
ML-For-Beginners/translations/ru/2-Regression/3-Linear
localizeflow[bot] 4ab4f52666
chore(i18n): sync translations with latest source changes (chunk 1/1, 12 changes)
4 months ago
..
solution chore(i18n): sync translations with latest source changes (chunk 1/1, 300 changes) 6 months ago
README.md chore(i18n): sync translations with latest source changes (chunk 1/1, 12 changes) 4 months ago
assignment.md chore(i18n): sync translations with latest source changes (chunk 1/1, 300 changes) 6 months ago
notebook.ipynb 🌐 Update translations via Co-op Translator 12 months ago

README.md

Создание регрессионной модели с помощью Scikit-learn: четыре подхода к регрессии

Заметка для начинающих

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

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

Инфографика от Dasani Madipalli

Тест перед лекцией

Этот урок доступен на языке R!

Введение

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

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

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

ML for beginners - Understanding Linear Regression

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

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

Предпосылки

К этому моменту вы должны быть знакомы со структурой данных по тыквам, которые мы рассматриваем. Они уже загружены и очищены в файле notebook.ipynb этого урока. В файле цена за бушель отображается в новом датафрейме. Убедитесь, что вы можете запускать эти ноутбуки в среде Visual Studio Code.

Подготовка

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

  • Когда лучше всего покупать тыквы?
  • Какую цену можно ожидать за ящик миниатюрных тыкв?
  • Стоит ли покупать их в корзинах на полбушеля или ящиках на 1 1/9 бушеля?
    Давайте продолжим исследовать эти данные.

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

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

Линия линейной регрессии

Как вы узнали в Уроке 1, цель упражнения по линейной регрессии — построить линию, которая будет:

  • Показывать взаимосвязь переменных. Отобразить зависимость между переменными.
  • Делать прогнозы. Точно предсказывать, где на линии окажется новая точка данных.

Часто для этого используется метод наименьших квадратов. Термин "наименьших квадратов" относится к процессу минимизации общей ошибки модели. Для каждой точки данных мы измеряем вертикальное расстояние (называемое остатком) между фактической точкой и нашей линией регрессии.

Мы возводим эти расстояния в квадрат по двум основным причинам:

  1. Величина вместо направления: Мы хотим, чтобы ошибка -5 рассматривалась так же, как ошибка +5. Возведение в квадрат превращает все значения в положительные.

  2. Штрафование выбросов: Квадрат больших ошибок увеличивает их вес, заставляя линию держаться ближе к отдалённым точкам.

Затем мы суммируем все эти квадраты. Наша цель — найти такую линию, для которой сумма будет минимальной — отсюда и название "наименьших квадратов".

🧮 Покажите математику

Эта линия, называемая линией наилучшего соответствия, выражается уравнением:

Y = a + bX

X — «объясняющая переменная». Y — «зависимая переменная». Наклон линии — b, а a — y-пересечение, то есть значение Y, когда X = 0.

расчет наклона

Сначала вычислите наклон b. Инфографика от Jen Looper

Иными словами, ссылаясь на исходный вопрос наших данных по тыквам: "предсказать цену тыквы за бушель по месяцу", X будет означать цену, а Y — месяц продажи.

завершение уравнения

Вычислите значение Y. Если платите около 4 долларов, должно быть, это апрель! Инфографика от Jen Looper

Математика, которая вычисляет линию, должна демонстрировать наклон линии, который также зависит от пересечения, т.е. где Y находится при X = 0.

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

Корреляция

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

Хорошая модель линейной регрессии имеет высокий коэффициент корреляции (ближе к 1, чем к 0), используя метод наименьших квадратов с линией регрессии.

Запустите ноутбук, который сопровождает этот урок, и посмотрите на диаграмму рассеяния «Месяц — Цена». Кажется ли вам, что данные связывают месяц и цену продажи тыкв с высокой или низкой корреляцией, согласно вашему визуальному восприятию графика? Изменится ли это, если использовать более мелкий масштаб вместо Month, например, день в году (т.е. количество дней с начала года)?

В приведенном ниже коде мы предположим, что данные были очищены, и получен датафрейм с именем new_pumpkins, подобный следующему:

ID Месяц ДеньВГоду Сорт Город Упаковка Низкая цена Высокая цена Цена
70 9 267 PIE TYPE BALTIMORE 1 1/9 бушеля картон 15.0 15.0 13.636364
71 9 267 PIE TYPE BALTIMORE 1 1/9 бушеля картон 18.0 18.0 16.363636
72 10 274 PIE TYPE BALTIMORE 1 1/9 бушеля картон 18.0 18.0 16.363636
73 10 274 PIE TYPE BALTIMORE 1 1/9 бушеля картон 17.0 17.0 15.454545
74 10 281 PIE TYPE BALTIMORE 1 1/9 бушеля картон 15.0 15.0 13.636364

Код для очистки данных доступен в notebook.ipynb. Мы выполнили те же шаги очистки, что и в предыдущем уроке, и рассчитали столбец DayOfYear с помощью следующего выражения:

day_of_year = pd.to_datetime(pumpkins['Date']).apply(lambda dt: (dt-datetime(dt.year,1,1)).days)

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

Поиск корреляции

ML for beginners - Looking for Correlation: The Key to Linear Regression

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

Из предыдущего урока вы, вероятно, видели, что средняя цена по месяцам выглядит так:

Средняя цена по месяцам

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

Диаграмма рассеяния Price против Day of Year

Давайте проверим корреляцию с помощью функции corr:

print(new_pumpkins['Month'].corr(new_pumpkins['Price']))
print(new_pumpkins['DayOfYear'].corr(new_pumpkins['Price']))

Похоже, что корреляция довольно мала — -0.15 для Month и -0.17 для DayOfMonth, но, возможно, есть другая важная зависимость. Судя по всему, имеются разные кластеры цен, соответствующие разным сортам тыкв. Чтобы подтвердить гипотезу, давайте отобразим каждый сорт тыкв разным цветом. Передавая параметр ax в функцию scatter, мы сможем вывести все точки на одном графике:

ax=None
colors = ['red','blue','green','yellow']
for i,var in enumerate(new_pumpkins['Variety'].unique()):
    df = new_pumpkins[new_pumpkins['Variety']==var]
    ax = df.plot.scatter('DayOfYear','Price',ax=ax,c=colors[i],label=var)
Диаграмма рассеяния Price против Day of Year

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

new_pumpkins.groupby('Variety')['Price'].mean().plot(kind='bar')
Столбчатая диаграмма цена по сортам

Сконцентрируемся теперь на одном сорте тыкв — «pie type» — и посмотрим, какой эффект оказывает дата на цену:

pie_pumpkins = new_pumpkins[new_pumpkins['Variety']=='PIE TYPE']
pie_pumpkins.plot.scatter('DayOfYear','Price') 
Диаграмма рассеяния Price против Day of Year

Если теперь вычислить корреляцию между Price и DayOfYear с помощью функции corr, мы получим значение около -0.27 — это значит, что обучение прогностической модели целесообразно.

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

pie_pumpkins.dropna(inplace=True)
pie_pumpkins.info()

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

Простая линейная регрессия

ML for beginners - Linear and Polynomial Regression using Scikit-learn

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

Для обучения нашей модели линейной регрессии мы будем использовать библиотеку Scikit-learn.

from sklearn.linear_model import LinearRegression
from sklearn.metrics import mean_squared_error
from sklearn.model_selection import train_test_split

Начнем с того, что отделим входные значения (признаки) и ожидаемый результат (метка) в отдельные массивы numpy:

X = pie_pumpkins['DayOfYear'].to_numpy().reshape(-1,1)
y = pie_pumpkins['Price']

Обратите внимание, что нам пришлось применить reshape к входным данным, чтобы библиотека линейной регрессии правильно их восприняла. Линейная регрессия ожидает на вход двумерный массив, где каждая строка массива соответствует вектору признаков. В нашем случае, поскольку у нас один вход, нам нужен массив формы N×1, где N — размер набора данных.

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

X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.2, random_state=0)

Наконец, обучение самой модели линейной регрессии занимает всего две строки кода. Мы создаем объект LinearRegression и подгоняем модель под данные с помощью метода fit:

lin_reg = LinearRegression()
lin_reg.fit(X_train,y_train)

Объект LinearRegression после выполнения fit содержит все коэффициенты регрессии, к которым можно получить доступ с помощью свойства .coef_. В нашем случае есть всего один коэффициент, который должен быть около -0.017. Это означает, что цены, по всей видимости, немного снижаются с течением времени, но незначительно, примерно на 2 цента в день. Мы также можем получить точку пересечения регрессии с осью Y с помощью lin_reg.intercept_ — в нашем случае это будет около 21, что указывает на цену в начале года.

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

pred = lin_reg.predict(X_test)

rmse = np.sqrt(mean_squared_error(y_test,pred))
print(f'RMSE: {rmse:3.3} ({rmse/np.mean(pred)*100:3.3}%)')

Наша ошибка кажется около 2 баллов, что примерно 17%. Не очень хорошо. Еще одним показателем качества модели является коэффициент детерминации, который можно получить следующим образом:

score = lin_reg.score(X_train,y_train)
print('Model determination: ', score)

Если значение равно 0, это значит, что модель не учитывает входные данные и действует как худший линейный предсказатель, который просто является средним значением результата. Значение 1 означает, что мы можем идеально предсказать все ожидаемые выходные данные. В нашем случае коэффициент около 0.06, что довольно низко.

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

plt.scatter(X_test,y_test)
plt.plot(X_test,pred)
Линейная регрессия

Полиномиальная регрессия

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

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

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

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

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

В Scikit-learn есть удобное API pipeline для объединения различных этапов обработки данных. Pipeline — это цепочка оценивателей. В нашем случае мы создадим pipeline, который сначала добавит полиномиальные признаки к нашей модели, а затем обучит регрессию:

from sklearn.preprocessing import PolynomialFeatures
from sklearn.pipeline import make_pipeline

pipeline = make_pipeline(PolynomialFeatures(2), LinearRegression())

pipeline.fit(X_train,y_train)

Использование PolynomialFeatures(2) означает, что мы включим все полиномы второй степени из входных данных. В нашем случае это будет просто DayOfYear2, но для двух входных переменных X и Y это добавит X2, XY и Y2. Можно также использовать полиномы более высокого порядка при необходимости.

Pipelines можно использовать так же, как и исходный объект LinearRegression, то есть мы можем выполнить fit для pipeline, а затем использовать predict для получения результатов предсказания. Вот график, показывающий тестовые данные и аппроксимирующую кривую:

Полиномиальная регрессия

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

Вы видите, что минимальные цены на тыквы наблюдаются где-то около Хэллоуина. Как вы это объясните?

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

Категориальные признаки

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

ML для начинающих - предсказания с категориальными признаками с помощью линейной регрессии

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

Здесь вы видите, как средняя цена зависит от сорта:

Средняя цена по сортам

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

  • Простой числовой кодировкой составляется таблица различных сортов, а затем название сорта заменяется индексом в этой таблице. Это не лучшая идея для линейной регрессии, потому что она воспринимает числовое значение индекса как фактическое число и добавляет его к результату, умножая на коэффициент. В нашем случае связь между номером индекса и ценой явно нелинейная, даже если упорядочить индексы определённым образом.
  • One-hot кодировка заменит столбец Variety на 4 разные столбца, по одному для каждого сорта. Каждый столбец будет содержать 1, если соответствующая строка относится к данному сорту, и 0 в противном случае. Это означает, что в линейной регрессии будет четыре коэффициента, по одному для каждого сорта тыквы, отвечающие за "начальную цену" (точнее "дополнительную цену") для конкретного сорта.

Пример кода ниже показывает, как можно выполнить one-hot кодировку сорта:

pd.get_dummies(new_pumpkins['Variety'])
ID FAIRYTALE MINIATURE MIXED HEIRLOOM VARIETIES PIE TYPE
70 0 0 0 1
71 0 0 0 1
... ... ... ... ...
1738 0 1 0 0
1739 0 1 0 0
1740 0 1 0 0
1741 0 1 0 0
1742 0 1 0 0

Чтобы обучить линейную регрессию, используя one-hot кодированный сорт в качестве входных данных, нам просто нужно правильно инициализировать данные X и y:

X = pd.get_dummies(new_pumpkins['Variety'])
y = new_pumpkins['Price']

Остальной код такой же, как мы использовали ранее для обучения линейной регрессии. Если вы попробуете, увидите, что среднеквадратическая ошибка примерно такая же, но коэффициент детерминации значительно выше (~77%). Чтобы получить еще более точные прогнозы, мы можем учитывать больше категориальных признаков, а также числовые признаки, например Month или DayOfYear. Чтобы получить один большой массив признаков, можно использовать join:

X = pd.get_dummies(new_pumpkins['Variety']) \
        .join(new_pumpkins['Month']) \
        .join(pd.get_dummies(new_pumpkins['City'])) \
        .join(pd.get_dummies(new_pumpkins['Package']))
y = new_pumpkins['Price']

Здесь мы также учитываем City и тип Package, что дает нам MSE 2.84 (10%) и коэффициент детерминации 0.94!

Объединяем все вместе

Чтобы получить лучшую модель, мы можем использовать объединённые (one-hot кодированные категориальные + числовые) данные из приведённого выше примера вместе с полиномиальной регрессией. Вот полный код для вашего удобства:

# подготовить обучающие данные
X = pd.get_dummies(new_pumpkins['Variety']) \
        .join(new_pumpkins['Month']) \
        .join(pd.get_dummies(new_pumpkins['City'])) \
        .join(pd.get_dummies(new_pumpkins['Package']))
y = new_pumpkins['Price']

# разделить на обучающую и тестовую выборки
X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.2, random_state=0)

# настроить и обучить конвейер
pipeline = make_pipeline(PolynomialFeatures(2), LinearRegression())
pipeline.fit(X_train,y_train)

# предсказать результаты для тестовых данных
pred = pipeline.predict(X_test)

# вычислить MSE и коэффициент детерминации
mse = np.sqrt(mean_squared_error(y_test,pred))
print(f'Mean error: {mse:3.3} ({mse/np.mean(pred)*100:3.3}%)')

score = pipeline.score(X_train,y_train)
print('Model determination: ', score)

Это должно дать нам лучший коэффициент детерминации почти 97% и MSE=2.23 (~8% ошибка предсказания).

Модель MSE Коэффициент детерминации
Линейная (DayOfYear) 2.77 (17.2%) 0.07
Полиномиальная (DayOfYear) 2.73 (17.0%) 0.08
Линейная (Variety) 5.24 (19.7%) 0.77
Линейная (Все признаки) 2.84 (10.5%) 0.94
Полиномиальная (Все признаки) 2.23 (8.25%) 0.97

🏆 Отличная работа! Вы создали четыре модели регрессии в одном уроке и повысили качество модели до 97%. В последнем разделе по регрессии вы узнаете о логистической регрессии для определения категорий.


🚀Задание

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

Викторина после лекции

Обзор и самостоятельное изучение

В этом уроке мы изучили линейную регрессию. Существуют и другие важные типы регрессии. Ознакомьтесь с поэтапной, гребневой (Ridge), лассо (Lasso) и Elasticnet техниками. Хорошим курсом для изучения является курс по статистическому обучению Стэнфорда

Домашнее задание

Постройте модель


Отказ от ответственности:
Этот документ был переведен с помощью сервиса автоматического перевода Co-op Translator. Несмотря на то, что мы стремимся к точности, имейте в виду, что автоматический перевод может содержать ошибки или неточности. Оригинальный документ на его исходном языке следует считать авторитетным источником. Для важной информации рекомендуется обратиться к профессиональному переводу, выполненному человеком. Мы не несем ответственности за любые недоразумения или неправильные толкования, возникшие в результате использования этого перевода.