前回 hpgenselect
プロシジャで罰則付きロジスティック回帰を実行してみた。
【SAS】hpgenselect プロシジャ_罰則付きロジスティック回帰(LASSO) - こちにぃるの日記
目的変数が連続値の時のLASSO回帰をやってなかったのでまとめてみる。
ついでにElasticNet回帰もやってみる。
【目次】
- 使用データ
- データ分割
- LASSO回帰 Hold-out法
- LASSO回帰 Cross-validation法
- ElasticNet回帰 Hold-out法
- ElasticNet回帰 Cross-Validation法
- モデル評価
- 参考
使用データ
SASHELP
にあるベースボールデータを使用する。選手のヒット数、エラー数などの成績から年俸(対数)を予測してみる。
*-- データ; data ads; set sashelp.baseball; if cmiss(of n:, of Cr:, logSalary, Division, League) = 0; if Division="West" then Division_West =1; else Division_West =0; *One-hot encoding; if League="American" then League_American=1; else League_American=0; *One-hot encoding; run;
データ分割
ベースボールデータの2割をテストデータとする。
ホールドアウト法用に残り8割を 7 : 3 = 訓練データ : バリデーションデータ に細分する。
*-- データ分割; proc surveyselect data=ads rate=0.2 out=ads outall method=srs seed=19; run; data train(drop=selected) test(drop=selected); set ads; if selected=1 then output test; else output train; run; proc surveyselect data=train rate=0.3 out=train outall method=srs seed=19; run; proc format; value rollf 0="train-data" 1="validation-data" 2="test-data"; run; data alldata; format selected selected2 rollf.; *-- フォーマット適用; set train test(in=in1); if in1 then do; selected =2; *-- テストデータに番号振る; selected2=2; end; else selected2=0; run;
LASSO回帰 Hold-out法
ホールドアウト法においては、partition statement
で訓練データと検証データを指定できる。
なお、model statement
の option に stb
を入れると偏回帰係数を出してくれる。
*-- ラッソ回帰; ods graphics on; proc glmselect data=train plots=all seed=19; partition roleVar=selected(train='0' validate='1'); model logSalary = nAtBat nHits nHome nRuns nRBI nBB nOuts nAssts nError CrAtBat CrHits CrHome CrRuns CrRbi CrBB Division_West League_American / details=all stats=all selection=lasso(choose=validate stop=none) stb; code file="glmselect_lasso.sas"; run; ods graphics off; data pred_lasso; format selected selected2 logSalary P_logSalary; set alldata; %include glmselect_lasso; run;
LASSO回帰 Cross-validation法
クロスバリデーションでは model statement
で selection=lasso(choose=cv) cvmethod=random(10)
とする。
random(k)
で k-fold cross-validation になる。なお、seedも指定可能。
*-- ラッソ回帰 CV; ods graphics on; proc glmselect data=train plots=all seed=19; model logSalary = nAtBat nHits nHome nRuns nRBI nBB nOuts nAssts nError CrAtBat CrHits CrHome CrRuns CrRbi CrBB Division_West League_American / details=all stats=all selection=lasso(choose=cv stop=none) cvmethod=random(10) stb; score out=score_lasso_cv predicted residual; code file="glmselect_lasso_cv.sas"; run; ods graphics off; data pred_lasso_cv; format selected2 logSalary P_logSalary; set alldata; %include glmselect_lasso_cv; run;
ElasticNet回帰 Hold-out法
ElasticNetもLassoと基本は同じ。
L2正則化項の係数を指定でき、グリッドサーチも可能。selection=elasticnet(choose=validate l2search=grid showl2search)
とする。
showl2search
を入れると最終決定値を表示できる。
もちろん、係数を直接指定することもできる。例:selection=elasticnet(choose=validate l2=0.5)
*-- ElasticNet回帰 ; ods graphics on; proc glmselect data=train plots=all seed=19; partition roleVar=selected(train='0' validate='1'); model logSalary = nAtBat nHits nHome nRuns nRBI nBB nOuts nAssts nError CrAtBat CrHits CrHome CrRuns CrRbi CrBB Division_West League_American / details=all stats=all selection=elasticnet(choose=validate l2search=grid showl2search stop=none) stb ; score out=score_elasticnet predicted residual; code file="glmselect_elasticnet_l2grid.sas"; run; ods graphics off; data pred_elasticnet_l2grid; format selected selected2 logSalary P_logSalary; set alldata; %include glmselect_elasticnet_l2grid; run;
ElasticNet回帰 Cross-Validation法
クロスバリデーションについても Lassoと同じ。
*-- ElasticNet回帰; ods graphics on; proc glmselect data=train plots=all seed=19; model logSalary = nAtBat nHits nHome nRuns nRBI nBB nOuts nAssts nError CrAtBat CrHits CrHome CrRuns CrRbi CrBB Division_West League_American / details=all stats=all selection=elasticnet(choose=cv l2search=grid showl2search stop=none) cvmethod=random(10) stb; score out=score_elasticnet predicted residual; code file="glmselect_elasticnet_cv_l2grid.sas"; run; ods graphics off; data pred_elasticnet_cv_l2grid; format selected selected2 logSalary P_logSalary; set alldata; %include glmselect_elasticnet_cv_l2grid; run;
今回は L2=0
でLasso回帰と等価になった。
モデル評価
モデル評価指標を複数並べたいので自作する。
*-- 評価指標; %macro _Scores(inds=, act=logSalary, pred=P_logSalary, group=); proc sql; create table &inds._Scores as select %if &group.^="" %then %do; &group. , %end; count(*) as N ,sum(abs(&pred. - &act.)) / count(*) as MAE label="平均絶対誤差(MAE:Mean Absolute Error)" ,sum((&pred. - &act.)**2) / count(*) as MSE label="平均二乗誤差(MSE:Mean Squared Error)" ,sqrt(calculated MSE) as RMSE label="MSEの平方根(RMSE:Root Mean Squared Error)" ,sum(abs((&pred. - &act.) / &act.)) / count(*) as MAPE label="平均絶対誤差(MAE:Mean Absolute Error)" ,sum(((&pred. - &act.) / &act.)**2) / count(*) as MSPE label="平均二乗パーセント誤差(MSPE:Mean Squared Percentage Error)" ,sqrt(calculated MSPE) as RMSE as RMSPE label="平均二乗パーセント誤差の平方根(RMSPE:Root Mean Squared Percentage Error)" from &inds. %if &group.^="" %then %do; group by &group. %end; ; quit; title "&inds."; proc print data=&inds._Scores; run; title ""; %mend _Scores; %_Scores(inds=pred_lasso, group=selected); %_Scores(inds=pred_lasso_cv, group=selected2); %_Scores(inds=pred_elasticnet_l2grid, group=selected); %_Scores(inds=pred_elasticnet_cv_l2grid, group=selected2);
RMSEで見ると今回はクロスバリデーションで作ったモデルが良好な予測性能。
参考
https://support.sas.com/documentation/onlinedoc/stat/131/glmselect.pdf