ランダムフォレスト|過学習に強いアンサンブルの実務ガイド(特徴量重要度・汎化)
多数の決定木をランダムに学習し、平均/多数決で安定した予測を得る手法です。単一の深い木の過学習を抑え、ノイズに強いのが特長です。
TL;DR
- 目的: 単一木の過学習を“多数決”で抑え、汎化性能を安定化
- 手順: 学習/検証分割 → n_estimators/深さ/特徴数の調整 → OOB/検証で判断
- 注意: 重要度はバイアスあり。Permutation/SHAP で補完、特徴量の解釈は慎重に
まずはここだけ(やさしい導入)
- 何をする?: 決定木をたくさん作って平均/多数決で“ブレ”を小さくする
- いつ使う?: ベースラインの強化、非線形/相互作用が多い課題、特徴量が多い表形式データ
- どう読む?: OOB/検証スコアで汎化、Permutation 重要度で“効いている”特徴を確認
用語ミニ辞典(1 行で)
- OOB(Out-of-Bag): ブートストラップから漏れたデータでの簡易検証
- max_features: 各分割で候補にする特徴数。小さいほど木の多様性が増す
- Permutation 重要度: 特徴をシャッフルして性能低下で寄与を測る、より公平な重要度
身近なたとえ
1 人の意見(単一木)では偏る可能性があるため、複数の専門家(多くの木)で多数決を取るイメージです。
最小コード例(分類)
from sklearn.ensemble import RandomForestClassifier
from sklearn.model_selection import train_test_split
from sklearn.metrics import accuracy_score
import pandas as pd
X = pd.DataFrame({
'age':[22,25,47,52,46,56,55,60],
'spend':[200,220,500,520,480,600,590,610],
'visits':[3,4,8,9,7,10,9,11]
})
y = [0,0,1,1,1,1,1,1] # 0/1 購買
X_tr, X_te, y_tr, y_te = train_test_split(X, y, test_size=0.3, random_state=42)
clf = RandomForestClassifier(n_estimators=200, max_depth=None, random_state=42, oob_score=True)
clf.fit(X_tr, y_tr)
pred = clf.predict(X_te)
print('acc=', accuracy_score(y_te, pred), 'OOB=', clf.oob_score_)
print('feature_importances=', clf.feature_importances_)
読み方の例: OOB は汎化の目安、feature_importances_ は寄与度のヒント(相互作用やスケール依存に注意)。
ハイパラの要点
- 木の数(n_estimators): 多いほど安定(計算コストと相談)
- 特徴数(max_features): ランダム性の源。少なめで多様性 UP
- 深さ/葉の最小サンプル: 過学習抑制に効く
実務上の注意
- カテゴリのエンコード、欠損の扱い、スケーリングの影響は限定的
- 重要度のバイアス(多水準/スケール)に注意。Permutation 重要度推奨
- 説明可能性が重要なら、木の可視化や SHAP を併用
実務ケーススタディ(解約予測の優先アラート)
目的: サブスクの解約(churn)を早期に検知し、優先対応すべき顧客を抽出したい。
- データと前処理
- 利用回数、直近ログイン、サポート履歴、料金プラン、契約月齢 など
- カテゴリはエンコード、欠損は適切に処理(単純補完で十分なことが多い)
- 学習と評価
- train/valid に分割。n_estimators を増やしつつ OOB/valid で頭打ちを確認
- 重要度の確認
- Permutation 重要度で“効いている”特徴を確認し、ビジネス解釈と突合
- 運用
- 重要度上位 × しきい値最適化でアラート。週次で再学習・ドリフト監視
from sklearn.inspection import permutation_importance
import matplotlib.pyplot as plt
import numpy as np
result = permutation_importance(clf, X_te, y_te, n_repeats=10, random_state=42)
imp = result.importances_mean
print('perm_importance=', imp)
# 棒グラフで可視化
order = np.argsort(imp)
plt.barh(np.array(X.columns)[order], imp[order])
plt.xlabel('Permutation Importance (mean decrease)')
plt.tight_layout(); plt.show()
import numpy as np
import matplotlib.pyplot as plt
from sklearn.ensemble import RandomForestClassifier
from sklearn.model_selection import train_test_split
from sklearn.metrics import accuracy_score
X_tr, X_te, y_tr, y_te = train_test_split(X, y, test_size=0.3, random_state=42)
ns = [10, 30, 50, 100, 200, 400]
oobs, accs = [], []
for n in ns:
clf = RandomForestClassifier(n_estimators=n, random_state=42, oob_score=True)
clf.fit(X_tr, y_tr)
pred = clf.predict(X_te)
accs.append(accuracy_score(y_te, pred))
oobs.append(clf.oob_score_)
plt.figure(figsize=(6,3))
plt.plot(ns, accs, marker='o', label='valid acc')
plt.plot(ns, oobs, marker='s', label='OOB')
plt.xlabel('n_estimators'); plt.ylabel('score'); plt.legend(); plt.tight_layout(); plt.show()
練習問題(理解を定着)
- 木の数を増やしても検証スコアが改善しない。何を確認する?
- ヒント: 深さ/葉の最小サンプル、max_features、データの情報量
- 重要度が「カテゴリの多い特徴」に偏る。どう評価し直す?
- ヒント: Permutation 重要度や SHAP を利用
- OOB が上がるのに本番では下がる。何が起きている?
- ヒント: データ分布のズレ(ドリフト)やリーク、前処理差異
- ハイパラのバランスとデータ量。学習が頭打ちなら特徴設計を見直す。
- Permutation や SHAP で相互作用/スケールの影響を補正して判断。
- 本番/学習の分布差を検知(PSI など)し、再学習や特徴の安定化を行う。
関連と次の一歩
よくある質問(FAQ)
- Q: 木の数はどれくらい?
- A: OOB/検証スコアが頭打ちになるまで増やし、計算コストと相談
- Q: 重要度の信頼性は?
- A: Permutation や SHAP で検証、相互作用やスケールの影響に留意
ランダムフォレスト・機械学習についてのご相談はこちら