You are currently viewing 特徴量選択(feature selection)方法3選〜Python

特徴量選択(feature selection)方法3選〜Python

特徴量選択(feature selection)はデータサイエンスにおいて非常に重要なプロセスです。通常アルゴリズムでモデルを構築する前に、どういうデータを使うかを判断する必要があります。ここではドメイン知識が大きな力を発揮しますが、ドメイン知識に加えて客観的に特徴量選択を選択する必要があります。

通常、全てのデータを使うわけには行かない理由は以下のとおり:

  • 説明可能モデルにしたい 特徴量を選択しないと、特徴空間が複雑となり、モデルの解釈が難しくなります。今の時代では、精度もしくは正解率よりも説明可能なモデルが求められています。これはどういうことかというと、データサイエンスに精通しないドメイン知識をもつ専門家と話が通じるために、各データが予測もしくは識別にどういう風に影響を与えているのかをモデルを使って説明する必要があり、これができると、ビジネスに役にたつインサイトが生まれやすくなります。興味がある方はXAI(Explainable AI)で検索してみてください。
  • 次元の呪い(Curse of Dimensionality)を回避したい これも非常に有名な話です。全ての特徴量を使うと過学習になってしまいます。つまり、学習データに対して完璧にフィットするモデルを作ると、そのモデルが新しいデータにフィットできなくなるのです。
  • 計算コストを削減したい これは分かりやすいですね。情報が多くなると、計算量が増えて計算時間が上ります。短時間で良いモデルを構築できるがベストです。

では具体的に何をすれば良いでしょうか。以下3種類の手法から一例ずつ、特徴量選択方法をご紹介します。

  • フィルダーベース手法
  • ラッパーベース手法
  • 組み込み手法

始める前に、まずデータセットをご紹介します。california_housingというデータを使います。scikit-learnにAPIがあり、直接に読み込むことができます。データの情報は以下のとおりです:

件数20640件
特徴量の数(次元)8次元
House Price(目的変数)0.15〜5
from sklearn.datasets import fetch_california_housing
import pandas as pd

cal_housing = fetch_california_housing()
X = cal_housing.data
y = cal_housing.target

cal_housing_df = pd.DataFrame(X, columns=cal_housing.feature_names)
cal_housing_df["House_price"] = cal_housing.target
display(cal_housing_df.head()) 

House_price列が目的変数になります。House_priceの予測モデルを構築するためにHouse_price以外の8列から必要な列を抽出し、予測モデルの説明変数とします。

では、特徴量選択手法の紹介に入ります。

フィルダーベース手法

フィルダーベース手法として、一番広く使われるビアソン相関係数をご紹介します。

From Wikipedia

相関係数は二つの特徴量(確率変数)の間の関係の強さを数値(-1~1)で示す指標です。マイナスは負の相関を示しており、例えば、「バンにいれる砂糖を減らすことにより売り上げが向上しました」から砂糖の削減売り上げの向上は負の相関にあります。逆に「バンにいれる砂糖を増やすことにより売り上げが向上しました」は正の相関を示しています。また0は無関係という意味です。

相関の数値だけではなく、heatmapも作って可視化します。

import seaborn as sns

print(corr["House_price"])

corr = cal_housing_df.corr(method='pearson')
ax = sns.heatmap(
    corr, 
    vmin=-1, vmax=1, center=0,
    cmap=sns.diverging_palette(20, 220, n=200),
    square=True
)
ax.set_xticklabels(
    ax.get_xticklabels(),
    rotation=45,
    horizontalalignment='right'
); 
MedInc         0.688075
HouseAge       0.105623
AveRooms       0.151948
AveBedrms     -0.046701
Population    -0.024650
AveOccup      -0.023737
Latitude      -0.144160
Longitude     -0.045967
House_price    1.000000

今回は特徴量選択ということなので、heatmapの最後の一行のみに注目すればいいのですが、データ分析において、例えば商品間のカニバリゼーションを知りたいなどの場合はheatmapが非常に役に立ちます。

ビアソン相関係数の他にも沢山の相関係数があります。ビアソン相関係数はパラメトリックな手法であり、つまり、データが正規分布に従っているという仮定を前提にしています。それに対して、ノンパラメトリックな手法として、スピアマン順位相関係数などがありますが、正規分布の仮定がありません。従って相関係数を計算する前にデータの分布も確認した方がいいでよう。

また「データを全て同じスケールにした方が相関の計算がしやすいではないか」という疑問をもつ方がいらっしゃるかもしれませんが、結論を言うとスケーリングは相関に影響しません。実際に検証を行った記事をご参照ください。

ラッパーベース手法

ラッパーベース手法として再帰的特徴量削減(Recursive Feature Elimination)を紹介します。scikit-learnの公式ドキュメントに詳細がありますが、簡単に説明すると、指定されたアルゴリズムでまず全特徴量で学習し、アルゴリズムが各特徴量に重みを付けますが、一番軽い重みをもつ特徴量を除外します。特徴量が必要な数に残るまで、残りの特徴量で再学習し、特徴の除外を繰り返します。

from sklearn.feature_selection import RFE
from sklearn import linear_model
from sklearn.preprocessing import normalize

X_norm = normalize(X, norm='l2')
rfe = RFE(estimator=linear_model.LinearRegression(), n_features_to_select=2)
rfe.fit(X_norm, y)
rfe_features = pd.DataFrame(X_norm, columns=cal_housing.feature_names).loc[:, rfe.get_support()].columns.tolist()
print(rfe_features) 
['MedInc', 'AveOccup']

ここは線形回帰を使って再帰的に二つの特徴量(n_features_to_select=2)を選びました。線形回帰の学習精度をあげるために、データを正規化(Normalization)しました。最後にMedIncとAveOccupが重みがある(重要度が高い)特徴量として選ばれました。

組み込み手法

組み込み手法はアルゴリズムでモデルを構築することによって、モデルが各特徴量への重み付きを確認する方法です。

よく使われる方法としてRandomForest、XGBoost等のツリーメソッドがあります。その他にLassoの特徴を利用する方法があります。LassoはL1正則化(Regularization)を使うことにより、特徴量の重みが0になるように制御できます。他の回帰アルゴリズムに比べると、重みが0になる特徴量の数が多いので、特徴量が多い場合は、要らない特徴量の特定に役に立ちます。

ここでは、自分好みのXGBoostを使います。

import xgboost as xgb

xgb_model = xgb.XGBRegressor()
xgb_model.fit(pd.DataFrame(X, columns=cal_housing.feature_names), y)
xgb.plot_importance(xgb_model) 

ご覧のとおり、MedInc、Latitude、Longitude、AveOccupが上位に上りましたが、LatitudeとLongitudeが座標なので、そのままだと目的変数のHouse Priceとあんまり関係がないのが分かります(ドメイン知識)。従ってドメイン知識で先にLatitudeとLongitudeを除外すべきです。残りのMedIncとAveOccupは再帰的特徴量削減(Recursive Feature Elimination)手法の結果と一致しています。

また、既にお気づきかもしれませんが、XGBoostのようなツリーメソッド手法は学習データを事前に正規化(Normalization)する必要がありません。Lassoを使う場合は事前に正規化するように心かけましょう。

まとめ

特徴量選択(feature selection)は機械学習の前処理において非常に重要なプロセスです。

この記事では以下についてお話をしました:

  • 特徴量選択が重要な理由
  • 3種類の特徴量選択手法の紹介

おまけに、特徴量選択のライブラリも存在するので、興味があればぜひチェックしてみてください。