Python基礎

【保存版】モデル評価:指標の選び方・交差検証・閾値最適化・ビジネス接続を“実務の型”で解説

精度が上がらない原因の多くは「評価設計の誤り」にあります。

評価は「何点取れたか」を競うものではなく、意思決定に耐えうるか を検証する営みです。
本記事は、回帰/分類/ランキングの 指標選定 → 交差検証 → 閾値/コスト設計 → キャリブレーション → 統計的安定性 → KPI接続 を、現場でそのまま使えるコードとチェックリストでまとめ直しました。プログラミング初学者にも読みやすいよう、コードの狙いと出力の読み方を丁寧に解説します。

この記事で身に付く力

  • タスクとデータ状況に沿った主要指標の選び方(AUC・PR-AUC・MAE など)

  • 適切なデータ分割/交差検証とリーク対策(StratifiedKFold / TimeSeriesSplit)

  • 閾値最適化コスト最小化(Youden J・Top-k・損失関数)

  • 予測確率のキャリブレーション(Brier・信頼度曲線)

  • ブートストラップで信頼区間(CI)を提示し、差が偶然かを説明できる

  • 予測指標をビジネスKPI(Precision@k / Recall@k / コスト)へ橋渡し

モデル評価でやりがちな落とし穴

まずは“事故”の典型パターンを押さえておきましょう。ここを外すと、どれだけ学習を回しても実務で使えません。

  • 指標ミスマッチ:不均衡データなのに Accuracy、コストが非対称なのに F1 のみを見る。
  • 前処理リーク:標準化やエンコードを全データで fit → CV が過大評価。
  • テスト濫用:ハイパラ探索にテストを使い回し → 選択バイアス。
  • ビジネス非接続:AUC↑ = 利益↑ ではない。意思決定に繋がらない評価。

解決策は「指標の設計 → CV → 閾値/コスト → KPI接続」を型として固定すること。以下で実装と一緒に落とし込みます。

用語メモ(最短で読み解くために)

  • Positive / Negative:関心事象(例:離反 = 1)/ 非該当
  • TP / FP / FN / TN:混同行列の4要素
  • Precision / Recall / F1:適合率 / 再現率 / 調和平均
  • ROC-AUC / PR-AUC:しきい値に依存しないランキング力

指標の選び方:タスク別の“最短表”

指標は ビジネスKPIの代理指標 です。迷ったらまずこれで決め打ちし、あとから補助指標で補強します。

タスク データ状況 推奨主要指標 補助指標/補足
回帰 外れ値あり MAE RMSE(外れ値に敏感)、R²(参考)
二値分類(均衡) バランス良い AUC + F1 Accuracyは補助、閾値最適化で業務接続
二値分類(不均衡) Positive稀少 PR-AUC + Recall@k/Precision@k ROCは楽観的になることあり
多クラス macro-F1 混同行列・class-weight
ランキング/推薦 Top-k重要 MAP@k / nDCG@k HitRate@k、Coverage
時系列 漏洩注意 MAE/RMSE + TimeSeriesCV 期間固定の外挿に注意

判断基準:KPIとの橋渡し(例:Recall@k ≒ 架電件数の上限、MAE ≒ 平均誤差コスト)。

データ分割と交差検証:正しい比較の土台

「良いモデル」かどうかは分割設計で決まります。特に shuffle/層化未来を覗かない時系列CV は鉄則です。

from sklearn.model_selection import train_test_split, KFold, StratifiedKFold, TimeSeriesSplit

# ホールドアウト(最終報告用のテストは最後に1回)

X\_tr, X\_te, y\_tr, y\_te = train\_test\_split(X, y, test\_size=0.2, stratify=y, random\_state=42)

# KFold(回帰)/ StratifiedKFold(分類)

cv\_cls = StratifiedKFold(n\_splits=5, shuffle=True, random\_state=42)
cv\_reg = KFold(n\_splits=5, shuffle=True, random\_state=42)

# 時系列CV

cv\_ts = TimeSeriesSplit(n\_splits=5)

このコードで何をしている?

  • 最終評価用の テスト を先に切り出し固定します(後から一切触らない)。
  • 学習と検証は CV(交差検証) で行い、分類ではクラス比を保つため StratifiedKFold を使います。
  • 時系列では TimeSeriesSplit を使い、未来の情報が訓練に混ざらない ようにします。

