前回は特徴量を追加するアプローチで、特徴量エンジニアリングを行いました。
今回は、不要な特徴量を削除する、引き算の方向で進めていこうと思います。
▼タイタニック振り返り全体の流れ
#1 最低限の前処理+パラメータチューニングなしの3モデル+stratified-k-fold
#2 特徴量をいくつか追加投入
#3 RFEによる特徴選択を試みる
#4 モデルのパラメータチューニング
#5 アンサンブルその1:シンプルなブレンド
#6 アンサンブルその2:スタッキング
▼前2回の記事
特徴選択の方法
一般的に、特徴量を増やすと、モデルは複雑になり過剰適合の可能性が高くなる(=汎化性能が下がる)傾向があります。
そこで、特徴選択という特徴量を減らす考え方が生まれてくるわけですが、これを機械的に処理する様々な方法があります。
「Pythonではじめる機械学習」の4章ではその点について触れられていて、基本的な戦略として以下の3つがあげられています。
①単変量統計(univariance statistics):ANOVA、カイ二乗検定等
②モデルベース特徴量選択(model-based selection):モデルを1回用いる方法。決定木ベースモデルのfeature_importances_や、線形回帰におけるL1正則化等
③反復選択(iterative selection):異なる特徴量を用いた複数のモデルを作り、評価する。RFE等
今回は③の反復選択で特徴選択をしていこうと思います。
反復選択には2種類のアプローチがあり、
1つは、まったく特徴量を使わないところから、ある基準が満たされるところあで1つずつ特徴量を加えていく方法。
2つは、すべての特徴量を使う状態から、1つずつ特徴量を取り除いていく方法です。
この後者の方法として、RFE(recursive feature elimination)というものがあります。
すべての特徴量でモデルを作る
→そのモデルで最も重要度が低い特徴量を削除
→残った特徴量でまたモデルを作る
→そのモデルで最も重要度が低い特徴量を削除
→・・・
といった流れで1つずつ特徴量を減らしながらモデルを作っていき、ある基準を満たしたら終了します。
前回の続きからはじめて、最適な特徴量はどれか、RFEを用いて見定めていきたいと思います。
RFEの実装×3モデル
RFECVの使い方は以下の通りです。(RFECVはRFEにCVをくっつけたもの)
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 |
#警告を無視 import warnings warnings.filterwarnings(action="ignore", module="scipy", message="^internal gelsd") #RFE from sklearn.feature_selection import RFECV rfecv = RFECV(estimator=clf, step=1, scoring="accuracy") rfecv.fit(X_set,y_set) rfecv.transform(X_set) # 最良の特徴量の数 rfecv.n_features_ # 最良の特徴量を表示 rfecv.support_ |
事前にモデルを作っておいて、estimatoreにそれを引き渡します。
scoringで、どの指標を用いてスコアを計算するか指定します(accuracyは精度)
それをfit,transformすれば完了です。
n_features_では、最もスコアが高かった時の特徴量の数、
support_では、その時の特徴量はどれだったかをTrue,Falseで表示してくれます。
RF×RFECV
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 |
#前回と同じようにモデルを作る kf = StratifiedKFold(n_splits=10,shuffle=True,random_state=1) for i,(train_index,test_index) in enumerate(kf.split(X_set,y_set)): X_cv_train = X_set.iloc[train_index] X_cv_test = X_set.iloc[test_index] y_cv_train = y_set[train_index] y_cv_test = y_set[test_index] clf = RandomForestClassifier(random_state=1) clf.fit(X_cv_train,y_cv_train) #RFECV rfecv = RFECV(estimator=clf, step=1, scoring="accuracy") rfecv.fit(X_set,y_set) rfecv.transform(X_set) #重要度と選択されたかどうか f_importances = pd.DataFrame({"features":X_set.columns,"importances":clf.feature_importances_,"select":rfecv.support_}) print(f_importances) |

ランダムフォレストはfeature_importances_属性をもっているので、このように特徴量の重要度を表示することができます。
見ると、重要度が低い3つの特徴量がFalseとなっていますね。
ではこの3つを削除して、再度ファンダムフォレスト分類器にかけてみます。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 |
drop_elements = ["IsAlone","Embarked_C","Embarked_Q"] X_set_rf = X_set.drop(drop_elements,axis=1) test_rf = test.drop(drop_elements,axis=1) rf_scores_rfe = [] for i,(train_index,test_index) in enumerate(kf.split(X_set_rf,y_set)): X_cv_train = X_set_rf.iloc[train_index] X_cv_test = X_set_rf.iloc[test_index] y_cv_train = y_set[train_index] y_cv_test = y_set[test_index] clf = RandomForestClassifier(random_state=1) clf.fit(X_cv_train,y_cv_train) y_cv_pred = clf.predict(X_cv_test) acc = accuracy_score(y_cv_test,y_cv_pred) rf_scores_rfe.append(acc) |
CVスコアの平均は、0.811392861196232と、前回のスコア0.793541よりも向上がみられました!
XGB×RFECV
コードはほぼ同じなので、結果だけ貼ります。

RFに加えて、Parchも不要とみなされました。
LGBM×RFECV
こちらも結果のみです。

ここまでのまとめ
RFECVで特徴選択してから、再度作成したモデルの精度は以下の通り。
▼今回のスコア

▼前回のスコア

CVスコアはみな向上しましたが、RFに関してだけ、kaggleの実際の正解データの正解率は下がってしまっており、過学習してしまったのでしょうか、、。
特徴量エンジニアリングに関してはここまでにして、次回からはハイパーパラメータチューニングに取り組んでいこうと思います。
最後まで読んでいただきありがとうございました。
つづきはこちら↓
【Kaggle】タイタニックの振り返り#4 ランダムフォレストのパラメータチューニング