モデルベース特徴量選択


AIって結局何なのかよく分からないので、とりあえず100日間勉強してみた Day28


経緯についてはこちらをご参照ください。



■本日の進捗

●モデルベース特徴量選択を理解

■はじめに

引き続き「Pythonではじめる機械学習(オライリー・ジャパン)」で学んでいきます。

これまでは特徴量を増やして(ある種学習モデルの複雑度を増して)精度向上を計る手法を経験してきました。しかし高次元データセットであればどの特徴量が重要なものなのかが分かればそれだけを用いてモデルを学習させることができ、汎化性能も向上しそうに思えます。

今回は自動的に重要度の高い特徴量を選択し学習させることのできる自動特徴量選択手法から、モデルベース特徴量選択を学んでいきます。

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

モデルベース特徴量選択(model-based feature selection)とは、任意のアルゴリズムで学習をさせる前に教師あり学習モデルで事前に特徴量を学習させて、与えた特徴量の中から重要なものだけを予め選択して次元削減を行う手法です。

この手法で用いる教師あり学習モデルは最終的に用いるアルゴリズムに関係なく自由に選択できるのですが、特徴量ごとに重要度の情報(重み、係数)を付加できる機械学習モデルでなければいけません。

良く用いられるのはリッジ回帰、Lasso回帰、サポートベクターマシンなどの正規化項を持つモデルや、自動的に重要度の情報(feature_importance_)を持つランダムフォレストや勾配ブースティング回帰木などがあります。

まずは4つの特徴量を持つあやめデータセットに大量のノイズデータを新たな特徴量として追加し、ロジスティック回帰で学習させてみます。

import numpy as np
import pandas as pd
from sklearn.datasets import load_iris
from sklearn.model_selection import train_test_split
from sklearn.linear_model import LogisticRegression

iris = load_iris()
X = pd.DataFrame(iris.data, columns=iris.feature_names)
y = iris.target

np.random.seed(8)
for i in range(88):
    X[f'noise_feature_{i+1}'] = np.random.rand(X.shape[0])

X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.3, random_state=8)

model = LogisticRegression(max_iter=1000, random_state=8)
model.fit(X_train, y_train)

score = model.score(X_test, y_test)
print("score is ", score)

スコアは上記の通りでした。ここからランダムフォレストを用いたモデルベース特徴量選択を行った後に再度ロジスティック回帰で学習させてみます。

import numpy as np
import pandas as pd
from sklearn.datasets import load_iris
from sklearn.model_selection import train_test_split
from sklearn.linear_model import LogisticRegression
from sklearn.ensemble import RandomForestClassifier
from sklearn.feature_selection import SelectFromModel

iris = load_iris()
X = pd.DataFrame(iris.data, columns=iris.feature_names)
y = iris.target

np.random.seed(8)
for i in range(88):
    X[f'noise_feature_{i+1}'] = np.random.rand(X.shape[0])

X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.3, random_state=8)

rf_model = RandomForestClassifier(random_state=8)
rf_model.fit(X_train, y_train)

selector = SelectFromModel(rf_model, threshold="mean")
selector.fit(X_train, y_train)

X_train_selected = selector.transform(X_train)
X_test_selected = selector.transform(X_test)

model = LogisticRegression(max_iter=1000, random_state=8)
model.fit(X_train_selected, y_train)

score = model.score(X_test_selected, y_test)
print("score is", score)

同じロジスティック回帰ですが、モデルの予測精度が大きく向上しています。これは恐らく追加した大量のノイズ特徴量の多くが除外されたのでしょう。

各特徴量の重要度も表示可能なので見てみましょう。

importances = rf_model.feature_importances_

for feature, importance in zip(X_train.columns, importances):
    print(f"{feature}: {importance:.4f}")

ノイズ特徴量はそのほとんどが0.01未満の重要度しかなく、モデルベース特徴量選択によって重要ではない特徴量だと判断されたことになります。それに対して元々存在する特徴量4つはどれも重要度0.05以上です。

■おわりに

構築したいモデルとは全く違うモデル(ランダムフォレスト)でモデルベース特徴量選択を行った結果、多くのノイズ特徴量を重要ではないと判断して取り除いてくれました。これは現実のデータ(作為的に追加したノイズデータではなく)の場合でも、重要ではないと判断された特徴量は落ち、モデルが学習する上で重要だった特徴量を(可能な限り)残した状態で学習を開始できます。

■参考文献

  1. Andreas C. Muller, Sarah Guido. Pythonではじめる機械学習. 中田 秀基 訳. オライリー・ジャパン. 2017. 392p.
  2. ChatGPT. 4o mini. OpenAI. 2024. https://chatgpt.com/
  3. API Reference. scikit-learn.org. https://scikit-learn.org/stable/api/index.html


コメントを残す

メールアドレスが公開されることはありません。 が付いている欄は必須項目です