オーバーフィッティング対策
田中VPoE:「モデルの精度を上げようとして複雑にしすぎると、学習データにだけ特化してしまう。これが過学習だ。実運用では新しいデータに対する予測が重要だから、過学習への対策は必須だ。」
あなた:「前に学んだ正則化以外にも対策があるんですか?」
田中VPoE:「たくさんある。Early Stopping、特徴量削減、データ拡張、ドロップアウトなど、状況に応じて使い分ける。今日はこれらを体系的に学ぼう。」
過学習の検出
まず、過学習が起きているかを正しく検出することが重要です。
from sklearn.model_selection import cross_validate
from sklearn.ensemble import RandomForestClassifier
model = RandomForestClassifier(n_estimators=200, max_depth=None, random_state=42)
cv_results = cross_validate(
model, X_train, y_train,
cv=5, scoring='f1',
return_train_score=True,
)
train_mean = cv_results['train_score'].mean()
val_mean = cv_results['test_score'].mean()
gap = train_mean - val_mean
print(f"学習スコア: {train_mean:.3f}")
print(f"検証スコア: {val_mean:.3f}")
print(f"ギャップ: {gap:.3f}")
if gap > 0.1:
print("→ 過学習の兆候あり!対策が必要です。")
elif gap < 0.02:
print("→ 良好。過学習は見られません。")
else:
print("→ 軽度の過学習。改善の余地があります。")
対策1: 正則化
線形モデルの正則化
from sklearn.linear_model import LogisticRegression
# C を小さくすることで強い正則化
for C in [0.001, 0.01, 0.1, 1.0, 10.0]:
model = LogisticRegression(C=C, max_iter=1000, random_state=42)
cv = cross_validate(model, X_train_scaled, y_train, cv=5,
scoring='f1', return_train_score=True)
print(f"C={C:>5}: 学習={cv['train_score'].mean():.3f}, "
f"検証={cv['test_score'].mean():.3f}, "
f"差={cv['train_score'].mean()-cv['test_score'].mean():.3f}")
木モデルの正則化
from sklearn.ensemble import RandomForestClassifier
# max_depth, min_samples_leaf で複雑度を制限
for depth in [3, 5, 10, 15, None]:
model = RandomForestClassifier(max_depth=depth, n_estimators=100, random_state=42)
cv = cross_validate(model, X_train, y_train, cv=5,
scoring='f1', return_train_score=True)
print(f"max_depth={str(depth):>4}: 学習={cv['train_score'].mean():.3f}, "
f"検証={cv['test_score'].mean():.3f}")
対策2: Early Stopping
学習を途中で止めることで、モデルが学習データに過度に適合するのを防ぎます。
import lightgbm as lgb
model = lgb.LGBMClassifier(
n_estimators=1000, # 十分大きく設定
learning_rate=0.05,
random_state=42,
verbose=-1,
)
model.fit(
X_train, y_train,
eval_set=[(X_val, y_val)],
callbacks=[
lgb.early_stopping(stopping_rounds=50), # 50ラウンド改善なしで停止
lgb.log_evaluation(0),
],
)
print(f"最適なイテレーション数: {model.best_iteration_}")
print(f"最適なスコア: {model.best_score_['valid_0']['binary_logloss']:.4f}")
Early Stopping の仕組み
イテレーション 学習Loss 検証Loss 状態
1 0.500 0.520 改善中
50 0.200 0.250 改善中
100 0.100 0.230 ← 検証Lossが最小
150 0.050 0.250 改善なし(50ラウンド)
→ イテレーション100で停止
対策3: 特徴量の削減
不要な特徴量を除外して、モデルの複雑度を下げます。
from sklearn.feature_selection import SelectFromModel
# 重要度が低い特徴量を除外
selector = SelectFromModel(
RandomForestClassifier(n_estimators=100, random_state=42),
threshold='median', # 中央値以上の重要度を持つ特徴量を選択
)
selector.fit(X_train, y_train)
X_train_selected = selector.transform(X_train)
X_val_selected = selector.transform(X_val)
print(f"元の特徴量数: {X_train.shape[1]}")
print(f"選択後の特徴量数: {X_train_selected.shape[1]}")
# 選択された特徴量で再評価
model_selected = RandomForestClassifier(n_estimators=100, random_state=42)
cv_selected = cross_validate(model_selected, X_train_selected, y_train,
cv=5, scoring='f1', return_train_score=True)
print(f"検証F1: {cv_selected['test_score'].mean():.3f}")
対策4: データの増量
データが少ない場合、データの量を増やすことが最も効果的です。
# SMOTE(Synthetic Minority Over-sampling Technique)
# 少数クラスの合成サンプルを生成
from imblearn.over_sampling import SMOTE
smote = SMOTE(random_state=42)
X_train_resampled, y_train_resampled = smote.fit_resample(X_train, y_train)
print(f"リサンプリング前: {pd.Series(y_train).value_counts().to_dict()}")
print(f"リサンプリング後: {pd.Series(y_train_resampled).value_counts().to_dict()}")
対策の選択ガイド
| 過学習の程度 | 推奨対策 |
|---|---|
| 軽度(差 < 0.05) | max_depth 調整、min_samples_leaf 増加 |
| 中度(差 0.05-0.15) | 正則化強化、特徴量削減、Early Stopping |
| 重度(差 > 0.15) | モデル簡素化、データ増量、アンサンブル |
実践的なチェックリスト
# 過学習対策のステップ
steps = [
"1. 学習曲線で過学習を確認",
"2. max_depth / min_samples_leaf を調整",
"3. 正則化パラメータを強化(C↓, alpha↑)",
"4. Early Stopping を適用",
"5. 不要な特徴量を削除",
"6. データが少なければ増量を検討",
"7. よりシンプルなモデルに変更を検討",
]
for step in steps:
print(step)
まとめ
- 過学習は学習/検証スコアのギャップで検出する
- 正則化: モデルの複雑度にペナルティを与える
- Early Stopping: 検証スコアが改善しなくなったら学習を停止
- 特徴量削減: 不要な特徴量を除外して複雑度を下げる
- データ増量: SMOTE 等で少数クラスのサンプルを増やす
- 対策は段階的に適用し、効果を確認しながら進める
チェックリスト
- 過学習の検出方法を実践できる
- 正則化パラメータの調整方法を理解した
- Early Stopping の仕組みと設定方法を把握した
- 状況に応じた対策の選択ができる
次のステップへ
次のレッスンでは、ハイパーパラメータ最適化の手法を学びます。GridSearch からベイジアン最適化まで、効率的にモデルを改善する方法を身につけましょう。
推定読了時間: 30分