ベースラインモデル構築
「EDAと前処理が完了した。いよいよモデル構築だ。」
田中VPoEが満足げにうなずく。
「まずはベースラインモデルを立てろ。いきなり複雑なモデルに飛びつくな。シンプルなモデルで基準を作り、そこから改善していく。これが実務のML開発だ。」
ベースラインモデルの重要性
ベースラインモデルの目的:
1. 性能の下限を確立する → これ以上は改善が必要
2. データの予測可能性を確認する → そもそも予測できるか
3. 特徴量の有効性を検証する → どの特徴量が効いているか
4. 比較基準を提供する → 複雑なモデルの改善幅を評価
評価指標の選定
離反予測では、Accuracy(正解率)だけでは不十分。不均衡データに適した指標を選ぶ。
主要指標
| 指標 | 計算方法 | 用途 |
|---|---|---|
| AUC-ROC | ROC曲線下面積 | 閾値非依存の全体的な識別能力 |
| PR-AUC | Precision-Recall曲線下面積 | 少数クラス(離反)の予測精度 |
| F1-Score | 2×Precision×Recall/(P+R) | 精度と再現率のバランス |
| Recall | TP/(TP+FN) | 離反者の見逃し率(重要) |
| Precision | TP/(TP+FP) | 離反予測の的中率 |
離反予測における指標の優先順位
離反予測での優先順位:
1. AUC-ROC → 主指標(全体の識別能力)
2. Recall → 離反者を見逃さないことが重要
3. PR-AUC → 不均衡データでの性能
4. F1 → バランス指標
5. Precision → 介入コストとのトレードオフ
ロジスティック回帰によるベースライン
import pandas as pd
import numpy as np
from sklearn.linear_model import LogisticRegression
from sklearn.metrics import (
roc_auc_score, average_precision_score,
classification_report, confusion_matrix
)
import matplotlib.pyplot as plt
# 前処理済みデータの読み込み(Step 2で構築済み)
# X_train, X_val, X_test, y_train, y_val, y_test
# ベースラインモデル: ロジスティック回帰
baseline_model = LogisticRegression(
max_iter=1000,
random_state=42,
class_weight='balanced' # 不均衡対策
)
baseline_model.fit(X_train, y_train)
# 予測
y_val_pred = baseline_model.predict(X_val)
y_val_proba = baseline_model.predict_proba(X_val)[:, 1]
# 評価
print("=== ベースラインモデル(ロジスティック回帰)===")
print(f"AUC-ROC: {roc_auc_score(y_val, y_val_proba):.4f}")
print(f"PR-AUC: {average_precision_score(y_val, y_val_proba):.4f}")
print(f"\n{classification_report(y_val, y_val_pred)}")
期待される結果
| 指標 | 期待値 | 備考 |
|---|---|---|
| AUC-ROC | 0.82-0.85 | ベースラインとして十分 |
| PR-AUC | 0.60-0.65 | 不均衡を考慮すると妥当 |
| F1-Score | 0.55-0.60 | class_weightで改善 |
| Recall | 0.75-0.80 | 離反者の検出率 |
混同行列の分析
from sklearn.metrics import ConfusionMatrixDisplay
cm = confusion_matrix(y_val, y_val_pred)
print("混同行列:")
print(f" TN={cm[0,0]} FP={cm[0,1]}")
print(f" FN={cm[1,0]} TP={cm[1,1]}")
# ビジネス観点での解釈
print(f"\n離反者の見逃し(FN): {cm[1,0]}人")
print(f"誤検知(FP): {cm[0,1]}人")
print(f"→ FN×離反コスト vs FP×介入コスト のトレードオフ")
disp = ConfusionMatrixDisplay(cm, display_labels=['Non-Churn', 'Churn'])
disp.plot(cmap='Blues')
plt.title('混同行列 - ベースラインモデル')
plt.savefig('baseline_confusion_matrix.png', dpi=150)
特徴量の重要度(係数)
# ロジスティック回帰の係数を確認
feature_importance = pd.DataFrame({
'feature': X_train.columns,
'coefficient': baseline_model.coef_[0]
}).sort_values('coefficient', ascending=False)
print("離反に正の影響(離反しやすい):")
print(feature_importance.head(10).to_string(index=False))
print("\n離反に負の影響(離反しにくい):")
print(feature_importance.tail(10).to_string(index=False))
class_weightの効果
# class_weightなし
model_no_weight = LogisticRegression(max_iter=1000, random_state=42)
model_no_weight.fit(X_train, y_train)
y_pred_no_weight = model_no_weight.predict(X_val)
y_proba_no_weight = model_no_weight.predict_proba(X_val)[:, 1]
print("class_weightなし:")
print(f" AUC-ROC: {roc_auc_score(y_val, y_proba_no_weight):.4f}")
print(f" Recall: {(confusion_matrix(y_val, y_pred_no_weight)[1,1] / y_val.sum()):.4f}")
print("\nclass_weight='balanced':")
print(f" AUC-ROC: {roc_auc_score(y_val, y_val_proba):.4f}")
print(f" Recall: {(cm[1,1] / y_val.sum()):.4f}")
# → class_weightでRecallが大幅に改善
まとめ
| 項目 | ポイント |
|---|---|
| ベースラインモデル | ロジスティック回帰 + class_weight=‘balanced’ |
| 主指標 | AUC-ROC(全体の識別能力) |
| 補助指標 | Recall(離反者の見逃し防止) |
| ベースライン性能 | AUC-ROC: 0.82-0.85 |
| 特徴量分析 | 係数の大きさで重要度を確認 |
チェックリスト
- ベースラインモデルの目的を説明できる
- 離反予測に適した評価指標を選定できる
- ロジスティック回帰でベースラインを構築できる
- 混同行列をビジネス観点で解釈できる
- class_weightの効果を理解した
次のステップへ
ベースラインが確立できた。次は決定木やアンサンブルモデルを使って、さらなる性能向上を目指そう。
推定読了時間: 30分