##PythonでRのglmnetで描かれるみたいなグラフが書いてみたかった
####PythonでLasso回帰の問題点は
とりあえずPython
でScikit-Learn
使ってLasso
回帰を計算している人はいますよね。私もPython
で計算しています。でも、R
のglmnet
で計算している人のLasso
のグラフを見るとうらやましく感じます。
Rのグラフは、こんなグラフです。。R/glmnet パッケージで LASSO によるスパース推定を行う方法から転載。
なんかわかりやすいですよね。$λ$(Pyhon
のScikit-Learn
ならalpha
です)が変化していくと、どう回帰係数が変化していくか一目瞭然です。でも、こういうのはScikit-Learn
には実装されていません。
私もこんなグラフ作りたーーーい!!と思って、今回python
のスクリプトを作りました。こういうグラフがないとスパースモデリングなんてできないよね。Scikit-Learn
で、スコアと回帰係数だけ出しても、Lasso
で行うスパースモデリングの実力を見ていないような気がするんですよね。
####Pythonでglmnetで出てくるみたいなグラフを作ってみた
そんなこんなで、For
文使って、自分で作ってみました。
いろいろ考えましたが、べたなやり方で、numpy
で作った数値をFor
文で、alpha
(lambda
)にいれながら、Lasso
回帰を繰り返して、回帰係数とスコアを計算しました。
# -*- coding: utf-8 -*-
from sklearn import datasets
from sklearn.model_selection import train_test_split
import pandas as pd
import numpy as np
import matplotlib.pyplot as plt
from sklearn.linear_model import Lasso
#ボストンのデータセットを読み込む
boston = datasets.load_boston()
alpha_lasso = []
coef_list = []
intercept_list = []
train_score = []
test_score = []
#print(boston['feature_names'])
#特徴量と目的変数をわける
X = boston['data']
y = boston['target']
X_train, X_test, y_train, y_test = train_test_split(X, y, train_size=0.8,random_state = 0)
#探索範囲を決めます
lasso_1 = np.linspace(0.01,100,1000)
for i in lasso_1:
#Lasso回帰モデルを訓練して作成
Lasso_regr = Lasso(alpha = i, max_iter=10000)
Lasso_regr.fit(X_train,y_train)
pre_train = Lasso_regr.predict(X_train)
pre_test = Lasso_regr.predict(X_test)
#結果の表示
print("alpha=",i)
print("訓練データにフィット")
print("訓練データの精度 =", Lasso_regr.score(X_train, y_train))
print("テストデータにフィット")
print("テストデータの精度 =", Lasso_regr.score(X_test, y_test))
alpha_lasso.append(i)
coef_list.append(Lasso_regr.coef_)
intercept_list.append(Lasso_regr.intercept_)
train_score.append(Lasso_regr.score(X_train, y_train))
test_score.append(Lasso_regr.score(X_test, y_test))
df_count = pd.Series(alpha_lasso,name = 'alpha')
df_coef= pd.DataFrame(coef_list,columns = boston.feature_names)
df_inter = pd.Series(intercept_list,name = 'intercept')
df_train_score = pd.Series(train_score,name = 'trian_score')
df_test_score = pd.Series(test_score,name = 'test_score')
#ここでalphaと回帰係数のグラフを作ります
plt.plot(df_count,df_coef)
plt.xscale('log')
plt.legend(labels = df_coef.columns,loc='lower right',fontsize=7)
plt.xlabel('alpha')
plt.ylabel('coefficient')
plt.title('alpha vs cosfficent graph like R/glmnet')
plt.show()
#ここでalphaと回帰係数のグラフを作ります
df_score = pd.concat([df_train_score,df_test_score], axis=1)
plt.plot(df_count,df_score)
plt.xscale('log')
plt.legend(labels = df_score.columns,loc='lower right',fontsize=8)
plt.xlabel('alpha')
plt.ylabel('r2_score')
plt.title('alpha vs score(train/test)')
plt.show()
こうやって、回帰係数をスパース化しているグラフとスコアのグラフを比較してみると、どのくらいにalpha
をしたらよいか、一目でわかります。デフォルトの1ではなくて、0.5あたりが良いような気がします。これ以上大きいとスコアが落ちるし、これより小さくしてもスコアがあがらないのに、スパース化するときにいらないと判断した特徴量が入ってくる。だから0.5あたりがちょうどよいような感じですね。
####Lassoで計算してスパースモデリングするなら!!
Lasso
で計算してスパースモデリングするなら、Python
でも、この2枚のグラフはいることがよくわかりました。