Lasso回帰でパラメータのalphaを変化させるとどんな風に特徴量が選択されていくのか見てみました。
特徴量が選択されて削減されると言っても、どの特徴量が削られていくか気になるね。
Lasso回帰でもalphaというパラメータが存在していて、この値を大きくすると、過学習を防ぐように働くとのことです。alphaの値が大きいと、どのように重みが変化しているのかをボストンの住宅価格データでみてみました。また、以前行った手動での特徴量選択と比較してみたいと思いました。
特徴量選択については、こちらの記事もご参考ください。
こんな人の役にたつかも
・機械学習プログラミングを勉強している人
・scikit-learnのLasso回帰の勉強をしている人
・scikit-learnnのLassoCVについて知りたい人
プログラムで確認してみよう
今回、Lasso回帰がどんな風に特徴量を削減していくのか、という点をみてみようと思いましたので、特徴量選択を行わないボストン価格データを「X」とします。
また、訓練データとテストデータに分割後、特徴量を手動で選択したものを「X_train_select」と「X_test_select」としています。分割後に特徴量選択を行うように変更したのは、「X_train」と「X_train_select」が同じtrain_test_splitのデータを元にするようにしたかったからです。
Lasso回帰には「X_train」を使用、線形回帰には「X_train_select」を利用することで、それぞれの特徴量選択の比較ができます。
from sklearn.datasets import load_boston
from sklearn import linear_model
from sklearn.model_selection import train_test_split
panda_box = load_boston()
X = panda_box.data
y = panda_box.target
#訓練データとテストデータに分割(テストデータ25%)
X_train, X_test, y_train, y_test = train_test_split(X, y, test_size = 0.25)
#0:CRIM 1:ZN 2:INDUS 3:CHAS 4:NOX 5:RM 6:AGE 7:DIS 8:RAD 9:TAX 10:PTRATIO 11:B 12:LSTAT
X_train_select = X_train[:,[0, 1, 2, 3, 5, 8, 10, 11, 12]]
X_test_select = X_test[:,[0, 1, 2, 3, 5, 8, 10, 11, 12]]
alpha=0.1
まずは、Lasso回帰のalpha=0.1です。パラメータのmax_iterはこのくらいの数値を入れておくと警告が出ません。
#Lasso回帰 alpha 0.1
lasso = linear_model.Lasso(alpha=0.1, max_iter=100000).fit(X_train, y_train)
print("=== Lasso alpha=0.1 ===")
print("決定係数")
print(lasso.score(X_test, y_test))
print("重み")
print(lasso.coef_)
=== Lasso alpha=0.1 ===
決定係数
0.6967882475601533
重み
[-8.22265817e-02 4.10828350e-02 -3.71980472e-02 2.23185861e+00
-0.00000000e+00 3.83914061e+00 2.66533305e-03 -9.74606827e-01
2.79279627e-01 -1.38420212e-02 -7.22910881e-01 8.62771049e-03
-6.11339673e-01]
0.1程度だとまだ0になる重みはないね。
alpha=1
次に、alpha=1にした時です。
#Lasso回帰 alpha 1
lasso = linear_model.Lasso(alpha=1, max_iter=100000).fit(X_train, y_train)
print("=== Lasso alpha=1 ===")
print("決定係数")
print(lasso.score(X_test, y_test))
print("重み")
print(lasso.coef_)
=== Lasso alpha=1 ===
決定係数
0.6617980086838072
重み
[-0.04641981 0.04459293 -0. 0. -0. 1.08708663
0.03612284 -0.47122791 0.25858992 -0.01442261 -0.66288517 0.0079368
-0.80925382]
影響が少ないと判断された、INDUSとCHAS、NOXが0になりました。
0:CRIM 1:ZN 2:INDUS 3:CHAS 4:NOX 5:RM 6:AGE 7:DIS 8:RAD 9:TAX 10:PTRATIO 11:B 12:LSTAT
alpha=10
次にalpha=10です。
#Lasso回帰 alpha 10
lasso = linear_model.Lasso(alpha=10, max_iter=100000).fit(X_train, y_train)
print("=== Lasso alpha=10 ===")
print("決定係数")
print(lasso.score(X_test, y_test))
print("重み")
print(lasso.coef_)
=== Lasso alpha=10 ===
決定係数
0.5215105502822736
重み
[-0. 0.02630739 -0. 0. 0. 0.
0. -0. 0. -0.00785992 -0. 0.00822231
-0.59952539]
かなり多くの特徴量が0となってしまいました。手動で選択した特徴量「RM」はかなり有力な特徴量だと思いましたが、ここでは0となっています。また、決定係数は52%となり、精度もかなり悪くなってしまいました。
手動で特徴量選択した線形回帰
reg = linear_model.LinearRegression().fit(X_train_select, y_train)
print(reg.score(X_test_select, y_test))
print(reg.coef_)
決定係数
0.6500767863376524
重み
[-0.06375633 -0.00733977 -0.01818399 4.23596306 4.56992751 0.10473634
-0.87730867 0.00865738 -0.56134587]
今回は、手動で特徴量選択をしたものより、alpha=0.1のLasso回帰の方が決定係数がよくなりました。
LassoCVというものもある
Ridge回帰の時もRidgeCVという、複数のパラメータ全ての交差検証を行っていちばん精度の良いパラメータ設定にしてくれるsciit-learnの便利機能がありました。
Lasso回帰にも存在していて、これも同じように利用することができます。先ほど個別にalphaを0.1〜10と三回に分けて記載していたものが次のように短縮できます。
l_cv = linear_model.LassoCV(alphas=[0.1, 1, 10], cv = 5, max_iter=100000).fit(X_train, y_train)
#一番よかったalphaの決定係数
print("{:.4f}" .format(l_cv.score(X_test, y_test)))
#一番よかったalpha
print(l_cv.alpha_)
#重み
print(l_cv.coef_)
#切片
print(l_cv.intercept_)
一番よかったalphaの決定係数
0.6968
一番よかったalpha
0.1
重み
[-8.22265817e-02 4.10828350e-02 -3.71980472e-02 2.23185861e+00
-0.00000000e+00 3.83914061e+00 2.66533305e-03 -9.74606827e-01
2.79279627e-01 -1.38420212e-02 -7.22910881e-01 8.62771049e-03
-6.11339673e-01]
切片
23.139614734437025
一番よかったalpha=0.1で精度が69%と先ほどの結果に一致しています。いくつかのLasso回帰パラメータで一番良いものを選択したい場合、このように簡略化することができます。
やはりあったか、LassoCV