📋 このステップで学ぶこと
なぜ特徴量選択が必要か
フィルタ法(相関係数、分散、SelectKBest)
ラッパー法(RFE、RFECV)
埋め込み法(Lasso、Random Forest、SelectFromModel)
特徴量選択手法の比較と使い分け
⏱️ 目安時間: 2時間
📝 演習問題: 6問
🎯 1. なぜ特徴量選択が必要か
特徴量が多ければ多いほど良いわけではありません。不要な特徴量 は様々な問題を引き起こします。
📊 不要な特徴量の問題
過学習: ノイズを学習してしまう
計算コスト: 学習・予測に時間がかかる
次元の呪い: 高次元空間ではデータがスカスカになる
解釈性の低下: どの特徴量が重要か分からなくなる
【特徴量選択の3つのアプローチ】
1. フィルタ法(Filter Methods)
└─ 統計的な指標で特徴量を評価・選択
└─ モデルに依存しない
└─ 高速だが、特徴量間の相互作用を考慮しない
└─ 例: 相関係数、分散、カイ二乗検定、SelectKBest
2. ラッパー法(Wrapper Methods)
└─ モデルの性能を使って特徴量を評価
└─ 特徴量の組み合わせを考慮
└─ 計算コストが高い
└─ 例: RFE(再帰的特徴量削除)、前進選択、後退選択
3. 埋め込み法(Embedded Methods)
└─ モデルの学習過程で特徴量を選択
└─ フィルタ法とラッパー法の中間
└─ 効率的
└─ 例: Lasso(L1正則化)、Random Forestの特徴量重要度
📊 2. フィルタ法
統計的な指標を使って、モデルを使わずに 特徴量を選択します。最も単純で高速な方法です。
相関係数による選択
相関係数で特徴量を選ぶ考え方:
目的変数との相関が高い 特徴量 → 残す(予測に役立つ)
他の特徴量との相関が高すぎる 特徴量 → 1つだけ残す(冗長)
# 相関係数による特徴量選択
import pandas as pd
import numpy as np
from sklearn.datasets import load_breast_cancer
# データを読み込む
cancer = load_breast_cancer()
X = pd.DataFrame(cancer.data, columns=cancer.feature_names)
y = pd.Series(cancer.target, name=’target’)
# 目的変数との相関を計算
# corrwith()はDataFrameの各列とyの相関を計算
correlations = X.corrwith(y)
# 相関の絶対値でソート(強い相関が上に来る)
correlations_abs = correlations.abs().sort_values(ascending=False)
print(“目的変数との相関(上位10個):”)
print(correlations_abs.head(10).round(4))
目的変数との相関(上位10個):
worst concave points 0.7936
worst perimeter 0.7829
mean concave points 0.7766
worst radius 0.7765
mean perimeter 0.7427
worst area 0.7338
mean radius 0.7301
mean area 0.7089
mean concavity 0.6964
worst concavity 0.6593
dtype: float64
SelectKBestのスコア関数を理解しよう
📊 SelectKBestとは
統計的なスコア関数を使って、目的変数との関連が強い上位k個の特徴量 を選択します。
score_funcの選び方:
スコア関数
用途
特徴
使いどころ
f_classif
分類問題
ANOVA F値。線形関係を評価
一般的な分類問題(最も使われる)
f_regression
回帰問題
F値。線形関係を評価
一般的な回帰問題
mutual_info_classif
分類問題
相互情報量。非線形関係も捉える
非線形な関係が強い場合
mutual_info_regression
回帰問題
相互情報量。非線形関係も捉える
非線形な関係が強い場合
chi2
分類問題
カイ二乗検定
カテゴリカル特徴量(非負値のみ)
💡 f_classifとmutual_info_classifの違い
f_classif: 線形関係を仮定。計算が速い。多くの場合で十分な性能
mutual_info_classif: 非線形関係も捉える。計算が遅い。複雑なデータ向け
迷ったらまずf_classifを試し、結果が悪ければmutual_info_classifを検討
ステップ1:データの準備
# SelectKBest: 上位k個の特徴量を選択
from sklearn.feature_selection import SelectKBest, f_classif, mutual_info_classif
from sklearn.datasets import load_breast_cancer
import pandas as pd
# データを読み込む
cancer = load_breast_cancer()
X = pd.DataFrame(cancer.data, columns=cancer.feature_names)
y = pd.Series(cancer.target, name=’target’)
print(f”元の特徴量数: {X.shape[1]}”)
print(f”特徴量名の例: {list(X.columns[:5])}”)
ステップ2:SelectKBestの実行
# ANOVA F値で上位10個を選択
selector = SelectKBest(
score_func=f_classif, # 分類問題用のスコア関数
k=10 # 上位10個を選択
)
# fit_transform(): スコアを計算して特徴量を選択
X_selected = selector.fit_transform(X, y)
print(f”SelectKBest (k=10):”)
print(f”選択後の形状: {X_selected.shape}”)
ステップ3:選択された特徴量の確認
# 選択された特徴量を確認
# get_support(): 選択された特徴量のブール配列を取得
selected_mask = selector.get_support()
selected_features = X.columns[selected_mask]
print(f”\n選択された特徴量:”)
for i, name in enumerate(selected_features, 1):
print(f” {i}. {name}”)
# スコアを確認
# scores_: 各特徴量のスコア
scores = pd.DataFrame({
‘feature’: X.columns,
‘score’: selector.scores_
}).sort_values(‘score’, ascending=False)
print(f”\nスコア(上位10):”)
print(scores.head(10).to_string(index=False))
元の特徴量数: 30
特徴量名の例: [‘mean radius’, ‘mean texture’, ‘mean perimeter’, ‘mean area’, ‘mean smoothness’]
SelectKBest (k=10):
選択後の形状: (569, 10)
選択された特徴量:
1. mean radius
2. mean perimeter
3. mean area
4. mean concavity
5. mean concave points
6. worst radius
7. worst perimeter
8. worst area
9. worst concavity
10. worst concave points
スコア(上位10):
feature score
worst concave points 1043.0286
worst radius 930.2813
worst perimeter 919.6621
worst area 869.3750
mean concave points 747.5298
mean radius 704.0538
mean perimeter 675.0802
mean area 641.2476
mean concavity 512.0165
worst concavity 421.9765
分散による選択(VarianceThreshold)
# VarianceThresholdで低分散の特徴量を除去
from sklearn.feature_selection import VarianceThreshold
# VarianceThresholdを作成
# threshold: 分散がこの値以下の特徴量を除去
var_selector = VarianceThreshold(threshold=0.1)
# 変換を実行
X_var = var_selector.fit_transform(X)
print(f”選択前: {X.shape[1]}特徴量”)
print(f”選択後: {X_var.shape[1]}特徴量”)
print(f”除去された: {X.shape[1] – X_var.shape[1]}特徴量”)
🔄 3. ラッパー法(RFE)
RFEの動作原理を理解しよう
📊 RFE(Recursive Feature Elimination)とは
モデルの特徴量重要度を使って、重要度が低い特徴量を再帰的(繰り返し)に削除 していく方法です。
RFEの手順:
全ての特徴量でモデルを訓練
各特徴量の重要度を計算 (係数の絶対値、特徴量重要度など)
最も重要度が低い特徴量を1つ(またはstep個)削除
目標の特徴量数になるまで2〜3を繰り返し
💡 SelectKBestとRFEの違い
SelectKBest: 各特徴量を独立に 評価(特徴量間の相互作用を考慮しない)
RFE: モデルの性能 を見ながら選択(特徴量間の相互作用も考慮)
RFEの方が精度が高いことが多いですが、計算コストも高くなります。
RFEの主なパラメータ:
パラメータ
説明
デフォルト
estimator
特徴量重要度を出せるモデル(RandomForest、LogisticRegressionなど)
必須
n_features_to_select
最終的に残す特徴量の数
半分
step
各イテレーションで削除する特徴量の数(割合も可)
1
ステップ1:RFEの実行
# RFE: 再帰的特徴量削除
from sklearn.feature_selection import RFE
from sklearn.ensemble import RandomForestClassifier
# 推定器(estimator)を作成
# RFEはこのモデルの特徴量重要度を使って選択する
model = RandomForestClassifier(n_estimators=100, random_state=42)
# RFEオブジェクトを作成
rfe = RFE(
estimator=model, # 特徴量重要度を計算するモデル
n_features_to_select=10, # 最終的に残す特徴量数
step=1 # 各ステップで1つずつ削除
)
# 実行
rfe.fit(X, y)
print(f”RFEで選択された特徴量({rfe.n_features_}個):”)
ステップ2:選択結果の確認
# 選択された特徴量
# support_: 選択された特徴量のブール配列
selected_features = X.columns[rfe.support_]
print(“選択された特徴量:”)
for i, name in enumerate(selected_features, 1):
print(f” {i}. {name}”)
# 特徴量のランキング
# ranking_: 各特徴量のランク(1が最も重要)
ranking = pd.DataFrame({
‘feature’: X.columns,
‘ranking’: rfe.ranking_
}).sort_values(‘ranking’)
print(“\n特徴量のランキング(上位10):”)
print(ranking.head(10).to_string(index=False))
RFEで選択された特徴量(10個):
選択された特徴量:
1. mean texture
2. mean perimeter
3. mean concavity
4. mean concave points
5. worst radius
6. worst texture
7. worst perimeter
8. worst concave points
9. worst symmetry
10. worst fractal dimension
特徴量のランキング(上位10):
feature ranking
mean texture 1
mean perimeter 1
mean concavity 1
mean concave points 1
worst radius 1
worst texture 1
worst perimeter 1
worst concave points 1
worst symmetry 1
worst fractal dimension 1
ステップ3:RFECVで最適な特徴量数を自動決定
何個の特徴量を残すべきかわからない場合は、RFECVを使います。
# RFECV: 交差検証で最適な特徴量数を決定
from sklearn.feature_selection import RFECV
from sklearn.model_selection import StratifiedKFold
model = RandomForestClassifier(n_estimators=100, random_state=42)
# RFECVオブジェクトを作成
rfecv = RFECV(
estimator=model,
step=1, # 1つずつ削除
cv=StratifiedKFold(5), # 5-Fold層化交差検証
scoring=’accuracy’, # 正解率で評価
min_features_to_select=1 # 最小1個まで試す
)
rfecv.fit(X, y)
print(f”最適な特徴量数: {rfecv.n_features_}”)
print(f”選択された特徴量: {list(X.columns[rfecv.support_])}”)
🌲 4. 埋め込み法
モデルの学習過程で特徴量の重要度を計算し、それに基づいて選択します。効率的でよく使われる方法です。
Lasso(L1正則化)による選択
Lassoの特徴量選択の仕組み:
L1正則化は、不要な特徴量の係数を完全に0 にします。
係数が0でない特徴量 = 重要な特徴量
alphaを大きくすると、より多くの係数が0になります。
# Lassoによる特徴量選択
from sklearn.linear_model import Lasso
from sklearn.preprocessing import StandardScaler
# データをスケーリング
scaler = StandardScaler()
X_scaled = scaler.fit_transform(X)
# Lassoモデルを作成
# alpha: 正則化の強さ(大きいほど係数が0になりやすい)
lasso = Lasso(alpha=0.01)
lasso.fit(X_scaled, y)
# 係数が0でない特徴量を確認
coef = pd.Series(lasso.coef_, index=X.columns)
selected_by_lasso = coef[coef != 0]
print(f”選択された特徴量数: {len(selected_by_lasso)}”)
print(f”\n係数が0でない特徴量:”)
print(selected_by_lasso.sort_values(key=abs, ascending=False))
Random Forestの特徴量重要度
Random Forestの特徴量重要度:
各特徴量が予測にどれだけ貢献したかを測定。
feature_importances_属性で取得できます。
解釈しやすく、実務でもよく使われます。
# Random Forestの特徴量重要度
from sklearn.ensemble import RandomForestClassifier
import numpy as np
# Random Forestを訓練
rf = RandomForestClassifier(n_estimators=100, random_state=42)
rf.fit(X, y)
# 特徴量重要度を取得
# feature_importances_: 各特徴量の重要度(合計1)
importances = pd.Series(
rf.feature_importances_,
index=X.columns
).sort_values(ascending=False)
print(“特徴量重要度(上位10):”)
print(importances.head(10).round(4))
# 重要度の累積
print(f”\n上位10特徴量の累積重要度: {importances.head(10).sum():.2%}”)
特徴量重要度(上位10):
worst perimeter 0.1421
worst concave points 0.1398
mean concave points 0.1163
worst radius 0.1068
mean perimeter 0.0548
worst area 0.0542
area error 0.0449
mean radius 0.0427
mean concavity 0.0399
worst concavity 0.0387
dtype: float64
上位10特徴量の累積重要度: 78.02%
SelectFromModelのthresholdパラメータを理解しよう
📊 SelectFromModelとは
モデルの特徴量重要度 や係数 に基づいて、重要度が閾値(threshold)以上の特徴量を選択します。
SelectFromModelの主なパラメータ:
パラメータ
説明
例
estimator
特徴量重要度を持つ訓練済みモデル
RandomForest, Lasso
threshold='mean'
重要度の平均以上を選択(デフォルト)
–
threshold='median'
重要度の中央値以上を選択
特徴量を半分に減らす
threshold=0.01
指定した値以上を選択
具体的な閾値がある場合
threshold='1.5*mean'
平均の1.5倍以上を選択
より厳しく選択
ステップ1:モデルの訓練と特徴量重要度の確認
# ランダムフォレストの特徴量重要度
from sklearn.ensemble import RandomForestClassifier
from sklearn.feature_selection import SelectFromModel
import pandas as pd
# モデルを訓練
model = RandomForestClassifier(n_estimators=100, random_state=42)
model.fit(X, y)
# 特徴量重要度を確認
importances = pd.DataFrame({
‘feature’: X.columns,
‘importance’: model.feature_importances_
}).sort_values(‘importance’, ascending=False)
print(“特徴量重要度(上位10):”)
print(importances.head(10).to_string(index=False))
# 重要度の統計
print(f”\n重要度の統計:”)
print(f” 平均: {model.feature_importances_.mean():.4f}”)
print(f” 中央値: {np.median(model.feature_importances_):.4f}”)
ステップ2:異なるthresholdでの選択
# SelectFromModel: 重要度に基づいて自動選択
import numpy as np
# threshold=’median’: 中央値以上を選択
selector_median = SelectFromModel(model, threshold=’median’, prefit=True)
X_median = selector_median.transform(X)
# threshold=’mean’: 平均以上を選択
selector_mean = SelectFromModel(model, threshold=’mean’, prefit=True)
X_mean = selector_mean.transform(X)
# threshold=0.01: 重要度0.01以上を選択
selector_001 = SelectFromModel(model, threshold=0.01, prefit=True)
X_001 = selector_001.transform(X)
print(“thresholdによる選択結果:”)
print(f” 元の特徴量数: {X.shape[1]}”)
print(f” threshold=’median’: {X_median.shape[1]}個”)
print(f” threshold=’mean’: {X_mean.shape[1]}個”)
print(f” threshold=0.01: {X_001.shape[1]}個”)
thresholdによる選択結果:
元の特徴量数: 30
threshold=’median’: 15個
threshold=’mean’: 8個
threshold=0.01: 17個
ステップ3:選択された特徴量の確認
# 選択された特徴量を確認(中央値以上の場合)
selected = X.columns[selector_median.get_support()]
print(f”\nthreshold=’median’で選択された特徴量:”)
for i, name in enumerate(selected, 1):
print(f” {i}. {name}”)
💡 thresholdの選び方
‘median’: 特徴量を半分に減らしたい場合
‘mean’: 平均より重要な特徴量だけ残したい場合(通常は’median’より少なくなる)
数値指定: 明確な閾値がある場合(ドメイン知識に基づく)
‘1.5*mean’: より厳しく選択したい場合
迷ったらまず'median'を試して、結果を見て調整しましょう。
📊 5. 特徴量選択手法の比較
手法
メリット
デメリット
使いどころ
フィルタ法 (相関、分散、SelectKBest)
高速、シンプル
特徴量間の相互作用を無視
初期スクリーニング
ラッパー法 (RFE)
最適な組み合わせを探索
計算コストが高い
最終調整、特徴量が少ない場合
埋め込み法 (Lasso、RF)
効率的、実用的
モデルに依存
最もよく使われる
完成コード:3つの特徴量選択手法の比較
# 特徴量選択 – 完成コード
import numpy as np
import pandas as pd
from sklearn.datasets import load_breast_cancer
from sklearn.feature_selection import (
SelectKBest, f_classif, # フィルタ法
RFE, # ラッパー法
SelectFromModel # 埋め込み法
)
from sklearn.ensemble import RandomForestClassifier
from sklearn.model_selection import cross_val_score
from sklearn.linear_model import LogisticRegression
from sklearn.preprocessing import StandardScaler
from sklearn.pipeline import Pipeline
# データ
cancer = load_breast_cancer()
X = pd.DataFrame(cancer.data, columns=cancer.feature_names)
y = cancer.target
print(f”元の特徴量数: {X.shape[1]}”)
# ========== 1. フィルタ法(SelectKBest) ==========
selector_kbest = SelectKBest(score_func=f_classif, k=10)
X_kbest = selector_kbest.fit_transform(X, y)
print(f”\nSelectKBest (k=10): {X_kbest.shape[1]}個”)
# ========== 2. ラッパー法(RFE) ==========
model_rf = RandomForestClassifier(n_estimators=100, random_state=42)
rfe = RFE(estimator=model_rf, n_features_to_select=10, step=1)
X_rfe = rfe.fit_transform(X, y)
print(f”RFE (n=10): {X_rfe.shape[1]}個”)
# ========== 3. 埋め込み法(SelectFromModel) ==========
model_rf.fit(X, y)
selector_sfm = SelectFromModel(model_rf, threshold=’median’, prefit=True)
X_sfm = selector_sfm.transform(X)
print(f”SelectFromModel (median): {X_sfm.shape[1]}個”)
# ========== 性能比較 ==========
print(“\n” + “=” * 50)
print(“特徴量選択手法の性能比較(5-Fold CV)”)
print(“=” * 50)
# 全特徴量
pipe_all = Pipeline([
(‘scaler’, StandardScaler()),
(‘model’, LogisticRegression(max_iter=1000))
])
score_all = cross_val_score(pipe_all, X, y, cv=5).mean()
print(f”\n全特徴量 ({X.shape[1]}): {score_all:.4f}”)
# SelectKBest
pipe_kbest = Pipeline([
(‘scaler’, StandardScaler()),
(‘selector’, SelectKBest(f_classif, k=10)),
(‘model’, LogisticRegression(max_iter=1000))
])
score_kbest = cross_val_score(pipe_kbest, X, y, cv=5).mean()
print(f”SelectKBest (10): {score_kbest:.4f}”)
# RFE
pipe_rfe = Pipeline([
(‘scaler’, StandardScaler()),
(‘selector’, RFE(LogisticRegression(max_iter=1000), n_features_to_select=10)),
(‘model’, LogisticRegression(max_iter=1000))
])
score_rfe = cross_val_score(pipe_rfe, X, y, cv=5).mean()
print(f”RFE (10): {score_rfe:.4f}”)
✅ 実践的なアドバイス
まず: フィルタ法で明らかに不要な特徴量を除去
次に: 埋め込み法(Random Forestの重要度)で候補を絞る
最後に: 必要ならRFECVで最終調整
📝 練習問題
問題1
やさしい
特徴量選択の目的
特徴量選択を行う主な目的として適切でないもの はどれですか?
A. 過学習を防ぐ
B. 計算コストを下げる
C. データを増やす
解答を見る
正解:C
特徴量選択はデータを増やすものではなく、不要な特徴量を減らすことで過学習を防ぎ、計算コストを下げるために行います。
問題2
ふつう
3つのアプローチ
RFE(再帰的特徴量削除)はどのアプローチに分類されますか?
A. フィルタ法
B. ラッパー法
C. 埋め込み法
解答を見る
正解:B(ラッパー法)
RFEはモデルの性能を使って特徴量を評価するため、ラッパー法に分類されます。
問題3
ふつう
SelectKBestのスコア関数
分類問題で線形関係を評価する場合、SelectKBestのscore_funcに何を指定しますか?
解答を見る
正解:f_classif
from sklearn.feature_selection import SelectKBest, f_classif
selector = SelectKBest(score_func=f_classif, k=10)
X_selected = selector.fit_transform(X, y)
問題4
むずかしい
SelectKBestの実装
上位5つの特徴量を選択するSelectKBestのコードを書いてください。
解答を見る
from sklearn.feature_selection import SelectKBest, f_classif
# SelectKBestを作成
selector = SelectKBest(
score_func=f_classif, # 分類問題用スコア関数
k=5 # 上位5個を選択
)
# 特徴量を選択
X_selected = selector.fit_transform(X, y)
# 選択された特徴量名を取得
selected_names = X.columns[selector.get_support()]
問題5
むずかしい
Random Forestの特徴量重要度
Random Forestから特徴量重要度を取得するコードを書いてください。
解答を見る
from sklearn.ensemble import RandomForestClassifier
import pandas as pd
# モデルを訓練
rf = RandomForestClassifier(n_estimators=100, random_state=42)
rf.fit(X, y)
# 特徴量重要度を取得
importances = pd.Series(
rf.feature_importances_, # 重要度の配列
index=X.columns # 特徴量名
).sort_values(ascending=False)
print(importances)
問題6
むずかしい
SelectFromModelの実装
Random Forestの重要度が中央値以上の特徴量を選択するコードを書いてください。
解答を見る
from sklearn.feature_selection import SelectFromModel
from sklearn.ensemble import RandomForestClassifier
# モデルを訓練
rf = RandomForestClassifier(n_estimators=100, random_state=42)
rf.fit(X, y)
# SelectFromModelで選択
selector = SelectFromModel(
rf, # 訓練済みモデル
threshold=’median’, # 中央値以上を選択
prefit=True # 既に訓練済み
)
# 変換
X_selected = selector.transform(X)
# 選択された特徴量
selected_features = X.columns[selector.get_support()]
📝 STEP 28 のまとめ
✅ このステップで学んだこと
フィルタ法: 相関係数、分散で統計的に選択(高速)
SelectKBest: 上位k個の特徴量を選択(f_classif, f_regressionなど)
ラッパー法: RFEでモデルを使って最適な組み合わせを探索
RFECV: 交差検証で最適な特徴量数を自動決定
埋め込み法: Lassoやランダムフォレストの重要度で選択
SelectFromModel: 重要度が閾値以上の特徴量を選択
🚀 次のステップへ
次のSTEP 29では、ガイド付きプロジェクト で住宅価格予測に挑戦します。これまで学んだ全てのスキルを統合して実践しましょう!
❓ よくある質問
Q1. 特徴量はいくつ残すべき?
明確なルールはありませんが、RFECVで自動決定 するか、交差検証スコア が最大になる数を選ぶのが一般的です。
Q2. 特徴量選択とモデル選択、どちらが先?
通常は特徴量選択が先 です。ただし、埋め込み法ではモデルに依存するため、最終的に使うモデルで行うのがベストです。
Q3. SelectKBestとRFE、どちらを使うべき?
SelectKBest: 高速で初期スクリーニング向き
RFE: より精度が高いが計算コストが高い
まずSelectKBestで大まかに絞り、必要ならRFEで最終調整するのがおすすめです。
×
artnasekai
#artnasekai #学習メモ