判断基準

  • shuffle=True で偶然差を均す

  • 分類は 層化、時系列は 未来を覗かない

基本評価(分類):混同行列・ROC/PR・レポート

固定閾値 0.5 に縛られず、確率出力 を基準に評価します。

import numpy as np, pandas as pd
from sklearn.metrics import (confusion_matrix, classification_report,
                             roc_auc_score, roc_curve, precision_recall_curve,
                             average_precision_score)

proba = model.predict\_proba(X\_te)\[:,1]
pred = (proba >= 0.5).astype(int)

cm = confusion\_matrix(y\_te, pred)
print(pd.DataFrame(cm, index=\["TrueNeg","TruePos"], columns=\["PredNeg","PredPos"]))

print(classification\_report(y\_te, pred, digits=3))
print("ROC-AUC=", roc\_auc\_score(y\_te, proba))

fpr, tpr, thr = roc\_curve(y\_te, proba)
prec, rec, thr2 = precision\_recall\_curve(y\_te, proba)
print("PR-AUC=", average\_precision\_score(y\_te, proba))

このコードで何をしている?

  • まず確率 proba を計算し、AUC(ROC/PR) でモデルの並べ替え能力を評価します。
  • 参考として 0.5 で二値化し、混同行列classification_report で誤りの内訳を確認します。

判断基準

  • 確率出力 を使い、ROC/PR混同行列 を両面チェック。

閾値最適化:Youden J・コスト最小・Top-k

実務では「何件まで架電できるか」「FN は極力避けたい」など、制約と損失が非対称 です。
閾値は業務前提から決める のが正解です。

from sklearn.metrics import roc_curve, confusion_matrix
import numpy as np

proba = model.predict\_proba(X\_te)\[:,1]
fpr, tpr, thr = roc\_curve(y\_te, proba)

# Youden J(tpr - fpr)最大

j = tpr - fpr
thr\_opt = thr\[j.argmax()]
print("Youden best threshold=", float(thr\_opt))

# コスト最適化(例:FPコスト=1, FNコスト=10)

cost\_fp, cost\_fn = 1.0, 10.0
best = (np.inf, 0.5)
for t in np.linspace(0,1,101):
p = (proba >= t).astype(int)
tn, fp, fn, tp = confusion\_matrix(y\_te, p).ravel()
cost = cost\_fp*fp + cost\_fn*fn
best = min(best, (cost, t))
print("Cost-min threshold=", best\[1])

このコードで何をしている?

  • Youden J は感度と偽陽性率のバランスをとる基準です。
  • コスト最適化 は、FP と FN に価格をつけて 総損失が最小 になる閾値を探します。

Top-k の考え方:リソース上限(例:上位 5% の顧客だけ架電)なら、Precision@k / Recall@k で直接評価・選定します。

キャリブレーション:確率の“当たり”を良くする

ツリー系モデルは確率が歪みがちです(在庫/リスクの見積もりで致命的)。
Brier スコア信頼度曲線 を見て、必要なら補正します。

from sklearn.calibration import CalibratedClassifierCV
from sklearn.metrics import brier_score_loss

# 例:確率が偏りがちなツリーモデルをPlattスケーリング

cal\_model = CalibratedClassifierCV(model, method="sigmoid", cv=5).fit(X\_tr, y\_tr)
proba\_cal = cal\_model.predict\_proba(X\_te)\[:,1]
print("Brier(before)", brier\_score\_loss(y\_te, model.predict\_proba(X\_te)\[:,1]))
print("Brier(after) ", brier\_score\_loss(y\_te, proba\_cal))

このコードで何をしている?

  • 学習済みモデルを CalibratedClassifierCV後付け校正 し、確率の当たり(Brier の低下)を確認します。

不均衡データ:PR-AUCとTop-k評価

資源が限られる現場では「上位何%に当てるか」が要諦。PR-AUC と Top-k で評価しましょう。

from sklearn.metrics import average_precision_score
import numpy as np

proba = model.predict\_proba(X\_te)\[:,1]
print("PR-AUC=", average\_precision\_score(y\_te, proba))

# Top-k(例:上位5%を営業対象にする)

