Autor notebooka: Jakub Nowacki.
Regresja liniowa jest jedną z podstawowych, niemniej nadal często wykorzystywanych rodzajów regresji. Przećwiczymy ją na przykładowym zbiorze danych związanych z cukrzycą.
In [15]:
import matplotlib.pyplot as plt
import numpy as np
from sklearn import datasets, linear_model
from sklearn.metrics import mean_squared_error, r2_score
%matplotlib inline
plt.rcParams['figure.figsize'] = (10, 8)
# Zbiór danych
diabetes = datasets.load_diabetes()
print(diabetes.DESCR)
In [16]:
diabetes.keys()
Out[16]:
In [17]:
diabetes.data
Out[17]:
In [18]:
diabetes.data.shape
Out[18]:
In [19]:
diabetes.feature_names
Out[19]:
In [20]:
diabetes.target
Out[20]:
Dla lepszej jasności przykładu użyjmy jednego atrybutu do przeprowadzenia regresji.
In [21]:
diabetes_X = diabetes.data[:, np.newaxis, 2] # wyciągamy jako wektor kolumnowy (nie trzeba tego robić jak mamy więcej niż jedną kolumnę)
# Dzielimy dane na zbiory treningowy i testowy
diabetes_X_train = diabetes_X[:-20]
diabetes_X_test = diabetes_X[-20:]
diabetes_y_train = diabetes.target[:-20]
diabetes_y_test = diabetes.target[-20:]
In [22]:
diabetes_X_train[:5], diabetes_y_train[:5]
Out[22]:
In [23]:
# Tworzymy obiekt modelu i go uczymy
regr = linear_model.LinearRegression()
regr.fit(diabetes_X_train, diabetes_y_train)
Out[23]:
Teraz możemy sprawdzić czy model dobrze się uczy i jak przewiduje na danych testowych.
In [24]:
diabetes_y_pred = regr.predict(diabetes_X_test)
diabetes_y_pred
Out[24]:
Możemy przeprowadzić teraz ocenę jakości modelu.
In [25]:
print('Współczynniki: \n', regr.coef_)
print("Błąd średniokwadratowy: %.2f"
% mean_squared_error(diabetes_y_test, diabetes_y_pred))
print('Metryka R2 (wariancji): %.2f' % r2_score(diabetes_y_test, diabetes_y_pred))
Narysujmy też predykcje naszego modelu na wykresie.
In [26]:
plt.scatter(diabetes_X_test, diabetes_y_test, color='black')
plt.scatter(diabetes_X_train, diabetes_y_train, color='red')
plt.plot(diabetes_X_test, diabetes_y_pred, color='blue', linewidth=3)
plt.show()
In [27]:
diabetes_X = diabetes.data # wyciągamy jako wektor kolumnowy (nie trzeba tego robić jak mamy więcej niż jedną kolumnę)
diabetes_X
Out[27]:
In [29]:
# diabetes_X = diabetes.data[:, np.newaxis, 2] # np.newaxis - wyciągamy jako wektor kolumnowy (nie trzeba tego robić jak mamy więcej niż jedną kolumnę)
diabetes_X = diabetes.data[:, [1, 2, 3]]
#diabetes_X = diabetes.data[:, np.newaxis, 2]
# Dzielimy dane na zbiory treningowy i testowy
diabetes_X_train = diabetes_X[:-20]
diabetes_X_test = diabetes_X[-20:]
diabetes_y_train = diabetes.target[:-20]
diabetes_y_test = diabetes.target[-20:]
# Tworzymy obiekt modelu i go uczymy
regr = linear_model.LinearRegression()
regr.fit(diabetes_X_train, diabetes_y_train)
diabetes_y_pred = regr.predict(diabetes_X_test)
print('Współczynniki: \n', regr.coef_)
print("Błąd średniokwadratowy: %.2f"
% mean_squared_error(diabetes_y_test, diabetes_y_pred))
print('Metryka R2 (wariancji): %.2f' % r2_score(diabetes_y_test, diabetes_y_pred))
plt.scatter(diabetes_X_test[:,2], diabetes_y_test, color='black')
plt.scatter(diabetes_X_train[:,2], diabetes_y_train, color='red')
plt.plot(diabetes_X_test[:,2], diabetes_y_pred, color='blue', linewidth=3)
plt.show()
In [30]:
import pandas as pd
dia_df = pd.DataFrame(diabetes.data, columns=diabetes.feature_names)\
.assign(target=diabetes.target)
dia_df.head()
Out[30]:
In [31]:
dia_train = dia_df.iloc[:-20, :]
dia_train.head(20)
Out[31]:
In [32]:
dia_test = dia_df.iloc[-20:, :]
dia_test
Out[32]:
In [33]:
lr = linear_model.LinearRegression()
lr.fit(dia_train[['age', 'sex', 'bmi']], dia_train['target'])
Out[33]:
In [34]:
dia_test = dia_test.assign(predict=lambda x: lr.predict(x[['age', 'sex', 'bmi']]))
dia_test
Out[34]:
In [35]:
print('Współczynniki: \n', lr.coef_)
print("Błąd średniokwadratowy: %.2f"
% mean_squared_error(dia_test['target'], lr.predict(dia_test[['age', 'sex', 'bmi']])))
print('Metryka R2 (wariancji): %.2f' % r2_score(dia_test['target'], dia_test['predict']))
In [37]:
import pandas as pd
def model(dataframe, features, target, procent_testowy=20):
dia_df = pd.DataFrame(diabetes.data, columns=diabetes.feature_names).assign(target=diabetes.target)
# Podiał zbioru na testowy i treningowy
dia_train = dia_df.iloc[:-procent_testowy, :]
dia_test = dia_df.iloc[-procent_testowy:, :]
lr = linear_model.LinearRegression()
lr.fit(dia_train[['bmi']], dia_train['target'])
dia_test = dia_test.assign(predict=lambda x: lr.predict(x[['bmi']]))
print('Współczynniki: \n', lr.coef_)
print("Błąd średniokwadratowy: %.2f" % mean_squared_error(dia_test['target'], lr.predict(dia_test[['bmi']])))
print('Metryka R2 (wariancji): %.2f' % r2_score(dia_test['target'], dia_test['predict']))
Aby wybrać odpowiedni model, który odpowiednio generalizuje, używa się technik regularyzacji. Dwie najbardziej znane techniki to Lasso, czyli regularyzacja L1, oraz Ridge, czyli regularyzacja L2. Poniżej przykłady wykorzystania tych algorytmów.
In [38]:
ridge = linear_model.Ridge()
ridge.fit(dia_train[['age', 'sex', 'bmi']], dia_train['target'])
Out[38]:
In [39]:
dia_test = dia_test.assign(predict=lambda x: ridge.predict(x[['age', 'sex', 'bmi']]))
dia_test
Out[39]:
In [40]:
print('Współczynniki: \n', ridge.coef_)
print("Błąd średniokwadratowy: %.2f"
% mean_squared_error(dia_test['target'], ridge.predict(dia_test[['age', 'sex', 'bmi']])))
print('Metryka R2 (wariancji): %.2f' % r2_score(dia_test['target'], dia_test['predict']))
In [41]:
lasso = linear_model.Lasso()
lasso.fit(dia_train[['age', 'sex', 'bmi']], dia_train['target'])
Out[41]:
In [42]:
dia_test = dia_test.assign(predict=lambda x: lasso.predict(x[['age', 'sex', 'bmi']]))
dia_test
Out[42]:
In [ ]:
print('Współczynniki: \n', lasso.coef_)
print("Błąd średniokwadratowy: %.2f"
% mean_squared_error(dia_test['target'], lasso.predict(dia_test[['age', 'sex', 'bmi']])))
print('Metryka R2 (wariancji): %.2f' % r2_score(dia_test['target'], dia_test['predict']))
Jak widać parametry wypadły gorzej niż dla zwykłej regresji liniowej. Wynika to z faktu, że regularyzacje mają hipetparametry, które należy dostosować do problemy. Do tego zostały stworzone wersje z wbudowaną walidacją krzyżową (Cross-validation, która również dobiera hiperparametry.
In [55]:
lasso = linear_model.LassoCV(cv=5)
lasso.fit(dia_train[['age', 'sex', 'bmi']], dia_train['target'])
Out[55]:
In [52]:
dia_test = dia_test.assign(predict=lambda x: lasso.predict(x[['age', 'sex', 'bmi']]))
dia_test
Out[52]:
In [59]:
columns = ['age', 'sex', 'bmi', 'bp', 's1', 's2', 's3', 's4', 's5', 's6']
lasso = linear_model.LassoCV(cv=5)
lasso.fit(dia_train[columns], dia_train['target'])
dia_test = dia_test.assign(predict=lambda x: lasso.predict(x[columns]))
print('Współczynniki: \n', lasso.coef_)
print("Błąd średniokwadratowy: %.2f"
% mean_squared_error(dia_test['target'], lasso.predict(dia_test[columns])))
print('Metryka R2 (wariancji): %.2f' % r2_score(dia_test['target'], dia_test['predict']))
In [53]:
print('Współczynniki: \n', lasso.coef_)
print("Błąd średniokwadratowy: %.2f"
% mean_squared_error(dia_test['target'], lasso.predict(dia_test[['age', 'sex', 'bmi']])))
print('Metryka R2 (wariancji): %.2f' % r2_score(dia_test['target'], dia_test['predict']))
Zobaczmy co dzieje się w trakcie procesu walidacji krzyżowej. Algorytm liczy dla każdego podziału danych krzywą MSE w zależności od parametru alpha, jak pokazano poniżej.
In [54]:
plt.plot(-pd.np.log10(lasso.alphas_), lasso.mse_path_, linestyle='--');
plt.plot(-pd.np.log10(lasso.alphas_), lasso.mse_path_.mean(axis=1), 'k', linewidth=3);
plt.xlabel('$-log_{10}(alpha)$');
plt.ylabel('Mean Square Error (MSE)');
In [63]:
import matplotlib.pyplot as plt
import numpy as np
from sklearn import datasets, linear_model
from sklearn.metrics import mean_squared_error, r2_score
import pandas as pd
# %matplotlib inline
diabetes = datasets.load_diabetes()
dataframe = pd.DataFrame(diabetes.data, columns=diabetes.feature_names).assign(target=diabetes.target)
dane_treningowe = dataframe.iloc[:-20, :]
dane_testowe = dataframe.iloc[-20:, :]
columns = ['age', 'sex', 'bmi', 'bp', 's1', 's2', 's3', 's4', 's5', 's6']
model = linear_model.LassoCV(cv=5)
model.fit(dane_treningowe[columns], dane_treningowe['target'])
dane_testowe = dane_testowe.assign(predict=lambda x: model.predict(dane_treningowe[columns]))
print('Współczynniki: \n', model.coef_)
print("Błąd średniokwadratowy: %.2f" % mean_squared_error(dia_test['target'], model.predict(dane_testowe[columns])))
print('Metryka R2 (wariancji): %.2f' % r2_score(dane_testowe['target'], dane_testowe['predict']))