Я пытаюсь предсказать некоторые цены из набора данных, который я очистил. Я никогда не использовал для этого Python (обычно я использую tidyverse
, но на этот раз я хотел изучить pipeline
.
Итак, вот фрагмент кода:
import pandas as pd
from sklearn.compose import ColumnTransformer
from sklearn.preprocessing import StandardScaler
from sklearn.preprocessing import OneHotEncoder
from sklearn.pipeline import Pipeline
from sklearn.svm import SVR
from sklearn.model_selection import train_test_split
from sklearn.model_selection import GridSearchCV
import numpy as np
df = pd.read_csv("https://raw.githubusercontent.com/norhther/idealista/main/idealistaBCN.csv")
df.drop("info", axis = 1, inplace = True)
df["floor"].fillna(1, inplace=True)
df.drop("neigh", axis = 1, inplace = True)
df.dropna(inplace = True)
df = df[df["habs"] < 11]
X = df.drop("price", axis = 1)
y = df["price"]
X_train, X_test, y_train, y_test = train_test_split(X, y, test_size = 0.2, random_state = 42)
ct = ColumnTransformer(
[("standardScaler", StandardScaler(), ["habs", "m2", "floor"]),
("onehot", OneHotEncoder(), ["type"]
)], remainder = "passthrough")
pipe = Pipeline(steps = [("Transformer", ct),
("svr", SVR())])
param_grid = {
"svr__kernel" : ['linear', 'poly', 'rbf', 'sigmoid'],
"svr__degree" : range(3,6),
"svr__gamma" : ['scale', 'auto'],
"svr__coef0" : np.linspace(0.01, 1, 2)
}
search = GridSearchCV(pipe, param_grid, scoring = ['neg_mean_squared_error'], refit='neg_mean_squared_error')
search.fit(X_train, y_train)
print(search.best_score_)
pipe = Pipeline(steps = [("Transformer", ct),
("svr", SVR(coef0 = search.best_params_["svr__coef0"],
degree = search.best_params_["svr__degree"],
kernel =
search.best_params_["svr__kernel"]))])
from sklearn.metrics import mean_squared_error
pipe.fit(X_train, y_train)
preds = pipe.predict(X_train)
mean_squared_error(preds, y_train)
А search.best_score_
здесь -443829697806.1671
, а MSE
это 608953977916.3896
Я думаю, что я что-то напутал, может быть, с трансформатором, но я не совсем уверен. Я думаю, что это преувеличение MSE
. Я сделал ужасно похожий подход с tidymodels
и получил гораздо лучшие результаты.
Так вот я хотел узнать, что-то не так с трансформатором, или это просто модель такая плохая.
Причина в том, что вы не включили C в параметр, и вам нужно охватить весь диапазон C, чтобы соответствовать. Если мы сопоставим его со значением по умолчанию C = 1, вы увидите, в чем заключается проблема:
import matplotlib.pyplot as plt
o = pipe.named_steps["Transformer"].fit_transform(X_train)
mdl = SVR(C=1)
mdl.fit(o,y_train)
plt.scatter(mdl.predict(o),y_train)
Есть некоторые значения цен, которые в 10 раз превышают средние значения (1e7 против медианы 5e5). Если вы используете mse или r ^ 2, они будут в значительной степени определяться этими экстремальными значениями. Поэтому нам нужно более внимательно следить за данными, и это решает C, о котором вы можете прочитать больше здесь. Пробуем диапазон:
ct = ColumnTransformer(
[("standardScaler", StandardScaler(), ["habs", "m2", "floor"]),
("onehot", OneHotEncoder(), ["type"]
)], remainder = "passthrough")
pipe = Pipeline(steps = [("Transformer", ct),
("svr", SVR())])
#, 'poly', 'rbf', 'sigmoid'
param_grid = {
"svr__kernel" : ['rbf'],
"svr__gamma" : ['auto'],
"svr__coef0" : [1,2],
"svr__C" : [1e-03,1e-01,1e1,1e3,1e5,1e7]
}
search = GridSearchCV(pipe, param_grid, scoring = ['neg_mean_squared_error'],
refit='neg_mean_squared_error')
search.fit(X_train, y_train)
print(search.best_score_)
-132061065775.25969
Ваши значения y высоки, а значения MSE будут находиться в диапазоне дисперсии ваших значений y, поэтому, если мы проверим это:
y_train.var()
545423126823.4545
132061065775.25969 / y_train.var()
0.24212590057261346
Это вполне нормально, вы уменьшаете MSE примерно до 25% дисперсии. Мы можем проверить это с помощью тестовых данных, и я думаю, в этом случае нам очень повезло, что значения C вполне в порядке:
from sklearn.metrics import mean_squared_error
o = pipe.named_steps["Transformer"].fit_transform(X_train)
mdl = SVR(C=10000000.0, coef0=1, gamma='auto')
mdl.fit(o,y_train)
o_test = pipe.named_steps["Transformer"].fit_transform(X_test)
pred = mdl.predict(o_test)
print( mean_squared_error(pred,y_test) , mean_squared_error(pred,y_test)/y_test.var())
plt.scatter(mdl.predict(o_test),y_test)
чем больше ваши целевые значения, тем больше будет ваш MSE?
Спасибо за ответ. Один вопрос: что означает видеть
MSE
в вариациях обучения, а не в обычных значениях?