使用Scikit-learn包的CalibratedClassifierCV

举报
yd_37369233 发表于 2026/08/31 11:04:28 2026/08/31
【摘要】 CalibratedClassifierCV 用于校准分类器的预测概率。许多分类器(如 SVM、决策树、随机森林)的 predict_proba 输出的概率并不准确,该类通过交叉验证来校准这些概率。核心概念概念 │ 说明──────────┼──────────────────────────────────────────────────────────────────────校准...

CalibratedClassifierCV 用于校准分类器的预测概率。许多分类器(如 SVM、决策树、随机森林)的 predict_proba 输出的概率并不准确,该类通过交叉验证来校准这些概率。

核心概念

概念 │ 说明
──────────┼──────────────────────────────────────────────────────────────────────
校准方法 │ sigmoid(Platt 缩放,适合小样本)或 isotonic(保序回归,适合大样本)
──────────┼──────────────────────────────────────────────────────────────────────
交叉验证 │ 内部用 CV 防止过拟合,避免用训练数据校准自身
──────────┼──────────────────────────────────────────────────────────────────────
包装器 │ 包裹任意实现了 fit / predict_proba 的分类器

基本用法

from sklearn.datasets import make_classification
from sklearn.model_selection import train_test_split
from sklearn.svm import SVC
from sklearn.calibration import CalibratedClassifierCV
from sklearn.metrics import brier_score_loss

# 1. 生成数据
X, y = make_classification(n_samples=1000, n_features=20, random_state=42)
X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.2, random_state=42)

# 2. 基础分类器(SVC 默认不支持 predict_proba,概率未校准)
base_clf = SVC(kernel='rbf')

# 3. 用 CalibratedClassifierCV 包装
#    method='sigmoid' -> Platt scaling
#    cv=5             -> 5 折交叉验证
calibrated_clf = CalibratedClassifierCV(base_clf, method='sigmoid', cv=5)
calibrated_clf.fit(X_train, y_train)

# 4. 校准后的概率
proba = calibrated_clf.predict_proba(X_test)
print("校准后 Brier score:", brier_score_loss(y_test, proba[:, 1]))

对比校准前后效果

import numpy as np
import matplotlib.pyplot as plt
from sklearn.naive_bayes import GaussianNB
from sklearn.calibration import calibration_curve

# 用朴素贝叶斯做对比(其概率通常校准较差)
clf = GaussianNB()
clf.fit(X_train, y_train)
proba_uncalibrated = clf.predict_proba(X_test)[:, 1]

calibrated = CalibratedClassifierCV(clf, method='isotonic', cv=5)
calibrated.fit(X_train, y_train)
proba_calibrated = calibrated.predict_proba(X_test)[:, 1]

# 绘制校准曲线
fig, ax = plt.subplots(1, 1, figsize=(6, 6))
for name, proba in [('未校准', proba_uncalibrated), ('校准后', proba_calibrated)]:
    frac_pos, mean_pred = calibration_curve(y_test, proba, n_bins=10)
    ax.plot(mean_pred, frac_pos, marker='o', label=name)

ax.plot([0, 1], [0, 1], 'k--', label='完美校准')
ax.set_xlabel('平均预测概率')
ax.set_ylabel('实际正样本比例')
ax.set_title('校准曲线 (Calibration Curve)')
ax.legend()
plt.tight_layout()
plt.savefig('calibration_curve.png', dpi=150)
plt.show()

# Brier score 对比
print("未校准 Brier:", brier_score_loss(y_test, proba_uncalibrated))
print("校准后 Brier:", brier_score_loss(y_test, proba_calibrated))

两种校准方法对比

from sklearn.ensemble import RandomForestClassifier

base = RandomForestClassifier(n_estimators=100, random_state=42)

for method in ['sigmoid', 'isotonic']:
    cal = CalibratedClassifierCV(base, method=method, cv=5)
    cal.fit(X_train, y_train)
    p = cal.predict_proba(X_test)[:, 1]
    print(f"method={method:10s}  Brier={brier_score_loss(y_test, p):.4f}")

关键参数说明

CalibratedClassifierCV(
    estimator=None,        # 基础分类器(旧版叫 base_estimator)
    method='sigmoid',      # 'sigmoid' 或 'isotonic'
    cv=5,                  # 交叉验证折数;设为 'prefit' 表示模型已训练好
    n_jobs=None,           # 并行数
)

cv=‘prefit’ 模式(模型已训练好)

# 先单独训练模型
base_clf = SVC(kernel='rbf', probability=True)
base_clf.fit(X_train, y_train)

# 再用一个独立的校准数据集来校准
X_calib, y_calib = X_test[:100], y_test[:100]   # 校准集
X_eval,  y_eval  = X_test[100:], y_test[100:]   # 评估集

calibrated = CalibratedClassifierCV(base_clf, cv='prefit')
calibrated.fit(X_calib, y_calib)   # 仅做校准,不重新训练

proba = calibrated.predict_proba(X_eval)
print("prefit Brier:", brier_score_loss(y_eval, proba[:, 1]))

选择建议

场景 │ 推荐配置
────────────────────────┼─────────────────────────────────────────
样本量 < 1000 │ method=‘sigmoid’(参数少,不易过拟合)
────────────────────────┼─────────────────────────────────────────
样本量 ≥ 1000 │ method=‘isotonic’(更灵活,校准更精确)
────────────────────────┼─────────────────────────────────────────
模型已训练好,仅需校准 │ cv=‘prefit’ + 独立校准集
────────────────────────┼─────────────────────────────────────────
需要并行加速 │ n_jobs=-1

│ 注意:校准只改善概率估计的质量(Brier score、log loss),不一定提升分类准确率(accuracy)。如果你的下游任务依赖概率值(如设置阈值、排序、风险评估),校准就非常有价值。

【版权声明】本文为华为云社区用户原创内容,未经允许不得转载,如需转载请自行联系原作者进行授权。如果您发现本社区中有涉嫌抄袭的内容,欢迎发送邮件进行举报,并提供相关证据,一经查实,本社区将立刻删除涉嫌侵权内容,举报邮箱: cloudbbs@huaweicloud.com
  • 点赞
  • 收藏
  • 关注作者

评论(0

0/1000
抱歉,系统识别当前为高风险访问,暂不支持该操作

全部回复

上滑加载中

设置昵称

在此一键设置昵称,即可参与社区互动!

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。