Автор оригинала: Scott Robinson.
Линейная регрессия в Python с помощью Scikit-Learn
Существует два типа алгоритмов контролируемого машинного обучения: регрессия и классификация. Первый предсказывает непрерывные выходы значений, в то время как второй предсказывает дискретные выходы. Например, предсказание цены дома в долларах-это проблема регрессии, тогда как предсказание того, является ли опухоль злокачественной или доброкачественной, – это проблема классификации.
В этой статье мы кратко рассмотрим, что такое линейная регрессия и как ее можно реализовать с помощью библиотеки Python Scikit-Learn, которая является одной из самых популярных библиотек машинного обучения для Python.
Теория линейной регрессии
Термин “линейность” в алгебре относится к линейной зависимости между двумя или более переменными. Если мы нарисуем эту связь в двумерном пространстве (в данном случае между двумя переменными), то получим прямую линию.
Давайте рассмотрим сценарий, в котором мы хотим определить линейную зависимость между количеством часов, которые студент изучает, и процентом оценок, которые студент набирает на экзамене. Мы хотим выяснить, что, учитывая количество часов, которые студент готовит к тесту, о том, как высокий балл может достичь студент? Если мы построим независимую переменную (часы) на оси x и зависимую переменную (процент) на оси y, линейная регрессия даст нам прямую линию, которая наилучшим образом соответствует точкам данных, как показано на рисунке ниже.
Мы знаем, что уравнение прямой линии в основном:
y = mx + b
Где b
– перехват, а m
– наклон линии. Таким образом, в основном алгоритм линейной регрессии дает нам наиболее оптимальное значение для перехвата и наклона (в двух измерениях). Переменные y
и x
остаются неизменными, поскольку они являются функциями данных и не могут быть изменены. Значения, которые мы можем контролировать, – это перехват и наклон. В зависимости от значений перехвата и наклона может быть несколько прямых. По сути, алгоритм линейной регрессии помещает несколько строк в точки данных и возвращает строку, которая приводит к наименьшей ошибке.
Эта же концепция может быть распространена на случаи, когда существует более двух переменных. Это называется множественной линейной регрессией. Например, рассмотрим сценарий, в котором вы должны спрогнозировать цену дома, основываясь на его площади, количестве спален, среднем доходе людей в этом районе, возрасте дома и т. Д. В этом случае зависимая переменная зависит от нескольких независимых переменных. Регрессионную модель, включающую несколько переменных, можно представить в виде:
y = b0 + m1b1 + m2b2 + m3b3 + ... ... mnbn
Это уравнение гиперплоскости. Помните, что линейная регрессионная модель в двух измерениях-это прямая линия, в трех измерениях-плоскость, а в более чем трех измерениях-гиперплоскость.
Линейная регрессия с помощью Python Scikit Learn
В этом разделе мы увидим, как библиотека Python Scikit-Learn для машинного обучения может быть использована для реализации регрессионных функций. Мы начнем с простой линейной регрессии с участием двух переменных, а затем перейдем к линейной регрессии с участием нескольких переменных.
Простая Линейная регрессия
В этой регрессионной задаче мы будем предсказывать процент оценок, которые студент должен набрать, исходя из количества часов, которые он изучал. Это простая задача линейной регрессии, поскольку она включает в себя всего две переменные.
Импорт библиотек
Чтобы импортировать необходимые библиотеки для этой задачи, выполните следующие инструкции импорта:
import pandas as pd import numpy as np import matplotlib.pyplot as plt %matplotlib inline
Примечание : Как вы, возможно, заметили из приведенных выше инструкций импорта, этот код был выполнен с использованием ноутбука Jupyter IPython.
Набор данных
Набор данных, используемый для этого примера, стал общедоступным и может быть загружен по этой ссылке:
Набор данных, используемый для этого примера, стал общедоступным и может быть загружен по этой ссылке:
Примечание: Этот пример был выполнен на компьютере под управлением Windows, и набор данных был сохранен в “D:\datasets-папка. Вы можете загрузить файл в другое место, если соответствующим образом измените путь к набору данных.
Следующая команда импортирует набор данных CSV с помощью pandas:
dataset = pd.read_csv('D:\Datasets\student_scores.csv')
Теперь давайте немного изучим наш набор данных. Для этого выполните следующий сценарий:
dataset.shape
После этого вы должны увидеть следующее распечатанное:
(25, 2)
Это означает, что наш набор данных имеет 25 строк и 2 столбца. Давайте посмотрим, как на самом деле выглядит наш набор данных. Для этого используйте метод head()
:
dataset.head()
Описанный выше метод извлекает первые 5 записей из нашего набора данных, который будет выглядеть следующим образом:
2.5 | 21 | 0 |
5.1 | 47 | 1 |
3.2 | 27 | 2 |
8.5 | 75 | 3 |
3.5 | 30 | 4 |
Чтобы увидеть статистические данные набора данных, мы можем использовать describe()
:
dataset.describe()
25.000000 | 25.000000 | считать |
5.012000 | 51.480000 | означать |
2.525094 | 25.286887 | станд |
1.100000 | 17.000000 | минута |
2.700000 | 30.000000 | 25% |
4.800000 | 47.000000 | 50% |
7.400000 | 75.000000 | 75% |
9.200000 | 95.000000 | максимум |
И наконец, давайте построим наши точки данных на 2-D графике, чтобы посмотреть на наш набор данных и посмотреть, сможем ли мы вручную найти какую-либо связь между этими данными. Мы можем создать сюжет со следующим сценарием:
dataset.plot(x='Hours', y='Scores', style='o') plt.title('Hours vs Percentage') plt.xlabel('Hours Studied') plt.ylabel('Percentage Score') plt.show()
В приведенном выше скрипте мы используем функцию plot()
фрейма данных pandas и передаем ей имена столбцов для x
coordinate и y
coordinate, которые являются “Часами” и “Баллами” соответственно.
Получившийся сюжет будет выглядеть так:
Из приведенного выше графика мы ясно видим, что существует положительная линейная зависимость между количеством изученных часов и процентом баллов.
Подготовка данных
Теперь у нас есть представление о статистических деталях наших данных. Следующим шагом является разделение данных на “атрибуты” и “метки”. Атрибуты являются независимыми переменными, а метки-зависимыми переменными, значения которых должны быть предсказаны. В нашем наборе данных у нас есть только два столбца. Мы хотим предсказать процентный балл в зависимости от изученных часов. Поэтому наш набор атрибутов будет состоять из столбца “Часы”, а метка-из столбца “Оценка”. Чтобы извлечь атрибуты и метки, выполните следующий сценарий:
X = dataset.iloc[:, :-1].values y = dataset.iloc[:, 1].values
Атрибуты хранятся в переменной X
. Мы указали “-1” в качестве диапазона для столбцов, так как хотели, чтобы наш набор атрибутов содержал все столбцы, кроме последнего, который является “Баллами”. Аналогично переменная y
содержит метки. Мы указали 1 для столбца метки, так как индекс для столбца “Оценки” равен 1. Помните, что индексы столбцов начинаются с 0, причем 1 является вторым столбцом. В следующем разделе мы рассмотрим лучший способ указания столбцов для атрибутов и меток.
Теперь, когда у нас есть атрибуты и метки, следующий шаг-разделить эти данные на обучающие и тестовые наборы. Мы сделаем это с помощью встроенного метода Scikit-Learn train_test_split()
:
from sklearn.model_selection import train_test_split X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.2, random_state=0)
Приведенный выше сценарий разбивает 80% данных на обучающий набор, а 20% – на тестовый. Переменная test_size
– это то место, где мы фактически указываем долю тестового набора.
Обучение алгоритма
Мы разделили наши данные на обучающие и тестовые наборы, и теперь, наконец, пришло время обучить наш алгоритм. Выполните следующую команду:
from sklearn.linear_model import LinearRegression regressor = LinearRegression() regressor.fit(X_train, y_train)
С помощью Scikit-Learn очень просто реализовать модели линейной регрессии, так как все, что вам действительно нужно сделать, это импортировать класс LinearRegression
, создать его экземпляр и вызвать метод fit()
вместе с нашими обучающими данными. Это примерно так же просто, как при использовании библиотеки машинного обучения для обучения на ваших данных.
В разделе теории мы сказали, что линейная регрессионная модель в основном находит лучшее значение для перехвата и наклона, что приводит к линии, которая лучше всего соответствует данным. Чтобы увидеть значение перехвата и наклона, вычисленное алгоритмом линейной регрессии для нашего набора данных, выполните следующий код.
Чтобы восстановить перехват:
print(regressor.intercept_)
Результирующее значение, которое вы видите, должно быть приблизительно 2.01816004143.
Для получения наклона (коэффициент x):
print(regressor.coef_)
Результат должен быть примерно 9.91065648.
Это означает, что на каждую единицу изменения в изученных часах изменение балла составляет около 9,91%. Или, проще говоря, если студент учится на один час больше, чем он ранее учился на экзамене, он может ожидать увеличения на 9,91% балла, достигнутого студентом ранее.
Делать Прогнозы
Теперь, когда мы обучили наш алгоритм, пришло время сделать некоторые прогнозы. Для этого мы воспользуемся нашими тестовыми данными и посмотрим, насколько точно наш алгоритм предсказывает процентный балл. Чтобы сделать прогнозы по тестовым данным, выполните следующий сценарий:
y_pred = regressor.predict(X_test)
y_pred
– это массив numpy, содержащий все предсказанные значения для входных значений в серии X_test
.
Чтобы сравнить фактические выходные значения для X_test
с прогнозируемыми значениями, выполните следующий сценарий:
df = pd.DataFrame({'Actual': y_test, 'Predicted': y_pred}) df
Вывод выглядит следующим образом:
20 | 16.884145 | 0 |
27 | 33.732261 | 1 |
69 | 75.357018 | 2 |
30 | 26.794801 | 3 |
62 | 60.491033 | 4 |
Хотя наша модель не очень точна, предсказанные проценты близки к реальным.
Примечание :
Значения в приведенных выше столбцах могут отличаться в вашем случае, поскольку функция train_test_split
случайным образом разбивает данные на наборы поездов и тестов, и ваши разбиения, скорее всего, отличаются от приведенных в этой статье.
Оценка алгоритма
Заключительным шагом является оценка производительности алгоритма. Этот шаг особенно важен для сравнения того, насколько хорошо различные алгоритмы работают с конкретным набором данных. Для регрессионных алгоритмов обычно используются три оценочные метрики:
- Средняя абсолютная ошибка (MAE) – это среднее значение абсолютного значения ошибок. Он рассчитывается как:
- Среднеквадратичная ошибка (MSE) – это среднее значение квадратов ошибок и вычисляется как:
- Среднеквадратичная ошибка (RMSE) – это квадратный корень из среднего значения квадратов ошибок:
К счастью, нам не нужно выполнять эти вычисления вручную. Библиотека Scikit-Learn поставляется с предустановленными функциями, которые могут быть использованы для определения этих значений для нас.
Давайте найдем значения этих метрик, используя наши тестовые данные. Выполните следующий код:
from sklearn import metrics print('Mean Absolute Error:', metrics.mean_absolute_error(y_test, y_pred)) print('Mean Squared Error:', metrics.mean_squared_error(y_test, y_pred)) print('Root Mean Squared Error:', np.sqrt(metrics.mean_squared_error(y_test, y_pred)))
Вывод будет выглядеть примерно так (но, вероятно, немного иначе):
Mean Absolute Error: 4.183859899 Mean Squared Error: 21.5987693072 Root Mean Squared Error: 4.6474476121
Вы можете видеть, что значение среднеквадратичной ошибки составляет 4,64, что составляет менее 10% от среднего значения процентов всех студентов, то есть 51,48. Это означает, что наш алгоритм проделал достойную работу.
Множественная линейная регрессия
В предыдущем разделе мы провели линейную регрессию с участием двух переменных. Почти все реальные проблемы, с которыми вы столкнетесь, будут иметь более двух переменных. Линейная регрессия с участием нескольких переменных называется “множественной линейной регрессией”. Шаги для выполнения множественной линейной регрессии почти аналогичны шагам простой линейной регрессии. Разница заключается в оценке. Вы можете использовать его, чтобы выяснить, какой фактор оказывает наибольшее влияние на прогнозируемый результат и как различные переменные связаны друг с другом.
В этом разделе мы будем использовать множественную линейную регрессию для прогнозирования потребления газа (в миллионах галлонов) в 48 штатах США на основе налогов на газ (в центах), дохода на душу населения (в долларах), мощеных автомагистралей (в милях) и доли населения, имеющего водительские права.
Подробную информацию о наборе данных можно найти по этой ссылке:
Подробную информацию о наборе данных можно найти по этой ссылке:
Первые два столбца в приведенном выше наборе данных не содержат никакой полезной информации, поэтому они были удалены из файла набора данных. Теперь давайте разработаем регрессионную модель для этой задачи.
Импорт библиотек
Следующий скрипт импортирует необходимые библиотеки:
import pandas as pd import numpy as np import matplotlib.pyplot as plt %matplotlib inline
Набор данных
Набор данных для этого примера доступен по адресу:
Набор данных для этого примера доступен по адресу:
Следующая команда импортирует набор данных из файла, загруженного по ссылке выше:
dataset = pd.read_csv('D:\Datasets\petrol_consumption.csv')
Как и в прошлый раз, давайте посмотрим, как на самом деле выглядит наш набор данных. Выполните команду head()
:
dataset.head()
Первые несколько строк нашего набора данных выглядят следующим образом:
9.0 | 0 | 3571 | 1976 | 541 | 0.525 |
9.0 | 1 | 4092 | 1250 | 524 | 0.572 |
9.0 | 2 | 3865 | 1586 | 561 | 0.580 |
7.5 | 3 | 4870 | 2351 | 414 | 0.529 |
8.0 | 4 | 4399 | 431 | 410 | 0.544 |
Чтобы увидеть статистические данные набора данных, мы снова воспользуемся командой describe()
:
dataset.describe()
48.000000 | считать | 48.000000 | 48.000000 | 48.000000 | 48.000000 |
7.668333 | означать | 4241.833333 | 5565.416667 | 576.770833 | 0.570333 |
0.950770 | станд | 573.623768 | 3491.507166 | 111.885816 | 0.055470 |
5.000000 | минута | 3063.000000 | 431.000000 | 344.000000 | 0.451000 |
7.000000 | 25% | 3739.000000 | 3110.250000 | 509.500000 | 0.529750 |
7.500000 | 50% | 4298.000000 | 4735.500000 | 568.500000 | 0.564500 |
8.125000 | 75% | 4578.750000 | 7156.000000 | 632.750000 | 0.595250 |
10.000000 | максимум | 5342.000000 | 17782.000000 | 986.000000 | 0.724000 |
Подготовка данных
Следующий шаг-разделить данные на атрибуты и метки, как мы делали ранее. Однако, в отличие от прошлого раза, на этот раз мы будем использовать имена столбцов для создания набора атрибутов и метки. Выполните следующий сценарий:
X = dataset[['Petrol_tax', 'Average_income', 'Paved_Highways', 'Population_Driver_licence(%)']] y = dataset['Petrol_Consumption']
Выполните следующий код, чтобы разделить наши данные на обучающие и тестовые наборы:
from sklearn.model_selection import train_test_split X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.2, random_state=0)
Обучение алгоритма
И, наконец, для обучения алгоритма мы выполняем тот же код, что и раньше, используя метод fit()
класса LinearRegression
:
from sklearn.linear_model import LinearRegression regressor = LinearRegression() regressor.fit(X_train, y_train)
Как было сказано ранее, в случае многомерной линейной регрессии регрессионная модель должна найти наиболее оптимальные коэффициенты для всех атрибутов. Чтобы увидеть, какие коэффициенты выбрала наша регрессионная модель, выполните следующий сценарий:
coeff_df = pd.DataFrame(regressor.coef_, X.columns, columns=['Coefficient']) coeff_df
Результат должен выглядеть примерно так:
Petrol_tax | -24.196784 |
Average_income | -0.816800 |
Асфальтированные магистрали | -0.000522 |
Population_Driver_license(%) | 1324.675464 |
Это означает, что при единичном увеличении “petrol_tax” потребление газа уменьшается на 24,19 миллиона галлонов. Аналогичным образом, увеличение доли населения, имеющего водительские права, на единицу приводит к увеличению потребления газа на 1,324 миллиарда галлонов. Мы видим, что “Average_income” и “Paved_Highways” очень мало влияют на потребление газа.
Делать Прогнозы
Чтобы сделать прогнозы по тестовым данным, выполните следующий сценарий:
y_pred = regressor.predict(X_test)
Чтобы сравнить фактические выходные значения для X_test
с прогнозируемыми значениями, выполните следующий сценарий:
df = pd.DataFrame({'Actual': y_test, 'Predicted': y_pred}) df
Чтобы сравнить фактические выходные значения для || X_test || с прогнозируемыми значениями, выполните следующий сценарий:
640 | 643.176639 | 36 |
464 | 411.950913 | 22 |
649 | 683.712762 | 20 |
648 | 728.049522 | 38 |
865 | 755.473801 | 18 |
524 | 559.135132 | 1 |
782 | 671.916474 | 44 |
540 | 550.633557 | 21 |
603 | 594.425464 | 16 |
510 | 525.038883 | 45 |
Оценка алгоритма
Заключительным шагом является оценка производительности алгоритма. Мы сделаем это, найдя значения для MAE , MSE и RMSE . Выполните следующий сценарий:
from sklearn import metrics print('Mean Absolute Error:', metrics.mean_absolute_error(y_test, y_pred)) print('Mean Squared Error:', metrics.mean_squared_error(y_test, y_pred)) print('Root Mean Squared Error:', np.sqrt(metrics.mean_squared_error(y_test, y_pred)))
Результат будет выглядеть примерно так:
Mean Absolute Error: 45.8979842541 Mean Squared Error: 3609.37119141 Root Mean Squared Error: 60.0780425065
Вы можете видеть, что значение среднеквадратичной ошибки составляет 60,07, что немного больше 10% от среднего значения потребления газа во всех штатах. Это означает, что наш алгоритм был не очень точен, но все же может делать достаточно хорошие прогнозы.
Есть много факторов, которые, возможно, способствовали этой неточности, некоторые из которых перечислены здесь:
- Нужно больше данных: Только один год данных-это не так уж много, в то время как наличие нескольких лет могло бы помочь нам немного повысить точность.
- Плохие предположения: Мы предположили, что эти данные имеют линейную зависимость, но это может быть не так. Визуализация данных может помочь вам определить это.
- Плохие характеристики: Характеристики, которые мы использовали, возможно, не имели достаточно высокой корреляции со значениями, которые мы пытались предсказать.
Вывод
В этой статье мы изучили один из наиболее фундаментальных алгоритмов машинного обучения-линейную регрессию. Мы реализовали как простую линейную регрессию, так и множественную линейную регрессию с помощью библиотеки машинного обучения Scikit-Learn.
Есть несколько вещей, которые вы можете сделать отсюда:
- Поиграйте с кодом и данными в этой статье, чтобы увидеть, можете ли вы улучшить результаты (попробуйте изменить размер обучения/теста, преобразовать/масштабировать входные функции и т. Д.)
- Найдите более полные ресурсы по методам машинного обучения, такие как курсы и , которые также научат вас использовать Scikit-Learn и другие популярные библиотеки ML
- Загрузите и поиграйте с некоторыми другими наборами данных регрессии, чтобы увидеть, какие результаты вы можете получить из них. Чем больше опыта, тем лучше!
Использовали ли вы Scikit-Learn или линейную регрессию для решения каких-либо проблем в прошлом? Если да, то что это было и каковы были результаты? Дайте нам знать в комментариях!