LESSON

モデル比較と選定

田中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分