sklearnを活用した特徴量選択を整理した

* 製造業出身のデータサイエンティストがお送りする記事
* 今回はscikit-learnで使用できる特徴量選択手法を使ってみました。

##はじめに
回帰モデルや分類モデルを構築する際に、特徴量エンジニアリングは重要な要素です。その際、ドメイン知識を使って特徴量選択することが多いですが、scikit-learnを使用して目星を付ける方法を実施してみましたので整理します。

##RFEによる特徴量選択
RFE（Recursive Feature Elimination）は再帰的特徴量削減手法になります。
すべての特徴量から開始してモデルを作成し、そのモデルで最も重要度が低い特徴量を削除します。その後またモデルを作成し、最も重要度が低い特徴量を削除します。この手順を定めた数の特徴量になるまで繰り返す手法です。

pythonのコードは下記の通りです。

```php
# 必要なライブラリーのインポート
mport pandas as pd
import numpy as np
from sklearn.datasets import load_boston
from sklearn.feature_selection import RFE
from sklearn.ensemble import GradientBoostingRegressor

# データセットの読込み
boston = load_boston()

# データフレームの作成
# 説明変数の格納
df = pd.DataFrame(boston.data, columns = boston.feature_names)

# 目的変数の追加
df['MEDV'] = boston.target

# estimatorとしてGBDTを使用。特徴量を5個選択
selector = RFE(GradientBoostingRegressor(n_estimators=100, random_state=10), n_features_to_select=5)
selector.fit(df.iloc[:, 0:13], df.iloc[:, 13])
mask = selector.get_support()
print(boston.feature_names)
print(mask)

# 選択した特徴量の列のみ取得
X_selected = selector.transform(df.iloc[:, 0:13])
print("X.shape={}, X_selected.shape={}".format(df.iloc[:, 0:13].shape, X_selected.shape))
```

実行結果は下記のようになります。

```
['CRIM' 'ZN' 'INDUS' 'CHAS' 'NOX' 'RM' 'AGE' 'DIS' 'RAD' 'TAX' 'PTRATIO'
 'B' 'LSTAT']
[False False False False  True  True False  True False False  True False
  True]
X.shape=(506, 13), X_selected.shape=(506, 5)
```

##SelectFromModelによる特徴量選択
モデルで得られる特徴量の重要性をあらわした feature_importances_を利用して特徴量を選択方法です。

pythonのコードは下記の通りです。

```php
from sklearn.feature_selection import SelectFromModel

# estimatorとしてGBDTを使用。
selector = SelectFromModel(GradientBoostingRegressor(n_estimators=100, random_state=10), threshold="median")    
selector.fit(df.iloc[:, 0:13], df.iloc[:, 13])
mask = selector.get_support()
print(boston.feature_names)
print(mask)

# 選択した特徴量の列のみ取得
X_selected = selector.transform(df.iloc[:, 0:13])
print("X.shape={}, X_selected.shape={}".format(df.iloc[:, 0:13].shape, X_selected.shape))
```

実行結果は下記のようになります。

```
['CRIM' 'ZN' 'INDUS' 'CHAS' 'NOX' 'RM' 'AGE' 'DIS' 'RAD' 'TAX' 'PTRATIO'
 'B' 'LSTAT']
[ True False False False  True  True False  True False False  True  True
  True]
X.shape=(506, 13), X_selected.shape=(506, 7)
```

##SelectKBestによる特徴量選択
説明変数のうち上位k個を選択する手法です。

pythonのコードは下記の通りです。

```php
from sklearn.feature_selection import SelectKBest, f_regression

# 5つの特徴量を選択
selector = SelectKBest(score_func=f_regression, k=5) 
selector.fit(df.iloc[:, 0:13], df.iloc[:, 13])
mask = selector.get_support()    # 各特徴量を選択したか否かのmaskを取得
print(boston.feature_names)
print(mask)

# 選択した特徴量の列のみ取得
X_selected = selector.transform(df.iloc[:, 0:13])
print("X.shape={}, X_selected.shape={}".format(df.iloc[:, 0:13].shape, X_selected.shape))
```

実行結果は下記のようになります。

```
['CRIM' 'ZN' 'INDUS' 'CHAS' 'NOX' 'RM' 'AGE' 'DIS' 'RAD' 'TAX' 'PTRATIO'
 'B' 'LSTAT']
[False False  True False False  True False False False  True  True False
  True]
X.shape=(506, 13), X_selected.shape=(506, 5)
```

##SelectPercentileによる特徴量選択
説明変数のうち上位k%を選択する手法です。

pythonのコードは下記の通りです。

```php
from sklearn.feature_selection import SelectPercentile, f_regression

# 特徴量のうち50%を選択
selector = SelectPercentile(score_func=f_regression, percentile=50) 
selector.fit(df.iloc[:, 0:13], df.iloc[:, 13])
mask = selector.get_support()
print(boston.feature_names)
print(mask)

# 選択した特徴量の列のみ取得
X_selected = selector.transform(df.iloc[:, 0:13])
print("X.shape={}, X_selected.shape={}".format(df.iloc[:, 0:13].shape, X_selected.shape))
```

実行結果は下記のようになります。

```
['CRIM' 'ZN' 'INDUS' 'CHAS' 'NOX' 'RM' 'AGE' 'DIS' 'RAD' 'TAX' 'PTRATIO'
 'B' 'LSTAT']
[False False  True False  True  True False False False  True  True False
  True]
X.shape=(506, 13), X_selected.shape=(506, 6)
```

##さいごに
最後まで読んで頂き、ありがとうございました。
今回はsklearnを使用した特徴量選択方法を整理しました。
実際の業務では、ライブラリーを使いながら、ドメイン知識と合わせて適切な特徴量エンジニアリングを実施することが重要かと思います。

訂正要望がありましたら、ご連絡頂けますと幸いです。