モデル解釈性
田中VPoE:「精度の高いモデルができても、『なぜこの顧客が離反すると予測されたのか?』を説明できなければ、ビジネス側は納得しない。マーケティングチームに施策を提案するには、予測の根拠が必要だ。」
あなた:「ブラックボックスのままでは使えないということですね。」
田中VPoE:「そうだ。SHAP を使えば、各特徴量がどの程度予測に寄与しているかを可視化できる。」
SHAP(SHapley Additive exPlanations)
ゲーム理論に基づく特徴量の寄与度を算出する手法です。
import shap
# LightGBM モデルの場合
model = lgbm_pipeline.named_steps['model']
X_test_processed = lgbm_pipeline.named_steps['preprocessor'].transform(X_test)
# SHAP値の計算
explainer = shap.TreeExplainer(model)
shap_values = explainer.shap_values(X_test_processed)
# 全体の特徴量重要度(SHAP ベース)
shap.summary_plot(shap_values[1], X_test_processed,
feature_names=feature_names, plot_type='bar')
個別の予測の説明
# 特定の顧客の予測理由を説明
customer_idx = 0
shap.force_plot(
explainer.expected_value[1],
shap_values[1][customer_idx],
X_test_processed[customer_idx],
feature_names=feature_names,
)
# テキストでの説明
print(f"顧客 {customer_idx} の離反確率: {y_prob[customer_idx]:.3f}")
print("\n予測に影響した要因:")
feature_effects = list(zip(feature_names, shap_values[1][customer_idx]))
feature_effects.sort(key=lambda x: abs(x[1]), reverse=True)
for name, effect in feature_effects[:5]:
direction = "離反方向" if effect > 0 else "継続方向"
print(f" {name}: {effect:+.3f} ({direction})")
SHAP Summary Plot
# 各特徴量がどのように予測に影響するかの全体像
shap.summary_plot(shap_values[1], X_test_processed,
feature_names=feature_names)
LIME(Local Interpretable Model-agnostic Explanations)
個別予測の局所的な説明を生成する手法です。
import lime
import lime.lime_tabular
explainer_lime = lime.lime_tabular.LimeTabularExplainer(
X_train_processed,
feature_names=feature_names,
class_names=['継続', '離反'],
mode='classification',
)
# 特定の顧客の説明
exp = explainer_lime.explain_instance(
X_test_processed[0],
model.predict_proba,
num_features=10,
)
exp.show_in_notebook()
print(exp.as_list())
Partial Dependence Plot(PDP)
特定の特徴量がモデルの予測にどう影響するかを可視化します。
from sklearn.inspection import PartialDependenceDisplay
fig, axes = plt.subplots(1, 3, figsize=(18, 5))
features_to_plot = ['days_inactive', 'purchase_count', 'support_tickets']
for ax, feature in zip(axes, features_to_plot):
PartialDependenceDisplay.from_estimator(
model, X_test_processed,
features=[feature_names.index(feature)],
feature_names=feature_names,
ax=ax,
)
ax.set_title(f'{feature} の影響')
plt.tight_layout()
plt.show()
ビジネスへの説明テンプレート
def generate_churn_report(customer_data, shap_values, feature_names, threshold=0.5):
"""離反リスクレポートの生成"""
prob = model.predict_proba(customer_data.reshape(1, -1))[0][1]
report = f"""
=== 離反リスクレポート ===
離反確率: {prob:.1%}
リスクレベル: {'高' if prob > 0.7 else '中' if prob > threshold else '低'}
主な要因:
"""
effects = sorted(zip(feature_names, shap_values),
key=lambda x: abs(x[1]), reverse=True)
for name, effect in effects[:3]:
direction = "リスク上昇" if effect > 0 else "リスク低下"
report += f" - {name}: {direction}(寄与度: {abs(effect):.3f})\n"
return report
print(generate_churn_report(X_test_processed[0], shap_values[1][0], feature_names))
まとめ
- SHAP: 理論的に正しい特徴量寄与度を算出(最も推奨)
- LIME: 個別予測の局所的な説明を生成
- PDP: 特徴量と予測の関係を可視化
- モデルの解釈性はビジネスへの説明と信頼獲得に不可欠
チェックリスト
- SHAP の基本的な使い方を理解した
- 個別予測の説明方法を把握した
- ビジネス向けのレポート生成を理解した
次のステップへ
次は演習です。アンサンブルと AutoML を使って精度を追求してみましょう。
推定読了時間: 15分