机器学习模型预测不准?用Python手把手教你概率校准(附完整代码)
·
机器学习模型预测不准?用Python手把手教你概率校准(附完整代码)
在金融风控、医疗诊断等关键领域,我们不仅需要模型给出分类结果,更希望了解预测结果的置信度。但你是否遇到过这种情况:模型预测某客户违约概率为80%,实际违约比例却只有50%?这种预测概率与真实发生频率的偏差,正是概率校准要解决的核心问题。
1. 概率校准的本质与价值
概率校准的本质是建立预测概率与真实发生频率之间的映射关系。想象一下天气预报:当气象台预测"降雨概率70%"时,我们期望在100次这样的预测中,实际降雨次数接近70次。机器学习模型的概率预测同样需要满足这种一致性。
为什么优秀模型也需要校准?
- 逻辑回归等简单模型天生具有概率解释性
- 但随机森林、XGBoost等复杂模型输出的"概率"实质上是类别比例
- 即使原生支持概率输出的模型,在样本不平衡时也会出现偏差
实际案例:某银行信用卡审批系统使用随机森林模型,预测"高风险"客户中实际违约比例比预测值低15%,导致风险准备金严重高估。
校准后的概率在以下场景尤为重要:
- 需要计算期望损失的风险评估
- 多模型结果融合的集成系统
- 成本敏感型决策的阈值选择
2. 校准效果评估方法论
2.1 可靠性图表(Reliability Diagram)
可靠性图表是直观展示校准效果的金标准。其绘制步骤包括:
- 将预测概率区间[0,1]分为10等份(0-0.1, 0.1-0.2,...,0.9-1.0)
- 计算每个区间内样本的:
- 平均预测概率(x轴)
- 实际正例比例(y轴)
- 绘制点线图并与对角线(y=x)对比
from sklearn.calibration import calibration_curve
prob_true, prob_pred = calibration_curve(y_test, y_proba, n_bins=10)
plt.plot(prob_pred, prob_true, marker='o', label='Our Model')
plt.plot([0, 1], [0, 1], linestyle='--', label='Perfectly Calibrated')
2.2 定量评估指标
除了可视化,我们还需要量化指标:
| 指标名称 | 计算公式 | 理想值 |
|---|---|---|
| Brier Score | $\frac{1}{N}\sum(y_i-p_i)^2$ | 0 |
| ECE | $\sum|acc(b)-conf(b)|$ | 0 |
| Log Loss | $-y\log(p)-(1-y)\log(1-p)$ | 越小越好 |
from sklearn.metrics import brier_score_loss
print(f"Brier Score: {brier_score_loss(y_test, y_proba):.4f}")
3. 两大校准方法实战
3.1 Platt Scaling(Sigmoid校准)
适用于中小数据集(样本量<1000)的参数化方法:
from sklearn.calibration import CalibratedClassifierCV
from sklearn.svm import SVC
base_model = SVC(kernel='rbf')
platt_model = CalibratedClassifierCV(base_model, method='sigmoid', cv=3)
platt_model.fit(X_train, y_train)
# 获取校准后概率
calibrated_probs = platt_model.predict_proba(X_test)[:, 1]
关键参数解析:
cv=3:使用3折交叉验证防止过拟合method='sigmoid':指定Platt校准方法ensemble=True:是否使用多模型集成(默认True)
3.2 Isotonic回归校准
更适合大数据集的非参数方法,能学习任意单调映射:
isotonic_model = CalibratedClassifierCV(base_model, method='isotonic', cv=3)
isotonic_model.fit(X_train, y_train)
# 对比校准前后效果
print(f"原始模型Brier Score: {brier_score_loss(y_test, base_model.predict_proba(X_test)[:, 1]):.4f}")
print(f"Isotonic校准后: {brier_score_loss(y_test, isotonic_model.predict_proba(X_test)[:, 1]):.4f}")
方法对比指南:
| 特性 | Platt Scaling | Isotonic回归 |
|---|---|---|
| 数据需求 | 少量数据即可 | 需要大量数据 |
| 映射灵活性 | 固定sigmoid形式 | 任意单调函数 |
| 计算效率 | 高 | 较低 |
| 抗过拟合能力 | 强 | 需交叉验证 |
4. 完整项目实战:信用风险评估
让我们通过一个端到端案例演示完整流程:
4.1 数据准备与基线模型
import pandas as pd
from sklearn.datasets import make_classification
from sklearn.model_selection import train_test_split
# 生成模拟信用数据
X, y = make_classification(n_samples=10000, n_features=20,
n_informative=15, weights=[0.9, 0.1],
random_state=42)
# 划分训练/校准/测试集
X_train, X_temp, y_train, y_temp = train_test_split(X, y, test_size=0.4)
X_cal, X_test, y_cal, y_test = train_test_split(X_temp, y_temp, test_size=0.5)
# 训练XGBoost基线模型
from xgboost import XGBClassifier
xgb = XGBClassifier(n_estimators=300, learning_rate=0.05)
xgb.fit(X_train, y_train)
4.2 校准实施与评估
# 定义校准函数
def evaluate_calibration(model, X, y, method='sigmoid'):
calibrated = CalibratedClassifierCV(model, method=method, cv='prefit')
calibrated.fit(X_cal, y_cal)
probs = calibrated.predict_proba(X_test)[:, 1]
# 绘制可靠性图
prob_true, prob_pred = calibration_curve(y_test, probs, n_bins=10)
plt.plot(prob_pred, prob_true, marker='o', label=f'{method}校准')
# 计算指标
brier = brier_score_loss(y_test, probs)
print(f"{method}校准Brier Score: {brier:.5f}")
return calibrated
# 对比不同方法
plt.figure(figsize=(10, 6))
plt.plot([0, 1], [0, 1], 'k--', label='理想校准')
evaluate_calibration(xgb, X_test, y_test, 'sigmoid')
evaluate_calibration(xgb, X_test, y_test, 'isotonic')
plt.legend()
4.3 业务应用示例
# 模拟业务决策:根据风险概率设置不同审批策略
def approval_strategy(prob, threshold=0.5):
if prob < 0.3:
return "自动通过"
elif 0.3 <= prob < 0.7:
return "人工审核"
else:
return "自动拒绝"
# 应用校准前后的差异示例
sample_idx = 10
raw_prob = xgb.predict_proba(X_test[sample_idx:sample_idx+1])[0, 1]
calibrated_prob = isotonic_model.predict_proba(X_test[sample_idx:sample_idx+1])[0, 1]
print(f"原始预测概率: {raw_prob:.2f} → 决策: {approval_strategy(raw_prob)}")
print(f"校准后概率: {calibrated_prob:.2f} → 决策: {approval_strategy(calibrated_prob)}")
5. 高级技巧与避坑指南
5.1 样本划分策略
校准需要独立的数据集,常见数据使用方式:
-
预划分法(推荐):
- 原始训练集 → 训练基础模型
- 独立校准集 → 训练校准器
- 测试集 → 最终评估
-
交叉验证法:
CalibratedClassifierCV(base_estimator=model, method='isotonic', cv=5)
5.2 类别不平衡处理
当正负样本比例悬殊时:
- 优先选择
method='sigmoid' - 在校准前先进行类别平衡采样
- 使用
class_weight参数调整基础模型
xgb = XGBClassifier(scale_pos_weight=sum(y==0)/sum(y==1))
5.3 多分类问题校准
对于K类问题,有两种策略:
-
One-vs-Rest(默认):
- 对每个类别单独训练二分类校准器
- 最后归一化概率总和
-
矩阵缩放(更复杂但更准确):
from sklearn.calibration import CalibratedClassifierCV calibrated = CalibratedClassifierCV(base_model, method='isotonic', cv=5, ensemble=False)
在医疗诊断项目中,使用Isotonic校准将多分类模型的临床决策准确率提升了12%,避免了过度自信预测导致的误诊风险。
更多推荐



所有评论(0)