Время прочтения: 4 мин.
В качестве примера будем использовать датасет “flats_moscow” с ценами квартир в Москве.
Все квартиры описывается с помощью следующих полей:
- n – порядок квартиры в таблице
- price – стоимость квартиры, тыс. $
- totsp – общая площадь квартиры, кв.м.
- livesp — жилая площадь квартиры, кв.м.
- kitsp – площадь кухни, кв.м.
- dist – расстояние от центра, км.
- metrdist – время до метро, мин.
- walk – 1 – пешком от метро, 0 – на транспорте
- brick 1 – кирпичный, монолит ж/б, 0 – другой
- floor 1 – этаж кроме первого и последнего, 0 – иначе
- code – число от 1 до 8, при помощи которых группируются наблюдения по районам.
При желании можно найти датасет по ссылке. Сейчас не будем задумываться над предобработкой данных и увеличением score, построим классическую модель линейной регрессии.
import numpy as np
import pandas as pd
import statsmodels.formula.api as smf
from sklearn.linear_model import LinearRegression
df = pd.read_csv('flats_moscow.txt', sep='\t')
X = df.drop(columns=['n', 'price'])
y = df['price']
reg = LinearRegression().fit(X, y)
Выведем полученные коэффициенты перед регрессорами и (коэф. детерминации).
print(reg.intercept_, reg.coef_, reg.score(X, y), sep='\n')
Построим такую же модель используя библиотеку statsmodels. Основной отличительной чертой является ручное прописывание формулы модели, которую мы хотим получить.
model_1 = smf.ols('price ~ totsp + livesp + kitsp + dist + metrdist +'\
'walk + brick + floor + code', data=df).fit()
Выведем информацию о модели.
print(model_1.summary())
Получаем таблицу, обратим внимание на её правую верхнюю часть. R-squred – коэф. детерминации, Adj. R-squred – скорректированный коэф. детерминации, значение F-статистики, проверяющей гипотезу о незначимости модели в целом и её достигнутый уровень значимости, а также информационные критерии AIC, BIC. Ниже находится информация о регрессорах. В столбце coef находятся значения коэффициентов, std err стандартное отклонение коэффициента, t значение t-статистики, проверяющей гипотезу о незначимости признака, R > |t| достигнутый уровень значимости для этой статистики. В последнем столбце находится 95% доверительный интервал для коэффициентов.
Теперь прологарифмируем totsp, livesp, kitsp и целевую переменную. При использовании sklearn нам бы пришлось отдельно изменять эти признаки, но это долго и муторно. В statsmodel от нас потребуется в строке с формулой явно указать, что мы хотим использовать логарифм признака.
model_2 = smf.ols('np.log(price) ~ np.log(totsp) + np.log(livesp) + np.log(kitsp) + dist +'\
' metrdist + walk + brick + floor + code', data=df).fit()
print(model_2.summary())
При построении моделей так же важно перекодировать категориальные переменные. В sklearn нам бы пришлось все так же вручную создавать новые n — 1 переменные, где – кол-во категорий. Используя statsmodel достаточно изменить тип столбца на категориальный.
df["code"] = df["code"].astype('category')
Построим такую же модель на преобразованных данных.
model_3 = smf.ols('np.log(price) ~ np.log(totsp) + np.log(livesp) + np.log(kitsp) + dist +'\
' metrdist + walk + brick + floor + code', data=df).fit()
print(model_3.summary())
Обратим внимание на достигнутый уровень значимости логарифма признака kitsp в столбце R > |t|. Он больше 0.05 , т.е. мы не можем отклонить гипотезу о незначимости этого признака. Это вполне логично, так как информацию, которую в себе содержит это признак могут уже содержать totsp и livesp. Удалим его. К категориальным признакам данных подход не применим.
Таким образом мы убедились, что для построения модели линейной регрессии, удобно использовать библиотеку statsmodel. Почему в линейных моделях нельзя перекодировать категориальные признаки в n новых, то есть использовать One-hot encoding, обсудим в следующей статье.