sklearn.feature_selection による特徴量選択

## 単変量統計

 各説明変数と目的変数との間の関係を計算し、最も高い確信度で関連している特徴量を選択する。

### [SelectKBest](http://scikit-learn.org/stable/modules/generated/sklearn.feature_selection.SelectKBest.html)

 説明変数のうち上位k個を選択する。通常、引数 `score_func` は分類では `f_classif`(デフォルト値)、回帰では `f_regression` を指定する。引数 `k` に選択する特徴量の数を指定する。

```py
from sklearn.datasets import load_boston
from sklearn.feature_selection import SelectKBest, f_regression

boston = load_boston()
X = boston.data
y = boston.target

# 5つの特徴量を選択
selector = SelectKBest(score_func=f_regression, k=5) 
selector.fit(X, y)
mask = selector.get_support()    # 各特徴量を選択したか否かのmaskを取得
print(boston.feature_names)
print(mask)

# 選択した特徴量の列のみ取得
X_selected = selector.transform(X)
print("X.shape={}, X_selected.shape={}".format(X.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](http://scikit-learn.org/stable/modules/generated/sklearn.feature_selection.SelectPercentile.html)

 説明変数のうち上位k%を選択する。通常、引数 `score_func` は分類では `f_classif`(デフォルト値)、回帰では `f_regression` を指定する。引数 `percentile` に選択する特徴量の割合（0～100）を指定する。

```py
from sklearn.datasets import load_boston
from sklearn.feature_selection import SelectPercentile, f_regression

boston = load_boston()
X = boston.data
y = boston.target

# 特徴量のうち40%を選択
selector = SelectPercentile(score_func=f_regression, percentile=40) 
selector.fit(X, y)
mask = selector.get_support()
print(boston.feature_names)
print(mask)

# 選択した特徴量の列のみ取得
X_selected = selector.transform(X)
print("X.shape={}, X_selected.shape={}".format(X.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)
```

### [GenericUnivariateSelect](http://scikit-learn.org/stable/modules/generated/sklearn.feature_selection.GenericUnivariateSelect.html)

 `mode` でモード(‘percentile’, ‘k_best’, ‘fpr’, ‘fdr’, ‘fwe’) 、`param` で各モードのパラメータを設定する。
例えば、

```py
selector = GenericUnivariateSelect(mode='percentile', score_func=f_regression, param=40)
```

と

```py
selector = SelectPercentile(score_func=f_regression, percentile=40) 
```

は同値である。


## モデルベース特徴量選択

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

### [SelectFromModel](http://scikit-learn.org/stable/modules/generated/sklearn.feature_selection.SelectFromModel.html#sklearn.feature_selection.SelectFromModel)

 引数には estimator、および閾値 `threshold` を指定する。

```py
from sklearn.datasets import load_boston
from sklearn.feature_selection import SelectFromModel
from sklearn.ensemble import RandomForestRegressor

boston = load_boston()
X = boston.data
y = boston.target

# estimator として RandomForestRegressor を使用。重要度が median 以上のものを選択
selector = SelectFromModel(RandomForestRegressor(n_estimators=100, random_state=42), threshold="median")    
selector.fit(X, y)
mask = selector.get_support()
print(boston.feature_names)
print(mask)

# 選択した特徴量の列のみ取得
X_selected = selector.transform(X)
print("X.shape={}, X_selected.shape={}".format(X.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  True  True False
  True]
X.shape=(506, 13), X_selected.shape=(506, 7)
```


## 反復特徴量選択

 まったく特徴量を使わないところから、ある基準が満たされるまで1つずつ重要度が高い特徴量を加えていく、もしくは、すべての特徴量を使う状態から1つずつ特徴量を取り除いていくという操作を繰り返すことで特徴量を選択する。

## [RFE](http://scikit-learn.org/stable/modules/generated/sklearn.feature_selection.RFE.html)

 RFE(Recursive Feature Elimination; 再帰的特徴量削減)は、すべての特徴量から開始してモデルを作り、そのモデルで最も重要度が低い特徴量を削除する。そしてまたモデルを作り、最も重要度が低い特徴量を削除する。この過程を事前に定めた数の特徴量になるまで繰り返す、という手法である。

 引数には estimator、および特徴量の数 `n_features_to_select` を指定する。  
 (特徴量数 - n_features_to_select) 回、モデル作成=>特徴量削除 が行われるので処理時間がかかる。


```py
from sklearn.datasets import load_boston
from sklearn.feature_selection import RFE
from sklearn.ensemble import RandomForestRegressor

boston = load_boston()
X = boston.data
y = boston.target

# estimator として RandomForestRegressor を使用。特徴量を5個選択
selector = RFE(RandomForestRegressor(n_estimators=100, random_state=42), n_features_to_select=5)
selector.fit(X, y)
mask = selector.get_support()
print(boston.feature_names)
print(mask)

# 選択した特徴量の列のみ取得
X_selected = selector.transform(X)
print("X.shape={}, X_selected.shape={}".format(X.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 False False
  True]
X.shape=(506, 13), X_selected.shape=(506, 5)
```

## 参考

- [1.13. Feature selection &#8212; scikit-learn 0.19.0 documentation](http://scikit-learn.org/stable/modules/feature_selection.html)
- [『Pythonではじめる機械学習 ―― scikit-learnで学ぶ特徴量エンジニアリングと機械学習の基礎』](https://www.amazon.co.jp/dp/4873117984)