モデル比較と選定
田中VPoE:「ロジスティック回帰、ランダムフォレスト、勾配ブースティング。いくつかのモデルを構築できるようになったが、どれを最終的に採用するかはどう決める?」
あなた:「一番精度が高いモデルを選べばいいのでは?」
田中VPoE:「精度だけでなく、解釈性、学習速度、推論速度、メンテナンスコストも考慮する必要がある。バイアスとバリアンスのトレードオフも重要な概念だ。」
バイアス-バリアンストレードオフ
バイアス(Bias)
モデルが単純すぎてデータのパターンを捉えきれない誤差です。
- 高バイアス = 未学習(Underfitting)
- 例: 非線形な関係を線形モデルで学習
バリアンス(Variance)
モデルが複雑すぎてデータの些細なノイズまで学習してしまう誤差です。
- 高バリアンス = 過学習(Overfitting)
- 例: 制限なしの決定木
トレードオフ
モデル複雑度↑ → バイアス↓ バリアンス↑
モデル複雑度↓ → バイアス↑ バリアンス↓
全体の誤差 = バイアス² + バリアンス + ノイズ
import matplotlib.pyplot as plt
import numpy as np
complexity = np.linspace(0.1, 10, 100)
bias = 1 / complexity
variance = complexity * 0.1
total_error = bias + variance
plt.figure(figsize=(10, 6))
plt.plot(complexity, bias, label='バイアス²', linestyle='--')
plt.plot(complexity, variance, label='バリアンス', linestyle='--')
plt.plot(complexity, total_error, label='全体の誤差', linewidth=2)
plt.axvline(complexity[np.argmin(total_error)], color='r',
linestyle=':', label='最適な複雑度')
plt.xlabel('モデルの複雑度')
plt.ylabel('誤差')
plt.title('バイアス-バリアンストレードオフ')
plt.legend()
plt.grid(True)
plt.show()
複数モデルの比較
from sklearn.linear_model import LogisticRegression
from sklearn.ensemble import RandomForestClassifier
from sklearn.model_selection import cross_val_score
from xgboost import XGBClassifier
import lightgbm as lgb
import pandas as pd
import time
models = {
'ロジスティック回帰': LogisticRegression(max_iter=1000, random_state=42),
'ランダムフォレスト': RandomForestClassifier(n_estimators=100, random_state=42),
'XGBoost': XGBClassifier(n_estimators=100, random_state=42, eval_metric='logloss'),
'LightGBM': lgb.LGBMClassifier(n_estimators=100, random_state=42, verbose=-1),
}
results = []
for name, model in models.items():
start = time.time()
scores = cross_val_score(model, X_train_scaled, y_train, cv=5, scoring='f1')
elapsed = time.time() - start
results.append({
'モデル': name,
'F1スコア(平均)': f'{scores.mean():.3f}',
'F1スコア(標準偏差)': f'{scores.std():.3f}',
'学習時間(秒)': f'{elapsed:.2f}',
})
comparison = pd.DataFrame(results)
print(comparison.to_string(index=False))
モデル選定の基準
| 基準 | 説明 | 重要度 |
|---|---|---|
| 予測精度 | F1スコア、AUC-ROC | 最重要 |
| 解釈性 | 予測理由を説明できるか | ビジネスによる |
| 学習速度 | モデル構築にかかる時間 | 再学習頻度による |
| 推論速度 | 1件の予測にかかる時間 | リアルタイム要件による |
| メンテナンス性 | 運用・更新のしやすさ | 長期運用では重要 |
NetShop 離反予測での判断
# 判断基準の例
evaluation = {
'ロジスティック回帰': {
'精度': '★★★',
'解釈性': '★★★★★',
'速度': '★★★★★',
'推奨場面': '解釈性重視、ベースライン',
},
'ランダムフォレスト': {
'精度': '★★★★',
'解釈性': '★★★',
'速度': '★★★★',
'推奨場面': 'バランス重視、安定性重視',
},
'LightGBM': {
'精度': '★★★★★',
'解釈性': '★★',
'速度': '★★★★',
'推奨場面': '精度重視、大規模データ',
},
}
モデル複雑度と精度の関係
# 決定木の深さによる精度変化
from sklearn.tree import DecisionTreeClassifier
depths = range(1, 20)
train_scores = []
val_scores = []
for depth in depths:
dt = DecisionTreeClassifier(max_depth=depth, random_state=42)
dt.fit(X_train, y_train)
train_scores.append(f1_score(y_train, dt.predict(X_train)))
val_scores.append(f1_score(y_val, dt.predict(X_val)))
plt.figure(figsize=(10, 6))
plt.plot(depths, train_scores, label='学習データ', marker='o')
plt.plot(depths, val_scores, label='検証データ', marker='s')
plt.xlabel('決定木の深さ(max_depth)')
plt.ylabel('F1スコア')
plt.title('モデル複雑度と精度の関係')
plt.legend()
plt.grid(True)
plt.show()
実務でのモデル選定フロー
1. ベースライン: ロジスティック回帰で基準精度を確認
2. 中間モデル: ランダムフォレストで非線形パターンを検証
3. 高精度モデル: LightGBM/XGBoost で精度を追求
4. 比較・選定: 精度/速度/解釈性を総合的に判断
5. 最終決定: ビジネス要件に最も合うモデルを選択
まとめ
- バイアスとバリアンスのトレードオフを理解して最適な複雑度を選ぶ
- 複数モデルを交差検証で公正に比較する
- 精度だけでなく、解釈性・速度・メンテナンス性も考慮する
- 実務ではベースライン → 複雑なモデルの順で進める
- ビジネス要件に最も合うモデルを最終選定する
チェックリスト
- バイアス-バリアンストレードオフを説明できる
- 複数モデルの公正な比較方法を理解した
- モデル選定で考慮すべき基準を把握した
- 実務でのモデル選定フローを理解した
次のステップへ
次は演習です。実際に複数のモデルを構築し、比較・選定を行います。
推定読了時間: 30分