アンサンブル予測
「一つのモデルに頼るのは危険だ。複数のモデルを組み合わせることで、個々のモデルの弱点を補完できる。」
田中VPoEがKaggleのリーダーボードを表示する。
「上位入賞者のほとんどがアンサンブルを使っている。単純平均でもいいが、最適な重みを見つければさらに精度が上がる。」
アンサンブルの基本概念
アンサンブル予測:
個別モデルの予測を組み合わせて、より正確な予測を生成する手法
利点:
- バイアスの低減: 異なるバイアスを持つモデルが互いに打ち消す
- 分散の低減: 複数予測の平均はノイズの影響が減る
- ロバスト性: 1つのモデルが失敗しても全体への影響が限定的
アンサンブル手法の比較
| 手法 | 方法 | 複雑さ | 効果 |
|---|---|---|---|
| 単純平均 | 全モデルの予測を等しく平均 | 低 | 中 |
| 加重平均 | バリデーション性能に基づく重み付き平均 | 中 | 高 |
| メディアン | 予測値の中央値を採用 | 低 | 中(外れ値に強い) |
| スタッキング | メタモデルで予測を統合 | 高 | 高 |
| ブレンディング | ホールドアウトセットで重みを学習 | 中 | 高 |
単純平均アンサンブル
import numpy as np
import pandas as pd
# 各モデルの予測結果を格納
predictions = {
'sarima': sarima_forecast,
'prophet': prophet_forecast,
'lightgbm': lgbm_forecast,
}
# 単純平均
ensemble_simple = np.mean([predictions[m] for m in predictions], axis=0)
# 各モデルとアンサンブルの精度比較
from sklearn.metrics import mean_absolute_error
for name, pred in predictions.items():
mae = mean_absolute_error(y_true, pred)
print(f"{name:12s}: MAE = {mae:.2f}")
mae_ensemble = mean_absolute_error(y_true, ensemble_simple)
print(f"{'ensemble':12s}: MAE = {mae_ensemble:.2f}")
加重平均アンサンブル
バリデーションデータでの性能に基づいて重みを決定する。
from scipy.optimize import minimize
def weighted_ensemble(weights, predictions_list):
"""重み付きアンサンブル予測"""
weighted = np.zeros_like(predictions_list[0])
for w, pred in zip(weights, predictions_list):
weighted += w * pred
return weighted
def objective(weights, predictions_list, y_true):
"""最小化する目的関数(RMSE)"""
pred = weighted_ensemble(weights, predictions_list)
return np.sqrt(np.mean((pred - y_true) ** 2))
# バリデーションデータで最適重みを探索
predictions_list = [predictions['sarima'], predictions['prophet'], predictions['lightgbm']]
n_models = len(predictions_list)
# 初期値: 均等配分
initial_weights = np.ones(n_models) / n_models
# 制約: 重みの合計 = 1, 各重み >= 0
constraints = {'type': 'eq', 'fun': lambda w: np.sum(w) - 1}
bounds = [(0, 1)] * n_models
result = minimize(
objective,
initial_weights,
args=(predictions_list, y_val),
method='SLSQP',
bounds=bounds,
constraints=constraints
)
optimal_weights = result.x
print("最適重み:")
for name, w in zip(predictions.keys(), optimal_weights):
print(f" {name}: {w:.3f}")
# 最適重みでアンサンブル
ensemble_weighted = weighted_ensemble(optimal_weights, predictions_list)
mae_weighted = mean_absolute_error(y_true, ensemble_weighted)
print(f"\n加重平均アンサンブル MAE: {mae_weighted:.2f}")
スタッキング
1段目のモデルの予測を特徴量として、2段目のメタモデルで最終予測を行う。
from sklearn.linear_model import Ridge
from sklearn.model_selection import TimeSeriesSplit
# 1段目: 各モデルのOut-of-Fold予測を作成
tscv = TimeSeriesSplit(n_splits=5)
oof_predictions = np.zeros((len(X_train), n_models))
for fold, (train_idx, val_idx) in enumerate(tscv.split(X_train)):
# 各モデルをfoldごとに学習し、val_idxの予測を格納
for i, model_fn in enumerate(model_functions):
model = model_fn()
model.fit(X_train.iloc[train_idx], y_train.iloc[train_idx])
oof_predictions[val_idx, i] = model.predict(X_train.iloc[val_idx])
# 2段目: メタモデル(Ridge回帰)の学習
meta_model = Ridge(alpha=1.0)
meta_model.fit(oof_predictions, y_train)
# テストデータでの予測
test_predictions = np.column_stack([
predictions['sarima'],
predictions['prophet'],
predictions['lightgbm'],
])
ensemble_stacking = meta_model.predict(test_predictions)
print(f"スタッキング MAE: {mean_absolute_error(y_true, ensemble_stacking):.2f}")
print(f"メタモデルの係数: {meta_model.coef_}")
Store Salesでのアンサンブル戦略
# カテゴリ別にアンサンブル重みを変える戦略
# 理由: カテゴリによって最適なモデルが異なる
category_weights = {}
for family in train['family'].unique():
family_val = y_val_per_family[family]
family_preds = [pred_per_family[m][family] for m in predictions.keys()]
result = minimize(
objective,
initial_weights,
args=(family_preds, family_val),
method='SLSQP',
bounds=bounds,
constraints=constraints
)
category_weights[family] = result.x
# 結果の例:
# GROCERY I: SARIMA=0.1, Prophet=0.2, LightGBM=0.7
# BEVERAGES: SARIMA=0.1, Prophet=0.3, LightGBM=0.6
# AUTOMOTIVE: SARIMA=0.4, Prophet=0.4, LightGBM=0.2
# → 安定カテゴリは統計モデル重視、変動大はLightGBM重視
アンサンブルの注意点
| 注意点 | 説明 |
|---|---|
| 多様性 | 似たモデルを組み合わせても効果が薄い |
| 過学習 | バリデーションデータに重みを最適化しすぎると過学習 |
| 計算コスト | モデル数に比例して推論時間が増加 |
| 保守性 | 本番運用ではシンプルなアンサンブルの方が安定 |
まとめ
| 項目 | ポイント |
|---|---|
| 単純平均 | 最もシンプルで効果的な第一歩 |
| 加重平均 | バリデーション性能で重みを最適化 |
| スタッキング | メタモデルで予測を統合。最も柔軟 |
| 戦略 | カテゴリ別に重みを変えるのが有効 |
チェックリスト
- アンサンブルの3つの利点を説明できる
- 加重平均の重みを最適化で求められる
- スタッキングの2段構造を理解した
- アンサンブルの注意点を把握した
次のステップへ
アンサンブル予測で精度を高めた。次は演習で実際にモデルを構築し、Kaggleスコアの改善に挑戦しよう。
推定読了時間: 30分