
機械学習で特徴量を正しく選択する方法
2020.08.27
特徴量を選択する3つの方法
本記事で、機械学習での特徴量を選択する方法について解説していきます。
特徴量を選択することで、『モデルの精度を上げたり』『計算時間を短縮することができる』などのメリットがあります。
今回は、「Kaggle」の中でも、特に有名なTitanic: Machine Learning from Disasterを扱い、特徴量を正しく選択する方法について解説していきます。
Kaggle(カグル)とは
Kaggle(カグル)は、企業や研究者がデータを投稿し、世界中の統計家やデータ分析家がその最適モデルを競い合う、予測モデリング及び分析手法関連プラットフォームです。
【Titanic: Machine Learning from Disaster】
機械学習を使用して、どの乗客がタイタニック号の難破船を生き延びたかを予測するモデルを作成します。
https://www.kaggle.com/c/titanic
こちらの記事もオススメ!
Filter Method
Filter法は、目的変数と特徴量から、相関係数やカイ2乗などの統計量を計算し、特徴量を選択する方法です。
「特徴量」と「目的変数」を一対一でみるので、特徴量同士の関係は考慮しない比較的簡単な選択方法になります。
相関係数を利用する方法では、相関係数の絶対値が大きい順に特徴量を選択します。
それでは、実際にタイタニックのデータを利用して実装していきたいと思います!
データの確認
まずは、データの確認してみましょう。
1 2 | train = pd.read_csv("train.csv") train.head() |
欠損値の有無を確認
次に、欠損値の有無を確認します。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 | print(train.isnull().sum()) #PassengerId 0 #Survived 0 #Pclass 0 #Name 0 #Sex 0 #Age 177 #SibSp 0 #Parch 0 #Ticket 0 #Fare 0 #Cabin 687 #Embarked 2 #dtype: int64 |
「Age」「Cabin」「Embarked」に欠損値があることが分かりました。
「Age」はシンプルに平均値で置換し、「Embarked」は最頻値で置換します。
「Cabin」は欠損値が多いので、今回は特徴量に入れません。
1 2 3 | train["Age"] = train["Age"].fillna(train["Age"].mean()) train['Embarked'] = train["Embarked"].fillna(train["Embarked"].mode().iloc[0]) |
get_dummies関数を使って数値にする
相関係数を求めるには、「数値」に直す必要があります。
そのため、get_dummies関数を使って数値にします。
なお、今回は、数値に直すことが難しい「Name」「Ticket」は除きます。
1 2 3 4 5 6 7 8 | <span style="font-weight: 400;">train[</span><span style="font-weight: 400;">'Sex'</span><span style="font-weight: 400;">] = pd.get_dummies(train[</span><span style="font-weight: 400;">'Sex'</span><span style="font-weight: 400;">])</span> <span style="font-weight: 400;">train_emb = pd.get_dummies(train[</span><span style="font-weight: 400;">'Embarked'</span><span style="font-weight: 400;">])</span> <span style="font-weight: 400;">trainX = pd.concat([train[</span><span style="font-weight: 400;">'PassengerId'</span><span style="font-weight: 400;">],train[</span><span style="font-weight: 400;">'Pclass'</span><span style="font-weight: 400;">],train[</span><span style="font-weight: 400;">'Age'</span><span style="font-weight: 400;">],</span> <span style="font-weight: 400;"> </span> <span style="font-weight: 400;">train[</span><span style="font-weight: 400;">'SibSp'</span><span style="font-weight: 400;">],train[</span><span style="font-weight: 400;">'Parch'</span><span style="font-weight: 400;">],train[</span><span style="font-weight: 400;">'Fare'</span><span style="font-weight: 400;">],</span> <span style="font-weight: 400;"> </span> <span style="font-weight: 400;">train_sex,train_emb],axis=</span><span style="font-weight: 400;">1</span><span style="font-weight: 400;">)</span> <span style="font-weight: 400;">trainX.head()</span> |
相関係数を求める
これで、相関係数を求めることができるようになりました。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 | trainY = train['Survived'] #目的変数 corrs = [] features = trainX.columns for c in features: corr = np.corrcoef(trainX[c], trainY)[0, 1] corrs.append(corr) corrs = np.array(corrs) idx = np.argsort(np.abs(corrs))[::-1] #重要度上位3つを格納 cols = trainX.columns.values[idx][:3] importances = corrs[idx][:3] print(cols, importances) # ['Sex' 'Pclass' 'Fare'] [ 0.54335138 -0.33848104 0.25730652] |
出力結果を見てみると、Sex(性別)が最も相関係数が大きいことが分かりました。
重要度を可視化
次に、重要度を可視化してみましょう。
1 2 3 4 5 6 7 | feature_importances = pd.DataFrame() feature_importances['feature'] = features feature_importances['importance'] = abs(corrs) <span style="font-weight: 400;">feature_importances = feature_importances.sort_values(by=</span><span style="font-weight: 400;">'importance'</span><span style="font-weight: 400;">, ascending=</span><span style="font-weight: 400;">False</span><span style="font-weight: 400;">)</span> plt.figure(figsize=(16, 8)) sns.barplot(data=feature_importances.head(10), x='importance', y='feature') |
グラフ
分析
全体的にみてみると、Sex(性別)が特に重要度が高いことがよくわかりますね。
それに対して、PassengerId や Q は重要度が低い結果になりました。
Wrapper Method
Wrapper法は、特徴量の組み合わせを変えてモデルを学習させて、性能を評価することを繰り返して特徴量を選択する方法です。
繰り返し学習するので、計算コストが高いことを覚えておきましょう。
Wapper法 3つの方法
Warapper法は、以下の3つの方法に分けることができます。
- 特徴量をひとつずつ減らしていく方法
- ひとつずつ増やしていく方法
- すべての組み合わせを試す方法
mlxtendを利用して実装
今回は、1つひとつずつ追加していく方法を、「mlxtend」を利用して実装していきます。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 | from sklearn.model_selection import train_test_split from sklearn.ensemble import RandomForestClassifier as RF from sklearn.metrics import roc_auc_score from mlxtend.feature_selection import SequentialFeatureSelector as SFS X_train, X_test, y_train, y_test = train_test_split( <span style="font-weight: 400;">trainX,</span> <span style="font-weight: 400;">trainY,</span> <span style="font-weight: 400;">test_size=</span><span style="font-weight: 400;">0.2</span><span style="font-weight: 400;">,</span> <span style="font-weight: 400;">random_state=</span><span style="font-weight: 400;">2019</span> ) sfs1 = SFS(RF(n_jobs=4), <span style="font-weight: 400;"> </span> <span style="font-weight: 400;">k_features=</span><span style="font-weight: 400;">10</span><span style="font-weight: 400;">,</span> <span style="font-weight: 400;"> </span> <span style="font-weight: 400;">forward=</span><span style="font-weight: 400;">True</span><span style="font-weight: 400;">,</span> <span style="font-weight: 400;"> </span> <span style="font-weight: 400;">floating=</span><span style="font-weight: 400;">False</span><span style="font-weight: 400;">,</span> <span style="font-weight: 400;"> </span> <span style="font-weight: 400;">verbose=</span><span style="font-weight: 400;">3</span><span style="font-weight: 400;">,</span> <span style="font-weight: 400;"> </span> <span style="font-weight: 400;">scoring=</span><span style="font-weight: 400;">'roc_auc'</span><span style="font-weight: 400;">,</span> <span style="font-weight: 400;"> </span> <span style="font-weight: 400;">cv=</span><span style="font-weight: 400;">3</span><span style="font-weight: 400;">)</span> sfs1 = sfs1.fit(X_train, y_train) |
これで、ひとつずつ特徴量を追加して精度をみることで、特徴量を選択することができます。
Embedded Method
Embedded法は、モデルの重要度を利用して特徴量を選択する方法です。
Lasso回帰や、木モデルなどがよく利用されます。
ランダムフォレストを使用して解説
今回は、「ランダムフォレスト」を使用して解説していきます。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 | from sklearn.ensemble import RandomForestClassifier as RF clf = RF(random_state=2019) clf.fit(trainX, trainY) features = trainX.columns fi = clf.feature_importances_ idx = np.argsort(fi)[::-1] cols = features.values[idx][:3] importances = fi[idx][:3] print(cols, importances) # ['Sex' 'Fare' 'PassengerId'] [0.23151801 0.20317807 0.19022855] |
ランダムフォレストを利用しても、Sex(性別)が一番重要度が高いという結果がでました。
可視化したデータ
では、可視化したデータもみてみましょう!
分析
グラフを見てみると、「Sex」「Fare」「PassengerId」「Age」が重要度が高いことがわかります。
それに対して、「Embarked」は重要度が低くなっています。
まとめ
機械学習で特徴量を選択する方法として
- Filter法
- Wrapper法
- Embedded法
を紹介しました。
今回は、例として特徴量が少ない課題を扱いましたが、特徴量の数が大量にある場合には正しく特徴量選択することがより重要になります。
特徴量を正しく選択できるようになれば、データサイエンティストとしてさらに大きく成長できることでしょう!
(株)ライトコードは、WEB・アプリ・ゲーム開発に強い、ITが大好きな会社です。
機械学習でのシステム開発依頼・お見積もりはこちらまでお願いします。
また、機械学習系エンジニアを積極採用中です!詳しくはこちらをご覧ください。
※現在、多数のお問合せを頂いており、返信に、多少お時間を頂く場合がございます。
こちらの記事もオススメ!
書いた人はこんな人

- 「好きを仕事にするエンジニア集団」の(株)ライトコードです!
ライトコードは、福岡、東京、大阪の3拠点で事業展開するIT企業です。
現在は、国内を代表する大手IT企業を取引先にもち、ITシステムの受託事業が中心。
いずれも直取引で、月間PV数1億を超えるWebサービスのシステム開発・運営、インフラの構築・運用に携わっています。
システム開発依頼・お見積もり大歓迎!
また、現在「WEBエンジニア」「モバイルエンジニア」「営業」「WEBデザイナー」「WEBディレクター」を積極採用中です!
インターンや新卒採用も行っております。
以下よりご応募をお待ちしております!
https://rightcode.co.jp/recruit
ITエンタメ10月 13, 2023Netflixの成功はレコメンドエンジン?
ライトコードの日常8月 30, 2023退職者の最終出社日に密着してみた!
ITエンタメ8月 3, 2023世界初の量産型ポータブルコンピュータを開発したのに倒産!?アダム・オズボーン
ITエンタメ7月 14, 2023【クリス・ワンストラス】GitHubが出来るまでとソフトウェアの未来