識別とは違って確率を正確に予測したい場合
Calibration¶
Probabilistic calibration あるいは単に calibration (較正)は、
確率分類モデルの予測確率の『正しさ』を評価すること
または
その評価に基づいて予測モデルを改善するための手法
の意味で使われる。後者は recalibration(再較正) とも呼ばれる。
評価手法の分類¶
calibration hierarchy などの分類
mean calibrationほど弱い基準
Mean calibration:データ全体での平均の予測確率と実際の比率が一致しているかどうか
Weak calibration:予測確率が全体として極端すぎたり控えめすぎたりしないか → 予測確率値の分布がロジスティック分布に合致しているか。
Moderate calibration:同じ予測確率を出した集団は、観測値の比率もその確率に一致するか
Strong calibration:任意の特徴量で条件つけた分布が予測と一致するか
1. Mean calibration¶
例えば二値分類において、モデルが全データに対して平均 0.20 のpositiveの確率を出していて、実際のpositiveの割合も 20% なら mean calibration は満たす、という考え方
しかし全体平均しか見ていないので正確性は欠ける
2. Weak calibration¶
Mean Calibrationより少し強い基準だが、ロジスティック回帰に依存した考え方。医療分野では使うらしい。
予測確率値の分布がロジスティック分布に合致しているかを確認するというもの。
具体的には、推定したロジスティック回帰モデルの線形予測子に対して線形回帰した際に、定数項がゼロで、傾きが1であるかどうかで評価する
3. Moderate calibration¶
予測確率でビニングし、それぞれを期待値で見て一致しているかどうか
Calibration Plot / reliability diagram¶
予測確率の正しさを評価するためのplot。
横軸に予測確率をとり、縦軸に経験確率(サンプル上の比率)をとるplot。
予測確率をいくつかのbinに区切り、bin内のサンプルでの比率から経験確率を計算する。
scikit-learnのcalibration_curve() で簡単に計算できる
Source
import numpy as np
import matplotlib.pyplot as plt
from sklearn.datasets import make_classification
from sklearn.ensemble import RandomForestClassifier
from sklearn.calibration import calibration_curve
from sklearn.model_selection import train_test_split
# データ生成・分割
X, y = make_classification(n_samples=2000, n_features=10, random_state=42)
X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.4, random_state=42)
# 学習・予測
rf = RandomForestClassifier(n_estimators=100, random_state=42)
rf.fit(X_train, y_train)
prob = rf.predict_proba(X_test)[:, 1]
# Calibration Curve
frac_pos, mean_pred = calibration_curve(y_test, prob, n_bins=5)
plt.figure(figsize=(6, 4))
plt.plot([0, 1], [0, 1], 'k--', label='Perfect')
plt.plot(mean_pred, frac_pos, 's-', label='RandomForest')
plt.xlabel('Mean Predicted Probability')
plt.ylabel('Fraction of Positives')
plt.title('Calibration Curve')
plt.legend()
plt.grid(True)
plt.tight_layout()
plt.show()
info - Unknown Directive
info - Unknown Directivescikit-learn documentation [Probability Calibration curves](https://scikit-learn.org/stable/auto_examples/calibration/plot_calibration_curve.html) ではNaive Bayesがかなり歪んだCalibration Curveを出力すること(そしてrecalibrationにより補正できること)が示されている
新しいReliability Diagram¶
Bröcker & Smith (2007) や Vaicenavicius et al., 2019 で横向きにしたcalibration plotが提案されている
大まかに再現したのが以下のコード
Source
import numpy as np
import matplotlib.pyplot as plt
from sklearn.datasets import make_classification
from sklearn.linear_model import LogisticRegression
from sklearn.model_selection import train_test_split
# データ生成・学習
X, y = make_classification(n_samples=5000, n_features=10, random_state=42)
X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.4, random_state=42)
model = LogisticRegression(random_state=42).fit(X_train, y_train)
prob = model.predict_proba(X_test)[:, 1]
# ビンごとにdeviation・consistency barsを計算
bin_edges = np.linspace(0, 1, 11)
means, devs, counts, lows, highs = [], [], [], [], []
for lo, hi in zip(bin_edges[:-1], bin_edges[1:]):
mask = (prob >= lo) & (prob < hi)
if mask.sum() == 0:
continue
p, yt = prob[mask], y_test[mask]
dev = yt.mean() - p.mean()
rs = [np.random.binomial(1, p).mean() - p.mean() for _ in range(1000)]
means.append(p.mean())
devs.append(dev)
counts.append(mask.sum())
lows.append(np.percentile(rs, 5))
highs.append(np.percentile(rs, 95))
means, devs, counts, lows, highs = map(np.array, [means, devs, counts, lows, highs])
# プロット
fig, ax = plt.subplots(figsize=(6, 4))
ax2 = ax.twinx()
ax2.bar(means, counts, width=0.08, color='steelblue', alpha=0.35, label='# samples')
ax2.set_ylabel('# samples', color='steelblue')
ax.axhline(0, color='black', linewidth=0.8)
ax.vlines(means, lows, highs, colors='red', linewidth=2, label='consistency bars')
ax.hlines(lows, means - 0.02, means + 0.02, colors='red', linewidth=2)
ax.hlines(highs, means - 0.02, means + 0.02, colors='red', linewidth=2)
ax.plot(means, devs, 'x--', color='black', markersize=7, markeredgewidth=2, label='deviation')
ax.set_xlabel('maximum prediction')
ax.set_ylabel('deviation')
ax.set_title('Reliability Diagram')
lines1, labels1 = ax.get_legend_handles_labels()
lines2, labels2 = ax2.get_legend_handles_labels()
ax.legend(lines1 + lines2, labels1 + labels2, fontsize=8)
plt.tight_layout()
plt.show()
Expected Calibration Error (ECE)¶
期待較正誤差 (Expected Calibration Error, ECE) は Naeini, Cooper, and Hauskrecht (2015) によって提案された指標で、binごとの実測比率と平均予測確率の平均絶対誤差。
例えば二値分類だとして、陽性クラスの予測確率を 、ラベルを とする。
予測確率を 個のビン に分けたとき、ECEは次のように定義される。
なお、ECEの派生が様々ある
Maximum Calibration Error (MCE)
Confidence-Calibrated ECE (CC-ECE)