k = int(len(proba) \* 0.05)
idx = np.argsort(-proba)\[:k]
recall\_at\_k = y\_te.iloc\[idx].mean()  # Positive率
print("Recall\@5%:", float(recall\_at\_k))

このコードで何をしている?

  • 上位スコア群だけを抽出し、その中にどれだけ Positive を含められたか を確認します(= Recall@k)。

回帰評価:MAE/RMSE/R²とビジネス解釈

回帰では MAE を主役(コスト直結)に据え、RMSE は外れ値感度、 は参考値として扱います。

from sklearn.metrics import mean_absolute_error, mean_squared_error, r2_score

pred = reg\_model.predict(X\_te)
mae = mean\_absolute\_error(y\_te, pred)
rmse = mean\_squared\_error(y\_te, pred, squared=False)
r2 = r2\_score(y\_te, pred)
print({"MAE": mae, "RMSE": rmse, "R2": r2})

このコードで何をしている?

  • MAE は「平均していくら外すか」=金額換算がしやすい。
  • RMSE は外れ値の影響を強く受けるため、品質のばらつき を把握できます。

統計的安定性:ブートストラップで信頼区間

「その差は偶然では?」に備えて、信頼区間(CI) を示します。
最短の実装はブートストラップです。

import numpy as np
from sklearn.utils import resample
from sklearn.metrics import roc_auc_score

proba = model.predict\_proba(X\_te)\[:,1]
auc = roc\_auc\_score(y\_te, proba)
aucs = \[]
for \_ in range(500):
idx = resample(np.arange(len(y\_te)), replace=True, random\_state=\_)
aucs.append(roc\_auc\_score(y\_te.iloc\[idx], proba\[idx]))
lo, hi = np.percentile(aucs, \[2.5, 97.5])
print(f"AUC={auc:.3f} (95% CI: {lo:.3f}-{hi:.3f})")

このコードで何をしている?

  • 検証セットを復元抽出して AUC を 500 回計算し、ばらつきの幅(95% CI)を示しています。会議で突っ込まれがちな「偶然では?」に正面から答えられます。

モデル比較の検定(考え方)

  • McNemar 検定:2 つの分類器で 誤分類の非対称性 を検定(同一サンプルの 0/1 予測を比較)。
  • DeLong 検定:AUC の 差の有意性 を検定。

実装はライブラリ依存のため省略。
重要なのは、差が偶然かどうか を「言葉で」添えることです(例:p 値、CI を本文に明記)。

ビジネス接続:KPI・コスト・意思決定

目的はスコアを上げることではなく、KPI を上げること。評価指標を意思決定に翻訳します。

  • 営業リソース上限があるRecall@k を直接 KPI に。k は架電/配布可能件数。
  • 偽陽性が高コスト:コスト曲線または最適閾値(FP:FN の単価設定)で最小化。
  • 需要予測/在庫:確率の当たり(キャリブレーション)を重視し、Brier や信頼度曲線を運用ダッシュボードに。
  • レポートの型:平均値だけでなく CITop-k の数値(例:上位 5% で Recall=0.43, Precision=0.18)を必ず添える。

評価設計から“面接に耐える”ポートフォリオへ

評価が語れるポートフォリオは説得力が段違い。交差検証→閾値→Top-k→CIまで組み込んだ例を、10分LTテンプレで話せるように仕上げましょう。独学で難しい場合はレビュー/質問対応のあるスクール活用も近道です。

・株式会社キカガク:実務再現型の課題設計と出口支援が強い。転職直結に◎
・Tech Academy:質問の速さ×短時間運用で継続しやすい。副業/在宅に◎

TechAcademy データサイエンスコース(受講料:174,600円~ ※更に割引あり)

TechAcademy 無料相談

株式会社キカガク AI人材長期育成コース(受講料:237,600円~)

キカガク 無料相談

ミニプロジェクト(提出推奨)

課題:「不均衡データの二値分類で、PR-AUCRecall@5%を改善し、最小コスト閾値で運用案を提示する」

  • CVでベースライン(ロジスティック/ツリーモデル)を比較
  • PR-AUC/ROC-AUCTop-k(5%)を計測
  • 閾値最適化(Youden/コスト最小)を実施し、混同行列コストを報告
  • ブートストラップCIで安定性を提示
  • READMEにKPI接続(例:架電当たり成約率/人件費)を3行で記載

