機械学習初心者が『Pythonではじめる機械学習』についてまとめてみた。 【4章 データの表現と特徴量エンジニアリング】

#特徴量エンジニアリングって？
　特徴量には、**連続値特徴量**と**離散値特徴量（カテゴリ特徴量）**が存在する。特徴量の表現は機械学習モデルの性能に大きな影響を及ぼす。そこで、最良のデータ表現を模索することを、**特徴量エンジニアリング**と呼ぶ。

#離散値特徴量
　例えば、ロジスティック回帰を適用する際に、入力特徴量が文字列であったり、カテゴリ特徴量であった場合は、その値には数値としての意味はない。このため、ロジスティック回帰を適用するには、他の表現方法が必要となる。

##ワンホットエンコーディング（ダミー変数）
　ダミー変数とは、カテゴリ変数を1つ以上の0と1の値を持つ新しい特徴量で置き換えるものである。カテゴリ特徴量に対して、とる値の分だけ新たに特徴量を作り、該当する特徴量のうち1つだけを1に、それ以外を0とする。

```python
import pandas as pd
pd.get_dummies(data)
```

　pandasでは、`get_dummies`関数を用いることでワンホットエンコーディングすることができる。すべての数値を連続値として扱い、ダミー変数を作らない。そのため、カテゴリ特徴量が整数値としてエンコーディングされていた場合は、ワンホットエンコーディングを行うことができない。これを回避するには、scikit-learnの`OneHotEncoder`を用いるか、DataFrameの列を数値から文字列に変換すれば良い。

```python
df['カテゴリ名'] = df['カテゴリ名'].astype(str)
pd.getdummies(df, columns=['カテゴリ名'])
```
　変換した整数特徴量の列に対してもダミー変数を作りたければ、文字列に変換したあとに、`get_dummies`関数を用いる際に`columns`パラメータで陽に指定すれば良い。

#連続値特徴量
　線形モデルを連続データに対してより強力にする方法として、**ビニング（離散化）**と**多項式特徴量**の利用、特定の条件下の連続データに対しては**単変量非線形変換**がある。

##ビニング（離散化）
　最良のデータ表現方法は、データの意味だけでなく、機械学習のモデルにも依存する。例えば、非常に広く利用されている、線形モデルと決定木ベースのモデルでは、特徴量の表現の違いについて大きく異なる性質がある。

```python
from sklearn.preprocessing import OneHotEncoder
bins = np.linspace('左端の値', '右端の値', 'エントリの数')
which_bin = np.digitize(X, bins=bins)
encoder = OneHotEncoder(sparse=False)
encoder.fit(which_bin)
```

　まず、特徴量の入力範囲を固定個数のビンに分割する。次に、個々のデータポイントがどのビンに入るかを記録する。
　ここまでで、どのビンにデータポイントが入っているかを表現したカテゴリ特徴量への置き換えが完了した。このデータにscikit-learnモデルを適用するために、ワンホットエンコーディングに変換し、`fit`メソッドを呼び出したあとに、`transform`メソッドを呼び出すことで、ビニングが完了する。

###交互作用特徴量
```python
X_product = np.hstack([X_binned, X*X_binned])
```

　ビニングによる特徴量表現をより豊かにする方法として、交互作用特徴量を加える方法がある。例えば、ビニングされたデータに対する線形モデルはビン内で定数を取っているが、傾きも学習できるはずである。そこで、ビンごとに傾きを学習するために、データポイントがどのビンに入っているかを示す特徴量とx軸のどこにあるかを示す特徴量の交互作用もしくは積を特徴量として加える。これを適用することによって、個々のビンがそれぞれオフセットと傾きを持つようになる。

##多項式特徴量
```python
from sklearn.preprocessing import PolynomialFeatures
```

　ある特徴量xに対して、2乗、3乗...を考える。これらの多項式を線形回帰モデルと組み合わせると、**多項式回帰**モデルになる。高次の多項式は、境界近辺やデータが少ない領域で極端な振る舞いを示す傾向にある。

##単変量非線形変換
　log、exp、sinなどの数学関数の特徴量を用いた変換が有用であることもある。logやexpはデータの相対的なスケールを修正してくれるため、線形モデルやニューラルネットワークで有用であり、sinやcosは周期的なパターンを持つ関数を扱う（要はフーリエ級数展開？）際に有用である。殆どのモデルは、個々の特徴量がおよそガウス分布に従っているときに最もうまく機能する。

#自動特徴量選択
　新しい特徴量を作る方法は多くあるが、追加しすぎれば、モデルは複雑になり、過剰適合の可能性が高くなる。そのため、最も有用な特徴量だけを残して残りを捨てることで特徴量を減らし、汎化性能を向上させることができる。そのための基本的な戦略には、**単変量統計**、**モデルベース選択**、**反復選択**の3つがある。

##単変量統計
```python
from sklearn.feature_selection import SelectKBest
from sklearn.feature_selection import SelectPercentile
```
　個々の特徴量とターゲットの間に統計的に顕著な関係が存在するかを計算し、高い確信度で関連している特徴量を選ぶ手法である。クラス分類では**分散分析**として知られる。この方法は単変量であるために、他の特徴量と組み合わせで意味を持つ特徴量は捨てられてしまう。
　特徴量を捨てる際の閾値の計算方法は手法によって異なり、`SelectKBest`では選択する特徴量の数を指定し、`SelectPercentile`では残す特徴量の割合を指定する。

##モデルベース選択
```python
from sklearn.feature_selection import SelectFromModel
from sklearn.ensemble import RandomForestClassifier
select = SelectFromModel( RandomForestClassifier(
    n_estimators=100, random_state=42), threshold="median")
```

　教師あり学習モデルを用いて個々の特徴量の重要性を判断し、重要なものだけを残す手法である。すべての特徴量を同時に考慮するので、変数間の交互作用を捉えることができる。
　`SelectFromModel`クラスは教師あり学習モデルで得られた特徴量の重要性が、指定した閾値よりも大きいものだけを選択する。

##反復選択
　異なる特徴量を用いた一連のモデルを作る。2つの基本的な方法があり、まったく特徴量を使わないところから、ある基準が満たされるまで特徴量を加えていく方法と、すべての特徴量を使う状態から特徴量を除いていく方法である。このうちの1つが**再帰的特徴量削減**である。

###再帰的特徴量削減
```python
from sklearn.feature_selection import RFE
select = RFE(RandomForestClassifier(n_estimators=100, random_state=42),
    n_features_to_select=40)
```

　すべての特徴量から開始してモデルを作り、そのモデルで最も重要度が低い特徴量を削除する。そして再びモデルを作り、最も重要度が低い特徴量を削除する。これを事前に定めた数の特徴量になるまで繰り返す。

#参考文献
Pythonではじめる機械学習
――scikit-learnで学ぶ特徴量エンジニアリングと機械学習の基礎
Andreas C. Muller、Sarah Guido　著、中田 秀基　訳