【24日目】スパースモデリングをやってみる【2021アドベントカレンダー】
2021年1人アドベントカレンダー(機械学習)、24日目の記事になります。
テーマは Lasso回帰を使ったスパースモデリング になります。
Lasso回帰とは、正則化された線形回帰の一つで、線形回帰のコスト関数に対して重みの合計を足したもの。
詳細は下記サイトを参照。
Lasso 回帰と Ridge 回帰の違いについては下記参照。
Colab のコードはこちら
LASSO 回帰によるスパースモデリング
alpha_lasso = []
coef_list = []
intercept_list = []
train_score = []
test_score = []
# 探索範囲
lasso_1 = np.linspace(0.01,100,1000)
for i in lasso_1:
model = Lasso(
alpha = i,
max_iter=10000,
random_state=SEED
)
# 学習
model.fit(X_train,y_train)
# 推論
pre_train = model.predict(X_train)
pre_test = model.predict(X_test)
# スコアの集約
alpha_lasso.append(i)
coef_list.append(model.coef_) # 回帰係数
intercept_list.append(model.intercept_) # 切片
train_score.append(model.score(X_train, y_train))
test_score.append(model.score(X_test, y_test)) # テストデータに対するR2スコア
# DataFrame、Series 化
df_count = pd.Series(alpha_lasso,name = 'alpha') # 正則化の強さ
df_coef= pd.DataFrame(coef_list, columns = X_train.columns) # 回帰係数
df_inter = pd.Series(intercept_list,name = 'intercept') # 切片
df_train_score = pd.Series(train_score,name = 'train_score') # 学習データに対するスコア
df_test_score = pd.Series(test_score,name = 'test_score') # テストデータに対するスコア
# alphaと回帰係数の可視化
plt.title('alpha vs coefficent graph like R/glmnet')
plt.xscale('log')
plt.xlabel('alpha')
plt.ylabel('coefficient')
plt.plot(df_count,df_coef)
plt.legend(labels = df_coef.columns,loc='uper right',fontsize=7)
plt.show()
# alphaとR2スコアのグラフ
df_score = pd.concat([df_train_score,df_test_score], axis=1)
plt.title('alpha vs R2 score(train/test)')
plt.xscale('log')
plt.xlabel('alpha')
plt.ylabel('r2_score')
plt.plot(df_count,df_score)
plt.legend(labels = df_score.columns,loc='uper right',fontsize=8)
plt.show()
alphaと回帰係数の可視化
alphaとR2スコアのグラフ
シンプルな学習・推論
alphaとR2スコアのグラフ をみると、alpha が 0.1 あたりが R2スコアが低くなっていますので、alpha に 0.1 を設定して学習・推論を行ってみます。
model = Lasso(
alpha = 0.1,
max_iter=10000,
random_state=SEED
)
# 学習
model.fit(X_train, y_train)
# 推論
y_pred = model.predict(X_test)
# 評価
rmse = mean_squared_error(y_test, y_pred, squared=False)
print("RMSE", rmse)
出力:
RMSE 0.9313807445033818
GroupKFold を使って Lasso 回帰
最も RMSE が小さくなる最適な alpha を可視化しながら探索してみます。
gkf = GroupKFold(n_splits=5)
groups = X_train["Genre"]
for i, (train_index, test_index) in enumerate(gkf.split(X_train, y_train, groups)):
X_train_gkf, X_test_gkf = X_train.iloc[train_index], X_train.iloc[test_index]
y_train_gkf, y_test_gkf = y_train.iloc[train_index], y_train.iloc[test_index]
# 探索
for alpha in range(-10, 20, 1):
model = Lasso(
alpha = alpha/10 ,
max_iter=10000,
random_state=SEED
)
# 学習
model.fit(X_train_gkf, y_train_gkf)
# 推論
y_pred = model.predict(X_test_gkf)
# 評価
rmse = mean_squared_error(y_test_gkf, y_pred, squared=False)
# 可視化
plt.scatter(
alpha/10,
rmse,
color="red"
)
plt.title(f"fold {i}")
plt.xlabel('alpha')
plt.ylabel('rmse')
plt.show()
alpha が 0 付近の時が 最も RMSE が小さくなっているようです。
LassoCV
LassoCV を使うとクロスバリデーションにより自動的に最適なパラメーターを探索することができます。
model = LassoCV(alphas=[0.01, -1, 2], cv = 5, max_iter=100000)
# 学習
model.fit(X_train, y_train)
# ベストスコア
print("Best alpha:", model.alpha_)
print("重み:", model.coef_)
print("切片:", model.intercept_)
# ベストスコア(alpha)を設定
best_model = Lasso(
alpha=model.alpha_,
max_iter=100000,
random_state=SEED
)
# ベストスコアで学習
best_model.fit(X_train, y_train)
# ベストスコアのモデルで推論
y_pred = best_model.predict(X_test)
# 評価
rmse = mean_squared_error(y_test, y_pred, squared=False)
print("RMSE", rmse)
出力:
Best alpha: 0.01
重み: [-0.00000000e+00 1.19582956e-01 5.16855133e-02 7.60801569e-03
0.00000000e+00 3.40944575e-02 0.00000000e+00 0.00000000e+00
4.57007862e-03 -0.00000000e+00 0.00000000e+00 -6.01479616e-04
-1.33607435e-05 3.14296420e-07 3.51993675e-04 -1.63156663e-06
6.92296310e-07]
切片: -0.05693081814503
RMSE 0.9232324622403981
24日目は以上になります、最後までお読みいただきありがとうございました。
参考サイト
Discussion