在做大模型效果评估时,很多同学应该都遇到过这样的场景:同一个模型输出,5 位标注者给出的分数可能从 3 分一直跨度到 5 分,最后按平均分排序,模型 A 和模型 B 可能只差 0.02。换一批标注者之后,结论甚至可能反转。更麻烦的是,即使平均分稳定,这个综合分数也没办法直接解释成“用户有多大比例认为这个回答是好的”。
这类问题本质上涉及两件事:一是把多个评估信号聚合成一个综合分数(Aggregate),二是把这个综合分数校准成有概率意义的结果(Calibrate)。把两个动作放在一起,并研究它们的执行顺序,就是本文要拆解的Aggregate-then-Calibrate(先聚合再校准)思想。
这篇文章会先讲清楚以人为中心评估中的聚合与校准是什么,然后通过一个可运行的 Python 实验,对比“先聚合再校准”和“先校准再聚合”两种流程的差异,最后补充理论保证的大致来源、常见问题与工程建议。无论你是做 NLP 评估、推荐系统效果分析,还是业务侧的用户满意度建模,这套方法论都可以直接用。
1. 背景与核心概念
1.1 什么是以人为中心的评估
以人为中心的评估(Human-centered Assessment)是指以人类判断作为基准的评估体系。和我们熟悉的自动化指标不同,它强调评估结果应该反映真实用户的感受、偏好或价值判断。
举几个典型例子:
- 大模型生成内容的回答是否有用、是否安全、是否符合用户意图;
- 推荐系统推荐的结果是否让用户感到满意;
- 智能客服的回复是否解决了用户问题;
- AI 辅助决策系统给出的建议是否被领域专家认可。
在这些场景中,最终评估标准不是某一个公式或某一条规则,而是“人怎么看”。但人的判断存在主观性和噪声,因此需要一套流程把多个人的判断整合起来,形成稳定、可解释、可比较的结果。
这里容易混淆的是“评估对象”和“评估信号”。评估对象是模型输出、推荐结果、决策建议等;评估信号则是标注者或用户给出的分数、排序、选择等反馈。以人为中心的评估要解决的核心问题,就是从一堆带有噪声的评估信号中,提取出关于评估对象的可靠结论。
1.2 聚合与校准分别解决什么问题
聚合(Aggregate)解决的是“多个信号如何变成一个数字”的问题。
假设我们有 K 个标注者对某个模型输出打分,最简单的聚合方式是取平均。但实际项目中往往需要更复杂的聚合方式,例如:
- 按标注者历史准确率进行加权平均;
- 使用 Bradley-Terry 模型从两两对比中估计综合实力分数;
- 使用 Elo 评分系统处理动态评估;
- 在 RLHF 中训练奖励模型,拟合人类偏好。
聚合可以让多个噪声较大的评估信号互相抵消一部分随机误差。按照独立同分布噪声的简单模型,K 个独立噪声的均值方差会缩小为原来的 1/K,因此聚合后的分数往往比单个标注者的分数更稳定。
校准(Calibrate)解决的是“这个分数能不能被理解成概率”的问题。
举个例子:某个模型回答的综合评分是 4.2 分(满分 5 分),这 4.2 分意味着什么?它能不能换算成“80% 的用户会认为这个回答很好”?如果不能,那么不同模型之间的 0.1 分差距就难以解释,也无法用于风险控制或决策。
校准要做的事情,就是找到一个单调映射,把原始分数映射成真实的概率估计。让“预测概率为 0.8 的样本”中,实际有约 80% 的样本确实属于正类。常见校准方法包括 Platt Scaling、温度缩放、Isotonic Regression 等。
1.3 为什么“先聚合再校准”值得关注
在同时需要聚合和校准的流程里,存在两种顺序选择:
- 先聚合多个评估信号,再对聚合后的综合分数做校准;
- 先对每个评估信号分别做校准,再把校准后的概率聚合起来。
从直觉上看,先校准再聚合似乎更精细,因为每个评估信号都被单独处理了。但在真实数据中,这种方法有一个很大的风险:单个标注者的评估信号噪声较高,如果每个标注者都单独训练一个校准器,校准器很容易过拟合到该标注者的噪声上。
先聚合再校准则不同。聚合阶段先把多个高噪声信号合并成一个低噪声的综合分数,校准阶段只需要在这个低噪声分数上拟合一个简单的单调映射。这样一来,统计学习的复杂度更低,有限样本下更容易获得稳定的概率输出。
本文后续的实验就是要直观验证这个现象。
2. 环境准备与实验设计
2.1 环境依赖
本文示例基于 Python 实现,主要依赖 NumPy 和 scikit-learn。
建议环境如下:
- Python 3.9 及以上版本;
- NumPy 1.21 及以上版本;
- scikit-learn 1.0 及以上版本。
不同版本之间 API 基本兼容,如果你使用的版本较新,通常可以直接运行。如果版本较旧,需要注意sklearn.metrics.brier_score_loss在旧版本中可能位于sklearn.metrics下,这个不需要额外处理。
安装依赖命令:
pip install numpy scikit-learn2.2 实验目标
实验会模拟一个典型的以人为中心评估场景:
- 有一批待评估样本,每个样本有一个真实的“质量标签”;
- 有 5 位标注者,每位标注者都会对样本打一个 0 到 1 之间的分数;
- 标注者存在个人偏差和随机噪声;
- 我们需要把 5 个标注者的分数处理成一个具有概率意义的预测值。
接着,我们分别实现两条流程:
- 先聚合再校准;
- 先校准再聚合。
最后用 Brier Score 和 Expected Calibration Error(ECE)对比两条流程的校准质量。
实验使用合成数据,好处是可以知道真实标签,能够准确评估校准效果。实际项目中,真实标签往往来自专家复核或业务结果,评估方式是一样的。
2.3 数据生成思路
为了让模拟数据尽量贴近真实评估场景,我们假设每个标注者的打分由三部分组成:
- 真实质量,即标注者都能看到一部分真实信号;
- 个人偏差,即有的标注者普遍给高分,有的普遍给低分;
- 随机噪声,即标注者每次打分时不稳定。
这个数据生成方式很直观:真实质量是二分类标签,但人类打分是在真实质量基础上叠加偏差和噪声。实验代码会使用同一个随机种子,方便复现。
3. 核心方法拆解
3.1 聚合阶段的常用方案
在真实项目中,聚合不一定是简单平均,需要根据评估任务选择合适的方法。
简单平均是最常用的基线。当标注者水平接近时,简单平均简单有效,但无法处理“某个标注者明显更专业”的情况。
加权平均是简单平均的扩展。权重可以来自标注者历史标注准确率,也可以来自标注者在专家复核样本上的表现。权重越高,说明该标注者对最终聚合结果的影响越大。
排序融合则适合“相对比较”场景。例如让标注者对多个回答进行两两对比,再通过 Bradley-Terry 模型估计每个回答的综合分。这种方法不要求标注者给出绝对分数,只要求相对判断,在人类偏好收集中非常常见。
在 RLHF 场景中,聚合往往体现为训练一个奖励模型。奖励模型输入一段文本和对应的响应,输出一个标量分数,拟合的是人类标注者对“哪个响应更好”的偏好。这个奖励模型的输出就相当于聚合后的综合分数。
无论采用哪种聚合方式,目标都是一样的:利用多来源信息,减少单个评估信号带来的随机误差。
3.2 校准阶段的常用方案
校准的目标是把一个任意范围的分数映射到概率空间 [0,1],并且让映射后的预测概率与真实频率一致。
Platt Scaling 是一种经典的参数校准方法。思路非常简单:使用一个带截距的逻辑回归模型,把原始分数作为唯一特征,拟合真实标签。
from sklearn.linear_model import LogisticRegression calibrator = LogisticRegression() calibrator.fit(raw_score.reshape(-1, 1), y_true) calibrated_prob = calibrator.predict_proba(raw_score.reshape(-1, 1))[:, 1]温度缩放是神经网络中常见的校准方法。它通过一个温度参数 T 对数几率(logits)进行缩放,再计算 softmax 概率。温度缩放不会改变预测类别,只会改变概率分布的置信程度。T 越大,概率越平滑;T 越小,概率越尖锐。
Isotonic Regression 是一种非参数校准方法,它拟合一个单调递增的分段常数函数。该方法不假设原始分数与概率之间满足 logistic 关系,因此拟合能力更强,但需要更多数据,否则容易过拟合。
选择哪种校准方法,取决于样本量和原始分数的分布形态。样本量较少时,优先使用参数化方法;样本量充足时,可以考虑非参数方法。
3.3 理论保证从哪里来
理解 Aggregate-then-Calibrate 为什么有效,可以从偏差-方差分解和统计学习复杂度两个角度来理解。
Brier Score 的定义是:
Brier Score = E[(p_pred - y)^2]它可以分解为两部分:
E[(p_pred - E[y|x])^2] + E[Var(y|x)]其中第一部分是预测概率与真实条件概率之间的偏差,第二部分是数据本身不可避免的噪声。校准的目标是尽量缩小第一部分。
先聚合再校准时,聚合阶段降低了输入分数的方差。也就是说,校准器看到的特征更稳定,和真实标签之间的相关性更强。此时校准器只需要学习一个相对平滑的映射,模型复杂度可以更低,有限样本下的泛化误差也就更容易控制。
先校准再聚合时,每个标注者的分数都带有较强噪声。要为每个标注者单独拟合一个校准器,每个校准器都必须处理“高噪声输入到标签”的复杂映射,这需要更大的假设空间和更多的样本。在标注者数量多、每人标注样本少的情况下,校准器很容易过拟合。
从学习理论的角度看,假设空间越复杂,Rademacher 复杂度越高,泛化误差上界越松;而先聚合再校准相当于先用无监督或半监督方式压缩了输入维度,降低了学习问题的有效复杂度。因此,它能够提供比先校准再聚合更紧的理论保证。
当然,具体论文中的定理会精确地给出误差上界,但核心逻辑就是上述偏差-方差权衡:聚合减少方差,校准控制偏差,顺序问题本质上是统计复杂度问题。
4. 完整实战案例:两种顺序的效果对比
下面我们通过一个完整的 Python 实验,对比两条流程。
4.1 生成模拟评估数据
首先导入依赖并生成模拟数据。
import numpy as np from sklearn.linear_model import LogisticRegression from sklearn.metrics import brier_score_loss from sklearn.model_selection import train_test_split np.random.seed(42) n_samples = 3000 X = np.random.randn(n_samples, 4) y = (X[:, 0] + 0.5 * X[:, 1] - 0.2 * X[:, 2] > 0).astype(int) n_raters = 5 rater_scores = [] for r in range(n_raters): bias = np.random.normal(0, 0.15) score = y + bias + np.random.normal(0, 0.35, n_samples) score = np.clip(score, 0, 1) rater_scores.append(score) S = np.column_stack(rater_scores)这段代码做了四件事:
- 随机生成 3000 个样本特征;
- 根据线性组合生成真实二分类标签;
- 模拟 5 位标注者,每位标注者有个人偏差和随机噪声;
- 把所有标注者的分数组合成矩阵 S,每一列代表一位标注者。
np.clip(score, 0, 1)是为了模拟标注者打分时只能给出 0 到 1 之间的分数。
4.2 划分数据集并实现“先聚合再校准”
接下来划分训练集和测试集,并实现先聚合再校准。
S_train, S_test, y_train, y_test = train_test_split( S, y, test_size=0.3, random_state=42 ) agg_train = S_train.mean(axis=1) agg_test = S_test.mean(axis=1) cal_agg = LogisticRegression() cal_agg.fit(agg_train.reshape(-1, 1), y_train) p_agg_cal = cal_agg.predict_proba(agg_test.reshape(-1, 1))[:, 1]这里的关键细节是:
- 先对训练集和测试集分别做平均聚合,避免信息泄露;
- 校准器只在训练集上拟合;
- 对测试集预测概率,用于最终评估。
agg_train.reshape(-1, 1)是因为LogisticRegression要求输入特征为二维数组。
4.3 实现对照方案“先校准再聚合”
我们再实现先对每个标注者分别校准,再对校准概率取平均。
p_rater_list = [] for r in range(n_raters): cal_r = LogisticRegression() cal_r.fit(S_train[:, r].reshape(-1, 1), y_train) p_r = cal_r.predict_proba(S_test[:, r].reshape(-1, 1))[:, 1] p_rater_list.append(p_r) p_cal_agg = np.mean(p_rater_list, axis=0)这条流程中,每位标注者都有自己独立的逻辑回归校准器。校准器学习的是“该标注者的分数到真实标签概率”的映射。最后把 5 个校准概率取平均。
看起来这条流程更精细,但因为每位标注者的分数噪声较大,单个校准器更容易过拟合。这一点在后面的评估结果中会体现出来。
4.4 计算评估指标
为了对比,我们再计算一个未校准基线的结果,以及 Brier Score 和 ECE 指标。
def expected_calibration_error(y_true, y_prob, n_bins=10): bins = np.linspace(0, 1, n_bins + 1) total = 0.0 n = len(y_true) for i in range(n_bins): mask = (y_prob > bins[i]) & (y_prob <= bins[i + 1]) if mask.sum() == 0: continue conf = y_prob[mask].mean() acc = y_true[mask].mean() total += (mask.sum() / n) * abs(conf - acc) return total然后评估三种方案:
p_raw = np.clip(agg_test, 0, 1) print("Raw Aggregated Score") print(" Brier:", brier_score_loss(y_test, p_raw)) print(" ECE :", expected_calibration_error(y_test, p_raw)) print("Calibrate-then-Aggregate") print(" Brier:", brier_score_loss(y_test, p_cal_agg)) print(" ECE :", expected_calibration_error(y_test, p_cal_agg)) print("Aggregate-then-Calibrate") print(" Brier:", brier_score_loss(y_test, p_agg_cal)) print(" ECE :", expected_calibration_error(y_test, p_agg_cal))其中p_raw是把原始平均分裁剪到 [0,1] 后直接当作预测概率,严格来说它不满足概率性质,这里仅作为未校准基线对照。
4.5 运行与结果解读
把上述代码按顺序组合保存为calibration_demo.py,然后运行:
python calibration_demo.py不同随机种子和不同数据分布下,具体数值会有浮动,但整体模式通常比较稳定:
- 未校准的原始聚合分数,Brier Score 和 ECE 通常最高;
- 先校准再聚合,相比未校准有一定提升,但每个标注者独立校准时会带入额外方差;
- 先聚合再校准,Brier Score 和 ECE 通常最低,因为校准器输入更稳定,拟合出的映射更可靠。
这个实验的意义在于:当多个评估信号都存在噪声时,先把它们合并成一个相对稳定的综合分数,再做概率校准,是更稳妥的选择。
5. 常见问题与排查思路
在实验和应用中,你可能会遇到以下几类问题。
| 问题现象 | 常见原因 | 解决思路 |
|---|---|---|
| 校准后概率仍然集中在 0.5 附近 | 特征与标签关系较弱,数据噪声过大 | 增加更有效的评估信号;检查标签定义是否清晰 |
| ECE 指标忽高忽低 | 分箱数量不合理或测试样本太少 | 调整 bin 数量;使用多个随机种子重复实验 |
| 先校准再聚合的效果反而更差 | 单个评估信号噪声大,校准器过拟合 | 改用先聚合再校准;增加每个评估者的标注样本量 |
| 聚合分数裁剪后直接计算 Brier 分数 | 原始分数不是概率 | 必须先做概率校准,再计算 Brier Score |
| 训练集和测试集划分不当导致结果虚高 | 聚合或校准过程使用了测试集信息 | 确保聚合参数和校准器只在训练集上拟合 |
如果你在自己的项目中看到校准效果不明显,建议先画一张可靠性图(Reliability Diagram)。把预测概率分成 10 个区间,横轴是预测概率,纵轴是实际正类频率。如果散点明显偏离对角线,就说明校准不到位;如果散点贴着对角线,则说明当前方案已经比较可靠。
另外要注意,Brier Score 对极端概率更敏感,而 ECE 对常见概率区间更敏感。两者结合使用,能更全面地判断校准效果。
6. 最佳实践与工程建议
6.1 把评估维度拆开建模
以人为中心评估中,一个常见误区是让标注者打一个“综合分”。但综合分往往混淆了多个维度,例如有用性、安全性、流畅性。更好的做法是让每个维度单独打分,再在聚合阶段按业务权重合并。这样既能定位模型问题,也有利于后续校准。
6.2 标注者权重需要谨慎设置
在加权聚合时,权重不能只看标注者之间的平均分差异。有的标注者分数普遍偏高,但排序能力很强;有的标注者分数接近全局均值,但区分度很差。建议用“校准后的排序相关性”或“对真实标签的预测能力”来计算权重,而不是简单使用均值。
6.3 校准集必须独立
无论是 Platt Scaling 还是 Isotonic Regression,校准器都应该在一个独立的验证集上拟合。如果直接在训练集上拟合,再在测试集上评估校准效果,得到的结果会偏乐观。更严谨的做法是把数据划分为训练集、校准集、测试集三部分。
6.4 结合自动化指标使用
校准后的概率适合做决策,但不一定适合做模型排名的唯一依据。A/B 场景中,可以先使用自动化指标筛掉明显较差的模型,再对少量候选模型进行以人为中心的细粒度评估。这样既保留了自动化指标的效率,又能充分利用人类评估的准确性。
6.5 关注长尾样本
校准是对整体概率分布的拟合,但长尾样本往往更关键。例如,大模型在安全敏感问题上的回答可能只占少量比例,却直接影响产品风险。建议在评估时对长尾类型单独计算 ECE,而不是只关注整体指标。
7. 总结与下一步
本文围绕 Aggregate-then-Calibrate 这一思想,拆解了以人为中心评估中的两个关键动作:聚合与校准。聚合解决的是多评估信号如何合成的问题,校准解决的是分数如何变成概率的问题。
通过实验可以看到,在标注者噪声较大的场景中,先聚合再校准通常优于先校准再聚合。根本原因在于聚合降低了输入特征的方差,让校准器可以专注于学习一个更简单的映射,从而在有限样本下获得更好的泛化能力。
如果接下来想深入这个方向,可以考虑从三个层面继续学习。
第一个层面是概率校准。深入理解温度缩放、Platt Scaling、Isotonic Regression 的适用条件,以及 Brier Score、ECE、可靠性图等评估工具。
第二个层面是聚合方法。学习 Bradley-Terry 模型、Elo 评分、奖励模型训练,以及如何处理标注者偏差和噪声。
第三个层面是理论分析。阅读关于校准误差上界、Rademacher 复杂度、偏差-方差分解的文献,理解为什么“先聚合再校准”能够带来理论保证。
如果你近期打算在自己的评估流程中引入校准,建议先从 Brier Score 和 ECE 两个指标开始,把评估分数和真实标签记录下来,做一次简单的 Platt Scaling,对比一下校准前后的差异。多数情况下,你会看到校准带来的提升,也能更自信地解释评估结果背后的概率含义。