レビュー観点チェックリスト(コピペ可)

  • 指標がタスク/データ状況に合っている
  • CVでモデル選択、テスト1回の原則を守っている
  • 閾値/コストの設計が明示されている
  • CIで安定性を示している
  • KPI接続(意思決定への示唆)が書かれている

付録A:ランキング評価(MAP@k / nDCG@k)最短コード

import numpy as np

def apk(actual, pred, k=10):
pred = pred\[:k]
score, hits = 0.0, 0
for i, p in enumerate(pred, start=1):
if p in actual and p not in pred\[:i-1]:
hits += 1
score += hits / i
return score / min(len(actual), k) if actual else 0.0

def mapk(actual\_list, pred\_list, k=10):
return np.mean(\[apk(a, p, k) for a, p in zip(actual\_list, pred\_list)])

付録B:評価レポート1枚の型(テンプレ)

  1. 目的と指標(PR-AUC / Recall@5% / コスト)
  2. CV結果(平均±std)
  3. テスト結果(混同行列/閾値/コスト)
  4. 安定性(CI)
  5. 意思決定案(運用・再学習・監視)

FAQ:よくある質問

Q1. Accuracyはいつ使う?
A. 均衡データかつミスのコストが対称なとき。多くの現場では補助的に扱います。

Q2. どの閾値が正解?
A. ユースケース依存。Youdenはクラス重みが同等の仮定。コスト最小/Top-kが実務向き。

Q3. AUCが上がったのに業務が改善しない
A. Top-k閾値後のPrecision/Recallを確認。営業枠/在庫制約と整合させる。

Q4. テストのCIは必要?
A. 意思決定の確からしさを示すために有用。ブートストラップやDeLongで提示。

この記事から次に読むべきもの(内部リンク)

機械学習
【保存版】scikit-learn基礎:回帰・分類・前処理・パイプライン・交差検証を“実務の型”で習得

機械学習で迷子になる最大の理由は、前処理→学習→評価→改善の順番が曖昧なまま個々のアルゴリズムに飛びつくこと。 本記事は、未経験〜初学者が週10時間×2〜3週で到達できるscikit-learnの最短 ...

ハイパーパラメータ入門
【保存版】ハイパーパラメータ入門:Grid/Random/Optunaの実務チューニング完全ガイド

チューニングのゴールは「スコアの数字遊び」ではありません。意思決定に耐える安定した最適化を短時間で作ること。 本記事は未経験〜初学者が週10時間×2週間で、GridSearchCV / Randomi ...

スキルアップ
【実務で差がつく】pandas実践:欠損処理・結合・ウィンドウ関数・時系列・品質保証まで“読みやすく速い”型を習得

基礎文法の次は、実務で毎回出る処理を“型”として覚える段階です。 本記事は、pandas 2.x を前提に、欠損・外れ値・結合・ウィンドウ関数・時系列・カテゴリ処理・集計の自動化・大規模データの分割処 ...

可視化
【保存版】可視化入門:Matplotlib/Plotlyの使い分けと“伝わるグラフ設計”10ステップ

結論:可視化は「きれいに描く」ことではなく、意思決定を動かすための設計です。 本稿では、未経験〜初学者が 週10時間×1〜2週 で、Matplotlib/Plotlyを軸に “伝わるグラフ”の設計と実 ...

ポートフォリオ
【保存版】データ職のポートフォリオ完全ガイド|再現性・評価・LTまで

ポートフォリオって「作ったものの置き場」でしょ? いいえ。採用側が見たいのは「意思決定に効いた証拠」と「再現性」です。 本ガイドは、未経験〜初学者が週10時間×4〜6週で、テーマ選定→要件定義→データ ...

最近のコメント

    • この記事を書いた人
    • 最新記事

    ふみと

    このブログでは、データサイエンティストとして市場価値を上げる方法を独自にまとめて発信しています。

    【プロフィール】
    ・大手企業データサイエンティスト/マーケティングサイエンティスト(10年、年収900万円台)/案件100件以上
    ・資格:JDLA E資格(日本ディープラーニング協会主催)/JDLA Community(CDLE会員)/Advanced Marketer/ビジネス統計スペシャリスト/統計検定2級/TOEIC 805
    ・スキル:Python/Tableau/SQL/機械学習/Deep Learning/RPA

    -Python基礎