!pip install mlxtend
Sequential feature selection algorithms are a family of greedy search algorithms that are used to reduce an initial d-dimensional feature space to a k-dimensional feature subspace where k < d.
In as nutshell, SFAs remove or add one feature at the time based on the classifier performance until a feature subset of the disired size k is reached. There are 4 different flavors SFAs available via the SequentialFeatureSelector:
import numpy as np
import pandas as pd
import seaborn as sns
import matplotlib.pyplot as plt
%matplotlib inline
from sklearn.model_selection import train_test_split
from sklearn.ensemble import RandomForestClassifier, RandomForestRegressor
from sklearn.metrics import roc_auc_score
from mlxtend.feature_selection import SequentialFeatureSelector as SFS
from sklearn.datasets import load_wine
from sklearn.preprocessing import StandardScaler
data = load_wine()
data.keys()
print(data.DESCR)
x = pd.DataFrame(data.data)
y = data.target
x.columns = data.feature_names
x.head()
x.isnull().sum()
x_train, x_test, y_train, y_test = train_test_split(x, y, test_size=0.2, random_state=0)
x_train.shape, x_test.shape
# 特徴量7つ抽出(7つ選んだ結果がプロパティに残るので、7つ選んだプロパティが最大とは限らない)
sfs = SFS(RandomForestClassifier(n_estimators=100, random_state=0, n_jobs=-1),
k_features = 7,
forward = True,
floating = False,
verbose = 2,
scoring = 'accuracy',
cv = 4,
n_jobs = -1
).fit(x_train, y_train)
# 選択された7つの特徴量
sfs.k_feature_names_
# 選択された7つの特徴量のカラム番号
sfs.k_feature_idx_
# スコア
sfs.k_score_
# 特徴量増加毎のスコアの変化確認
pd.DataFrame.from_dict(sfs.get_metric_dict()).T
上記の結果から、最もスコアの高い特徴量の組を選んで予測モデルを作成すれば良い。
(上記では、特徴量数が3-magnesium, flavanoids, color_intensity で、スコア最良)
上記のやり方では、手動で最も高いスコアの組を読み取らなければならないが、以下のやり方だと、k_feature_names_プロパティに最も良い組み合わせが残る。
# 特徴量1つから8つの組み合わせの中でスコアが最大の組み合わせを見つける。
sfs = SFS(RandomForestClassifier(n_estimators=100, random_state=0, n_jobs=-1),
k_features = (1,8),
forward = True,
floating = False,
verbose = 2,
scoring = 'accuracy',
cv = 4,
n_jobs = -1
).fit(x_train, y_train)
sfs.k_score_
sfs.k_feature_names_
上のように、最もスコアの高い組み合わせが抽出された。
# 特徴量8つから1つまでの組み合わせの中でスコアが最大の組み合わせを見つける。
sbs = SFS(RandomForestClassifier(n_estimators=100, random_state=0, n_jobs=-1),
k_features = (1, 8),
forward = False,
floating = False,
verbose = 2,
scoring = 'accuracy',
cv = 4,
n_jobs = -1
).fit(x_train.values, y_train)
# ※:StepBackward(forward = False)に変えてpd.DataFrameを渡すとエラーになるので、x_train.valuesで渡す
# エラー詳細url: https://github.com/rasbt/mlxtend/issues/505
sbs.k_score_
sbs.k_feature_names_
# DataFrameのvaluesを渡しているので、インデックスが出る
from mlxtend.feature_selection import ExhaustiveFeatureSelector as EFS
# 最小特徴量4、最大特徴量5で探す
efs = EFS(RandomForestClassifier(n_estimators=100, random_state=0, n_jobs=-1),
min_features = 4,
max_features = 5,
scoring = 'accuracy',
cv= None,
n_jobs = -1
).fit(x_train, y_train)
上記の場合、13個から4つ選ぶ組み合わせと、13個から5つ選ぶ組み合わせを探すので、全部で2002組の組み合わせから探すことになる。なので、計算コストが膨大で時間がかかる。
# 13個から4個選ぶ組み合わせと13個から5つ選ぶ組み合わせの数
from scipy.special import comb
comb(13, 4, exact=True) + comb(13, 5, exact=True)
efs.best_score_
efs.best_feature_names_
efs.best_idx_
from mlxtend.plotting import plot_sequential_feature_selection as plot_sfs
plot_sfs(efs.get_metric_dict(), kind='std_dev')