確率校正入門:分類器の「0.9」は本当に90%か(Platt・Isotonic・Temperature)
はじめに
モデルが「確信度90%」と出します。この0.9を、閾値判定や期待コストの計算にそのまま使ってよいのでしょうか。今回の実験に使った分類器は、当たり外れを見分ける力(AUCで0.85)はそれなりなのに、出してくる確率はかなり歪んでいました。予測が0.9の集団を集めても、実際に陽性なのは9割には届きません。予測確率と実測の頻度がどれだけずれているか(期待校正誤差、ECE)を測ると0.112ありました。
識別性能(当たり・外れを分ける力)と校正(確率の正しさ)は別物です。AUCが高くても確率がずれることは珍しくありません。この記事では、独立性の仮定が崩れて系統的に自信過剰になるナイーブベイズを題材に、その自信過剰を信頼性図とECEで診断し、Platt scaling・Isotonic回帰・Temperature scalingの3手法で後処理校正します。結論を先に言うと、AUCをまったく落とさずにECEを0.112から0.026まで下げられました。
対象読者:
- 分類確率を閾値判定・リスク評価・意思決定に使う実務者
- accuracyやAUCは見ているが、確率の校正までは見ていない方
- 信頼度スコアの品質を測り、後付けで直したい方
記事のポイント:
- 校正(予測確率=実際の頻度)と識別性能(AUC等)が別物であることを数値で確認します
- 信頼性図とECEで校正のずれを可視化します
- Platt / Isotonic / Temperature で後処理校正し、ECEとAUCへの影響を比較します
精度が高くても確率がずれる理由
決定境界の正しさ(識別)と、出力確率の正しさ(校正)は独立に動きます。閾値0.5でクラスを分けるだけなら、確率が0.6でも0.99でも判定は変わりません。AUCは順位だけを見る指標なので、確率を単調変換しても値は不変です。だから「AUCが高い=確率が信用できる」とは限りません。
自信過剰は特定のモデルで起きやすいです。深層モデルや勾配ブースティングは予測を0や1へ押し込みがちで、ナイーブベイズは特徴間の独立性を仮定するため、相関した特徴があると同じ証拠を何度も数えてしまい、極端な確率を出します。今回はこの性質を逆手に取り、相関・冗長特徴を含むデータでガウシアンナイーブベイズを学習させ、確実に自信過剰なモデルを作りました。
校正の測り方
信頼性図は、予測確率をビンに区切り、ビンごとに「予測確率の平均」と「実測の陽性率」を並べてプロットします。完全に校正されていれば点は対角線に乗ります。対角線から下に外れていれば、予測が実測より高い、つまり自信過剰です。
ECE(期待校正誤差)は、このずれをビンのサンプル数で重み付けして平均した1つの数値です。
はビン のサンプル数、 は実測陽性率、 は予測確率の平均です。0に近いほど校正がよいです。あわせてlog lossも見ておくと、校正と識別を合わせた確率予測全体の質が測れます。
後処理による校正手法
学習済みモデルはそのままに、出力確率だけを校正用のホールドアウトで補正します。
Temperature scalingは、log-odds(対数オッズ)を温度 で割ってから確率に戻します。 なら確率が中央に寄って自信過剰が和らぎ、 なら逆に鋭くなります。パラメータは ひとつだけで、順位を変えないので識別性能は完全に保たれます。
Platt scalingは、モデルの出力にロジスティック回帰を1本当てます。パラメータは2つで、少データでも安定しますが、シグモイド型のずれしか直せません。Isotonic回帰は、単調非減少という制約だけを課したノンパラメトリックな写像で、複雑なずれにも対応できるぶんデータを要求し、少ないと過学習します。
Temperatureの実装は短いです。校正用集合でlog lossを最小化する を1次元探索するだけです。
def fit_temperature(p_cal, y_cal):
z = logit(p_cal)
def nll(T):
pt = 1 / (1 + np.exp(-z / T))
return log_loss(y_cal, pt, labels=[0, 1])
return minimize_scalar(nll, bounds=(0.05, 10.0), method="bounded").x
PlattとIsotonicは、学習済みモデルを凍結してCalibratedClassifierCVに渡します。scikit-learn 1.6以降はFrozenEstimatorでラップする点に注意してください。
frozen = FrozenEstimator(base)
platt = CalibratedClassifierCV(frozen, method="sigmoid").fit(Xcal, ycal)
iso = CalibratedClassifierCV(frozen, method="isotonic").fit(Xcal, ycal)
過学習させたモデルで試す
相関・冗長特徴を持つ2クラスデータを生成し、学習用・校正用・テスト用に分けます。校正はテストとは別のホールドアウトで行います。ここを学習データで済ませると、モデルが見た答えに合わせて校正してしまい、リークになります。乱数シードは42に固定しました。
校正前と校正後(Isotonic)の信頼性図を重ねると、自信過剰だった赤い曲線が、緑ではほぼ対角線に乗ります。

4手法を並べると、それぞれの癖が見えます。

得られた温度は でした。1より大きいので、モデルが自信過剰だったことがそのまま数字に出ています。テスト集合での指標は次のとおりです。
| 手法 | ECE | AUC | log loss |
|---|---|---|---|
| 校正なし | 0.112 | 0.850 | 0.599 |
| Temperature (T=2.30) | 0.042 | 0.850 | 0.487 |
| Platt | 0.050 | 0.850 | 0.495 |
| Isotonic | 0.026 | 0.849 | 0.494 |

どの校正手法を選ぶか
AUCがどの手法でも0.850のまま動かなかった点が重要です。校正は確率の目盛りを付け替えるだけで、順位、つまり識別性能には触れていません。校正されていないからといってモデルが「悪い」わけではなく、確率の解釈を直せば済みます。
手法ごとに得意は分かれました。校正用に3000件使えた今回はIsotonicが最良(ECE0.026)で、複雑なずれに追随できる強みが出ました。信頼性図をよく見ると、Plattは予測が0.13から0.82の範囲に圧縮され、両端に届きません。シグモイドで押し込む性質の裏返しです。Temperatureは1パラメータでここまで下げており、校正データが少ない場面での安定性を考えると、少ない手間でよく効きます。校正用データが数百件しか取れないなら、Isotonicの過学習を避けてTemperatureやPlattを選ぶ、という判断になります。
log lossも0.599から0.49前後へ改善しました。確率を意思決定に使う場面、たとえば期待損失の最小化や、確率に応じてコストの違う対応を振り分ける運用では、この改善がそのまま効いてきます。信用スコアリングの実務でも、スコアの順位だけでなく「このスコア帯の実際のデフォルト率」が効くため、校正は順位性能と同じくらい問われます。
使ううえでの注意点はいくつかあります。校正は必ずテストとは別のホールドアウトで行います。ECEはビン分割の仕方に依存するので、適応ビンやクラスワイズECEも併用すると安定します。そして校正は学習時の分布に対して成立するもので、分布シフトが起きれば崩れます。運用中はECEを監視項目に入れておくのが安全です。確率そのものではなく予測区間に被覆率保証を付けたい場合は、Conformal Predictionが分布フリーの選択肢になります。
まとめ
識別できることと、確率が正しいことは別問題です。今回はAUC0.85を保ったまま、ECEを0.112から0.026へ下げられました。確率を閾値設計や期待コスト計算、与信や医療のようなリスク領域の意思決定に使うなら、校正は省けない工程になります。まず手元のモデルで信頼性図とECEを描き、校正用ホールドアウトを1つ確保します。校正データが潤沢ならIsotonic、少なければTemperatureかPlattから始めるとよいでしょう。