演習:アンサンブルとAutoMLで精度を追求しよう
田中VPoE:「ここまでの知識を総動員して、最高精度のモデルを構築してみよう。アンサンブル手法と AutoML を組み合わせて、離反予測の精度を限界まで引き上げてくれ。」
あなた:「Voting、Stacking、FLAML を試して、最も良い結果を採用します。」
田中VPoE:「精度だけでなく、SHAP で解釈性も確保すること。ビジネスに使えるモデルは精度と説明力の両方が必要だ。」
ミッション概要
アンサンブル手法と AutoML を活用して NetShop の離反予測モデルの精度を最大化し、SHAP による解釈性も確保します。
Mission 1: Voting と Stacking で精度を追求する
異なるモデルを組み合わせたアンサンブルを構築してください。
要件
- Soft Voting を構築する(3つ以上のモデル)
- Stacking を構築する(メタモデルはロジスティック回帰)
- 単体モデルとの精度差を比較する
from sklearn.ensemble import VotingClassifier, StackingClassifier
from sklearn.linear_model import LogisticRegression
from sklearn.ensemble import RandomForestClassifier
import lightgbm as lgb
from xgboost import XGBClassifier
# ここにアンサンブルモデルのコードを書く
解答例
from sklearn.ensemble import VotingClassifier, StackingClassifier
from sklearn.linear_model import LogisticRegression
from sklearn.ensemble import RandomForestClassifier, GradientBoostingClassifier
import lightgbm as lgb
from sklearn.model_selection import cross_val_score
from sklearn.metrics import f1_score
from sklearn.pipeline import Pipeline
from sklearn.preprocessing import StandardScaler
from sklearn.impute import SimpleImputer
# 前処理(Step 4 のデータを使用)
preprocessor = Pipeline([
('imputer', SimpleImputer(strategy='median')),
('scaler', StandardScaler()),
])
X_train_proc = preprocessor.fit_transform(X_train)
X_test_proc = preprocessor.transform(X_test)
# 個別モデル
models = {
'LR': LogisticRegression(max_iter=1000, random_state=42),
'RF': RandomForestClassifier(n_estimators=200, max_depth=10, random_state=42),
'LightGBM': lgb.LGBMClassifier(n_estimators=200, learning_rate=0.1, random_state=42, verbose=-1),
'XGBoost': XGBClassifier(n_estimators=200, learning_rate=0.1, random_state=42, eval_metric='logloss'),
}
# 個別モデルの評価
print("=== 個別モデル ===")
for name, model in models.items():
scores = cross_val_score(model, X_train_proc, y_train, cv=5, scoring='f1')
print(f"{name:10s}: F1 = {scores.mean():.3f} (+/- {scores.std():.3f})")
# Soft Voting
voting = VotingClassifier(
estimators=list(models.items()),
voting='soft',
weights=[1, 2, 3, 3],
)
scores_voting = cross_val_score(voting, X_train_proc, y_train, cv=5, scoring='f1')
print(f"\n{'Voting':10s}: F1 = {scores_voting.mean():.3f} (+/- {scores_voting.std():.3f})")
# Stacking
stacking = StackingClassifier(
estimators=list(models.items()),
final_estimator=LogisticRegression(random_state=42),
cv=5,
stack_method='predict_proba',
)
scores_stacking = cross_val_score(stacking, X_train_proc, y_train, cv=5, scoring='f1')
print(f"{'Stacking':10s}: F1 = {scores_stacking.mean():.3f} (+/- {scores_stacking.std():.3f})")
# テストデータでの最終評価
voting.fit(X_train_proc, y_train)
stacking.fit(X_train_proc, y_train)
print(f"\n=== テストデータ評価 ===")
print(f"Voting F1: {f1_score(y_test, voting.predict(X_test_proc)):.3f}")
print(f"Stacking F1: {f1_score(y_test, stacking.predict(X_test_proc)):.3f}")
Mission 2: FLAML で AutoML ベースラインと比較する
FLAML で自動モデル構築を行い、手動モデルとの精度差を確認してください。
要件
- FLAML を60秒の時間制約で実行する
- 最適モデルの種類とパラメータを確認する
- 手動構築モデルとの精度差を比較する
from flaml import AutoML
# ここに FLAML のコードを書く
解答例
from flaml import AutoML
automl = AutoML()
automl.fit(
X_train_proc, y_train,
task='classification',
metric='f1',
time_budget=60,
eval_method='cv',
n_splits=5,
verbose=0,
)
print(f"=== FLAML 結果 ===")
print(f"最適モデル: {automl.best_estimator}")
print(f"CV F1スコア: {automl.best_loss * -1 if automl.best_loss else 'N/A'}")
y_pred_automl = automl.predict(X_test_proc)
automl_f1 = f1_score(y_test, y_pred_automl)
print(f"テスト F1: {automl_f1:.3f}")
# 全モデルの比較
print(f"\n=== 全モデル比較 ===")
all_results = {
'Voting': f1_score(y_test, voting.predict(X_test_proc)),
'Stacking': f1_score(y_test, stacking.predict(X_test_proc)),
'FLAML': automl_f1,
}
for name, f1_val in sorted(all_results.items(), key=lambda x: x[1], reverse=True):
print(f"{name:12s}: F1 = {f1_val:.3f}")
best_model_name = max(all_results, key=all_results.get)
print(f"\n最良モデル: {best_model_name}")
Mission 3: SHAP でモデルの解釈性を確保する
最良モデルに対して SHAP 分析を行い、ビジネス向けのレポートを作成してください。
要件
- SHAP 値を計算する
- グローバルな特徴量重要度を可視化する
- 離反リスクが高い顧客3人について個別の説明を生成する
- ビジネス向けのサマリーレポートを出力する
import shap
# ここに SHAP 分析のコードを書く
解答例
import shap
import matplotlib.pyplot as plt
# LightGBM 単体モデルで SHAP 分析(アンサンブルは直接 SHAP 適用が難しい)
lgbm_model = lgb.LGBMClassifier(n_estimators=200, learning_rate=0.1, random_state=42, verbose=-1)
lgbm_model.fit(X_train_proc, y_train)
# SHAP値の計算
explainer = shap.TreeExplainer(lgbm_model)
shap_values = explainer.shap_values(X_test_proc)
# グローバルな特徴量重要度
feature_names = [f"feature_{i}" for i in range(X_test_proc.shape[1])]
if hasattr(X_test, 'columns'):
feature_names = list(X_test.columns)
print("=== SHAP ベース特徴量重要度 ===")
import numpy as np
mean_abs_shap = np.abs(shap_values[1]).mean(axis=0)
importance_shap = pd.Series(mean_abs_shap, index=feature_names)
importance_shap = importance_shap.sort_values(ascending=False)
for feat, imp in importance_shap.items():
print(f" {feat}: {imp:.4f}")
# 離反リスクが高い顧客の分析
y_prob_lgbm = lgbm_model.predict_proba(X_test_proc)[:, 1]
high_risk_idx = np.argsort(y_prob_lgbm)[-3:][::-1]
print(f"\n=== 離反リスクが高い顧客 TOP 3 ===")
for rank, idx in enumerate(high_risk_idx, 1):
print(f"\n--- 顧客 #{rank} (離反確率: {y_prob_lgbm[idx]:.1%}) ---")
effects = sorted(
zip(feature_names, shap_values[1][idx]),
key=lambda x: abs(x[1]), reverse=True,
)
for name, effect in effects[:5]:
direction = "リスク上昇" if effect > 0 else "リスク低下"
print(f" {name}: {effect:+.3f} ({direction})")
# ビジネスサマリーレポート
print(f"\n{'='*60}")
print("=== ビジネスサマリーレポート ===")
print(f"{'='*60}")
print(f"モデル: LightGBM(F1スコア: {f1_score(y_test, lgbm_model.predict(X_test_proc)):.3f})")
print(f"テストデータ: {len(y_test)}人")
print(f"離反予測人数: {(y_prob_lgbm >= 0.5).sum()}人")
print(f"\n離反の主要因(SHAP分析より):")
for i, (feat, imp) in enumerate(importance_shap.head(3).items(), 1):
print(f" {i}. {feat}(重要度: {imp:.4f})")
print(f"\n推奨施策:")
print(f" - 離反確率50%以上の顧客{(y_prob_lgbm >= 0.5).sum()}人にクーポン配布")
print(f" - 離反確率30-50%の顧客{((y_prob_lgbm >= 0.3) & (y_prob_lgbm < 0.5)).sum()}人にフォローメール送信")
達成度チェック
- Soft Voting と Stacking を構築し、精度を比較した
- FLAML で AutoML を実行し、手動モデルと比較した
- SHAP でグローバルな特徴量重要度を可視化した
- 離反リスクが高い顧客の個別説明を生成した
- ビジネス向けのサマリーレポートを作成した
推定所要時間: 60分