Краткое введение в линейную регрессию в Python

Всем привет! После краткого знакомства с библиотекой« Pandas », а также библиотекой NumPy, я хотел дать быстрое введение в построение моделей на Python, а что может быть лучше для начала, чем одна из самых простых моделей, линейная регрессия? Это будет первый пост о машинном обучении, и в будущем я планирую писать о более сложных моделях. Будьте на связи! Но пока давайте сосредоточимся на линейной регрессии.

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

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

Немного о математике

Связь между переменными Y и X представлена ​​этим уравнением:

Y`i = mX + b

В этом уравнении Y - зависимая переменная - или переменная, которую мы пытаемся предсказать или оценить; X - независимая переменная - переменная, которую мы используем для прогнозов; m - наклон линии регрессии - он отражает влияние X на Y. Другими словами, если X увеличивается на 1 единицу, Y увеличивается ровно на m единиц. («Полное раскрытие информации»: это верно, только если мы знаем, что X и Y имеют линейную связь. Почти во всех случаях линейной регрессии это не будет правдой!) b - константа, также известная как Y-пересечение. Если X равно 0, Y будет равно b (Предупреждение: см. Полное раскрытие ранее!). Это не обязательно применимо в реальной жизни - мы не всегда знаем точную взаимосвязь между X и Y или имеем точную линейную взаимосвязь.

Эти предостережения приводят нас к простой линейной регрессии (SLR). В модели SLR мы строим модель на основе данных - наклон и пересечение по оси Y выводятся из данных; кроме того, нам не нужно, чтобы отношения между X и Y были строго линейными. Модели SLR также включают ошибки в данных (также известные как остатки). Я не буду вдаваться в подробности сейчас, возможно, в более позднем посте, но остатки - это в основном различия между истинным значением Y и прогнозируемым / оценочным значением Y. Важно отметить, что в линейной регрессии мы пытаются предсказать непрерывную переменную. В регрессионной модели мы пытаемся минимизировать эти ошибки, находя линию наилучшего соответствия - линия регрессии от ошибок будет минимальной. Мы пытаемся минимизировать длину черных линий (точнее, расстояние синих точек) от красной линии - как можно ближе к нулю. Это связано (или эквивалентно) минимизации среднеквадратичной ошибки (MSE) или суммы квадратов ошибки (SSE), также называемой остаточной суммой квадратов. (RSS), но это может выходить за рамки этого сообщения в блоге :-)

В большинстве случаев у нас будет несколько независимых переменных - у нас будет несколько переменных; это может быть всего две независимые переменные и до сотен (или теоретически даже тысяч) переменных. в этих случаях мы будем использовать модель множественной линейной регрессии (MLR). Уравнение регрессии почти такое же, как и простое уравнение регрессии, только с большим количеством переменных:

Y’i = b0 + b1X1i + b2X2i

На этом завершается математическая часть этого поста :) Готовы приступить к реализации этого на Python?

Линейная регрессия в Python

Есть два основных способа выполнения линейной регрессии в Python - с помощью Statsmodels и scikit-learn. Также можно использовать библиотеку Scipy, но я считаю, что это не так распространено, как две другие библиотеки, о которых я упоминал. Давайте посмотрим, как провести линейную регрессию в обоих из них:

Линейная регрессия в статистических моделях

Statsmodels - это модуль Python, который предоставляет классы и функции для оценки множества различных статистических моделей, а также для проведения статистических тестов и исследования статистических данных. (из документации)

Как и в случае с Pandas и NumPy, самый простой способ получить или установить Statsmodels - использовать пакет Anaconda. Если по каким-то причинам вас интересует установка другим способом, загляните по этой ссылке. После установки вам нужно будет импортировать его каждый раз, когда вы захотите его использовать:

import statsmodels.api as sm

Давайте посмотрим, как на самом деле использовать статистические модели для линейной регрессии. Я буду использовать пример из класса по науке о данных, который я проходил в General Assembly DC:

Сначала мы импортируем набор данных из sklearn (другая упомянутая мною библиотека):

from sklearn import datasets ## imports datasets from scikit-learn
data = datasets.load_boston() ## loads Boston dataset from datasets library 

Это датасет цен на дома в Бостоне (ссылка на описание). Поскольку это набор данных, предназначенный для тестирования и обучения инструментов машинного обучения, он поставляется с описанием набора данных, и мы можем увидеть его с помощью команды print data.DESCR (это верно только для sklearn наборы данных, а не каждый набор данных! Было бы здорово…). Я добавляю начало описания, чтобы лучше понять переменные:

Boston House Prices dataset
===========================

Notes
------
Data Set Characteristics:  

    :Number of Instances: 506 

    :Number of Attributes: 13 numeric/categorical predictive
    
    :Median Value (attribute 14) is usually the target

    :Attribute Information (in order):
        - CRIM     per capita crime rate by town
        - ZN       proportion of residential land zoned for lots over 25,000 sq.ft.
        - INDUS    proportion of non-retail business acres per town
        - CHAS     Charles River dummy variable (= 1 if tract bounds river; 0 otherwise)
        - NOX      nitric oxides concentration (parts per 10 million)
        - RM       average number of rooms per dwelling
        - AGE      proportion of owner-occupied units built prior to 1940
        - DIS      weighted distances to five Boston employment centres
        - RAD      index of accessibility to radial highways
        - TAX      full-value property-tax rate per $10,000
        - PTRATIO  pupil-teacher ratio by town
        - B        1000(Bk - 0.63)^2 where Bk is the proportion of blacks by town
        - LSTAT    % lower status of the population
        - MEDV     Median value of owner-occupied homes in $1000's

    :Missing Attribute Values: None

    :Creator: Harrison, D. and Rubinfeld, D.L.

This is a copy of UCI ML housing dataset.
http://archive.ics.uci.edu/ml/datasets/Housing


This dataset was taken from the StatLib library which is maintained at Carnegie Mellon University.

При запуске data.feature_names и data.target будут напечатаны имена столбцов независимых переменных и зависимой переменной соответственно. Это означает, что Scikit-learn уже установил данные о стоимости / цене дома в качестве целевой переменной, а 13 других переменных установлены в качестве предикторов. Давайте посмотрим, как запустить линейную регрессию для этого набора данных.

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

import numpy as np
import pandas as pd
# define the data/predictors as the pre-set feature names  
df = pd.DataFrame(data.data, columns=data.feature_names)

# Put the target (housing value -- MEDV) in another DataFrame
target = pd.DataFrame(data.target, columns=["MEDV"])

Что мы здесь сделали, так это взяли набор данных и загрузили его как фрейм данных pandas; после этого мы устанавливаем предикторы (как df) - независимые переменные, которые предварительно установлены в наборе данных. Мы также устанавливаем цель - зависимую переменную или переменную, которую мы пытаемся предсказать / оценить.

Теперь нам нужно построить модель линейной регрессии. Нам нужно выбрать переменные, которые, по нашему мнению, будут хорошими предикторами для зависимой переменной - это можно сделать, проверив корреляцию (и) между переменными, построив график данных и визуально выполнив поиск взаимосвязи, проведя предварительное исследование того, какие переменные являются хорошими предикторами y и т. д. Для этого первого примера возьмем RM - среднее количество комнат и LSTAT - процент более низкого статуса населения. Важно отметить, что Statsmodels не добавляет константу по умолчанию. Давайте сначала посмотрим на это без константы в нашей регрессионной модели:

## Without a constant

import statsmodels.api as sm

X = df["RM"]
y = target["MEDV"]

# Note the difference in argument order
model = sm.OLS(y, X).fit()
predictions = model.predict(X) # make the predictions by the model

# Print out the statistics
model.summary()

Выход:

Интерпретация таблицы. Это очень длинная таблица, не так ли? Сначала у нас есть зависимая переменная, модель и метод. OLS означает обычные наименьшие квадраты, а метод наименьших квадратов означает, что мы пытаемся подогнать линию регрессии, которая минимизировала бы квадрат расстояния от линии регрессии (см. предыдущий раздел эта почта). Дата и время говорят сами за себя :) Как и количество наблюдений. Df остатков и моделей относится к степеням свободы - количеству значений в окончательном расчете статистики, которые могут изменяться.

Коэффициент 3,6534 означает, что при увеличении переменной RM на 1 прогнозируемое значение MDEV увеличивается на 3,6534. Несколько других важных значений - это R-квадрат - процент отклонения, который объясняет наша модель; стандартная ошибка (стандартное отклонение выборочного распределения статистики, чаще всего среднего); t-баллы и p-значения для проверки гипотез - RM имеет статистически значимое p-значение; существует 95% доверительный интервал для RM ( означает, что мы прогнозируем с доверием 95%, что значение RM находится между 3,548 и 3,759).

Если мы действительно хотим добавить константу в нашу модель - мы должны установить ее с помощью команды X = sm.add_constant(X), где X - имя вашего фрейма данных, содержащего ваши входные (независимые) переменные.

import statsmodels.api as sm # import statsmodels 

X = df["RM"] ## X usually means our input variables (or independent variables)
y = target["MEDV"] ## Y usually means our output/dependent variable
X = sm.add_constant(X) ## let's add an intercept (beta_0) to our model

# Note the difference in argument order
model = sm.OLS(y, X).fit() ## sm.OLS(output, input)
predictions = model.predict(X)

# Print out the statistics
model.summary()

Выход:

Интерпретация таблицы. У постоянного члена коэффициенты разные. Без константы мы заставляем нашу модель проходить через начало координат, но теперь у нас есть пересечение по оси Y на уровне -34,67. Мы также изменили наклон предиктора RM с 3,634 на 9,1021.

Теперь давайте попробуем подогнать модель регрессии с более чем одной переменной - мы будем использовать RM и LSTAT, о которых я упоминал ранее. Примерка модели такая же:

X = df[[“RM”, “LSTAT”]]
y = target[“MEDV”]
model = sm.OLS(y, X).fit()
predictions = model.predict(X)
model.summary()

И вывод:

Интерпретация выходных данных. Здесь мы видим, что эта модель имеет гораздо более высокое значение R-квадрата - 0,948, что означает, что эта модель объясняет 94,8% дисперсии в нашей зависимой переменной. Каждый раз, когда мы добавляем переменные в регрессионную модель, R² будет больше, но это довольно высокий R². Мы видим, что и RM, и LSTAT статистически значимы при прогнозировании (или оценке) медианной стоимости дома; неудивительно, что при увеличении RM на 1 MEDV увеличится на 4,9069, а при увеличении LSTAT на 1, MEDV уменьшится на -0,6557. Как вы, возможно, помните, LSTAT - это процентная доля населения с более низким статусом, и, к сожалению, мы можем ожидать, что он снизит медианное значение домов. По той же логике, чем больше комнат в доме, тем выше будет его стоимость.

Это был пример как одиночной, так и множественной линейной регрессии в Statsmodels. Мы могли бы использовать столько переменных, сколько захотим, в наших регрессионных моделях - вплоть до всех 13! Далее я продемонстрирую, как запускать модели линейной регрессии в SKLearn.

Линейная регрессия в SKLearn

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

from sklearn import linear_model

Давайте использовать тот же набор данных, который мы использовали ранее, о ценах на жилье в Бостоне. Вначале процесс будет таким же - импорт наборов данных из SKLearn и загрузка в набор данных Boston:

from sklearn import datasets ## imports datasets from scikit-learn
data = datasets.load_boston() ## loads Boston dataset from datasets library

Затем мы загрузим данные в Pandas (как и раньше):

# define the data/predictors as the pre-set feature names  
df = pd.DataFrame(data.data, columns=data.feature_names)

# Put the target (housing value -- MEDV) in another DataFrame
target = pd.DataFrame(data.target, columns=["MEDV"])

Итак, теперь, как и раньше, у нас есть фрейм данных, содержащий независимые переменные (помеченные как «df») и фрейм данных с зависимой переменной (помеченные как «target»). Давайте подберем регрессионную модель с помощью SKLearn. Сначала мы определим наши X и Y - на этот раз я буду использовать все переменные во фрейме данных, чтобы предсказать цену на жилье:

X = df
y = target[“MEDV”]

А потом подгоню модель:

lm = linear_model.LinearRegression()
model = lm.fit(X,y)

Функция lm.fit () соответствует линейной модели. Мы хотим использовать модель для прогнозирования (для этого мы и здесь!), Поэтому воспользуемся lm.predict ():

predictions = lm.predict(X)
print(predictions)[0:5]

Функция печати распечатает первые 5 прогнозов для y (я не распечатал весь список, чтобы «сэкономить место». Удаление [0: 5] приведет к печати всего списка):

[ 30.00821269  25.0298606   30.5702317   28.60814055  27.94288232]

Помните, lm.predict () предсказывает y (зависимую переменную), используя подобранную нами линейную модель. Вы, должно быть, заметили, что когда мы запускаем линейную регрессию с помощью SKLearn, мы не получаем красивую таблицу (ладно, она не такая красивая… но довольно полезная), как в Statsmodels. Что мы можем сделать, так это использовать встроенные функции для возврата оценки, коэффициентов и предполагаемых пересечений. Посмотрим, как это работает:

lm.score(X,y)

Дал бы такой результат:

0.7406077428649428

Это оценка R² нашей модели. Как вы, наверное, помните, это процент объясненной дисперсии прогнозов. Если интересно, подробнее здесь. Теперь давайте проверим коэффициенты для предикторов:

lm.coef_

даст этот результат:

array([ -1.07170557e-01,   4.63952195e-02,   2.08602395e-02,
         2.68856140e+00,  -1.77957587e+01,   3.80475246e+00,
         7.51061703e-04,  -1.47575880e+00,   3.05655038e-01,
        -1.23293463e-02,  -9.53463555e-01,   9.39251272e-03,
        -5.25466633e-01])

и перехват:

lm.intercept_

что даст такой результат:

36.491103280363134

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

Итак, это было быстрое (но довольно долгое!) Введение в то, как проводить линейную регрессию в Python. На практике вы не будете использовать весь набор данных, но вы разделите свои данные на обучающие данные для обучения вашей модели и тестовые данные, чтобы, как вы уже догадались, протестировать свою модель / прогнозы. Если вы хотите прочитать об этом, пожалуйста, прочтите мой следующий пост в блоге. А пока я надеюсь, что вам понравился этот пост, и я увижу вас в следующем.

Спасибо за чтение!