模型输出的概率可信吗?用 CalibratedClassifierCV 校准并核对 Brier 分数

在训练数据内部用 sigmoid 拟合概率校准器,用独立测试集同时比较 Brier 分数、准确率和分组发生频率。

分类器给出 0.8,并不自动表示相似条件下有 80% 的样本属于正类。概率校准的任务是把模型输出与观察到的发生频率对齐。可以用 CalibratedClassifierCV 在训练数据内部拟合校准映射,再用独立测试集同时查看 Brier 分数和校准曲线。

先分清分类正确率和概率质量

示例核对环境为 Python 3.11、scikit-learn 1.9.1、NumPy 2.4.6;涉及表格的代码还使用 pandas 3.0.6。资料核对日期为 2026 年 10 月 1 日。代码在 CPU 上运行,不需要账号、API 密钥或下载预训练权重。

模型输出的概率可信吗?用 CalibratedClassifierCV 校准并核对 Brier 分数

本例用固定种子生成 1,800 条二分类演示样本,以 GaussianNB 为基础分类器,再比较 sigmoid 校准前后的结果。数据含冗余特征,目的是演示概率诊断和校准接口,不是模拟真实客户或证明 GaussianNB 总需要校准。

准确率只看选中的类别是否正确;Brier 分数比较正类概率与真实 0/1 标签的平方误差,越低越好,但它还受区分能力和数据本身的不确定性影响。官方校准指南特别说明:更低的 Brier 损失不能单独证明校准程度更好。还要看概率分组中预测均值与实际正类比例是否接近。

例如一组样本平均预测 0.7,实际只有约 0.45 属于正类,就是值得检查的过度自信现象;这不等于对单个 0.7 的预测已经知道真值。

用训练集内部交叉验证拟合校准器

python -m venv .venv
# Windows PowerShell 中使用这个环境的解释器:
.\.venv\Scripts\python.exe -m pip install scikit-learn==1.9.1 numpy==2.4.6 pandas==3.0.6
.\.venv\Scripts\python.exe demo.py

把下方完整 Python 代码保存为 demo.py,再运行最后一条命令。macOS/Linux 使用 .venv/bin/python 代替 Windows 路径。安装需要网络;完成安装后,这些示例的数据在代码中生成,可离线运行。使用其他版本时先打印 sklearn.__version__,不要把两个环境的报错混在一起排查。

先留下 30% 测试数据。CalibratedClassifierCV 的 cv=3 在训练部分组织内部拟合和校准,测试数据不参与这一步。CalibratedClassifierCV 官方接口说明 estimator、method 和 cv 的含义;sigmoid 是一种校准映射,不能把它当成“把每个概率都调得更准确”的保证。

import numpy as np
from sklearn.datasets import make_classification
from sklearn.model_selection import train_test_split
from sklearn.naive_bayes import GaussianNB
from sklearn.calibration import CalibratedClassifierCV, calibration_curve
from sklearn.metrics import brier_score_loss, accuracy_score

X, y = make_classification(n_samples=1800, n_features=12, n_informative=4,
                          n_redundant=6, weights=[0.7, 0.3], random_state=13)
X_train, X_test, y_train, y_test = train_test_split(
    X, y, test_size=0.3, stratify=y, random_state=13)
plain = GaussianNB().fit(X_train, y_train)
calibrated = CalibratedClassifierCV(estimator=GaussianNB(), method="sigmoid", cv=3)
calibrated.fit(X_train, y_train)
for name, model in [("plain", plain), ("calibrated", calibrated)]:
    positive_col = np.flatnonzero(model.classes_ == 1).item()
    prob = model.predict_proba(X_test)[:, positive_col]
    observed, estimated = calibration_curve(y_test, prob, n_bins=5, strategy="quantile")
    print(name, "brier", round(brier_score_loss(y_test, prob), 4),
          "accuracy", round(accuracy_score(y_test, model.predict(X_test)), 4))
    print("mean-pred/observed", np.round(np.c_[estimated, observed], 3).tolist())
    assert np.isfinite(prob).all() and ((0 <= prob) & (prob <= 1)).all()

同时检查曲线分组和分数

plain brier 0.107 accuracy 0.8741
mean-pred/observed [[0.0, 0.009], [0.001, 0.019], [0.034, 0.111], [0.7, 0.454], [1.0, 0.917]]
calibrated brier 0.096 accuracy 0.8741
mean-pred/observed [[0.073, 0.009], [0.073, 0.019], [0.084, 0.111], [0.563, 0.454], [0.814, 0.917]]

本次演示中 Brier 从 0.1070 变为 0.0960,准确率都约为 0.8741。它展示了类别预测基本不变时,概率仍可以发生变化。输出的每一对数字依次是平均预测概率、观察到的正类比例。校准前第四组约为 [0.700, 0.454],校准后约为 [0.563, 0.454];校准后的前两组仍没有完全贴近实际比例,不能把这次运行解释为已经解决所有概率偏差。

验证时还要核对 classes_:代码从类别列表查找标签 1 对应的列,不假定任意分类器的第二列总是你的业务正类。n_bins=5、strategy=”quantile” 是为小型演示按样本数组织分组;某些分组因概率重复可能合并,不应要求任何数据都固定输出五行。

什么情况下先别信校准结果

  • 每一折缺少某类:先检查训练标签分布与 cv。少量正类不能支持稳定的概率映射。
  • 同一客户跨折或数据有时间顺序:改用符合数据关系的交叉验证,不能随机拆分后声称概率可靠。
  • 用测试集选择校准方法或分组数量:测试集已参与选择,需重新留出最终检查数据。
  • 上线发生率改变:重新检查来源和发生率,旧数据拟合的映射不保证仍适用。

校准不保证准确率提升,也不让预测变成因果解释。isotonic 等其他方法有各自样本量和过拟合风险;这篇先给出一个可检查的 sigmoid 基线,换方法时应使用同样的独立数据和诊断步骤。

Ai菜鸟网。发布者:AI小管家,转载请注明出处:https://www.alyyhw.com/30569.html

赞 (0)
AI小管家的头像AI小管家
数值和类别特征怎么一起处理?用 ColumnTransformer 建立混合列管道
上一篇 10小时前
分类样本不平衡怎么处理?比较 class_weight 前后的少数类召回
下一篇 10小时前

相关推荐

联系我们

联系我们

1

在线咨询: QQ交谈

邮件:admin@example.com

工作时间:周一至周五,9:30-18:30,节假日休息

关注微信
关注微信
分享本页
返回顶部