Skip to content

模型评估与指标

本页介绍机器学习的评估方法论:如何科学地衡量一个模型好不好。无论你用决策树、SVM 还是深度网络(见 监督学习、卷积神经网络 CNN),训练完都要面对同一个问题——“这个模型到底行不行?“。选错指标会得出错误结论,划分数据不当会让评估虚高,这些都是实战中最常见的坑。评估方法论是数学基础与工程实践交汇的地方,也是写论文和做技术报告的通用语言。

模型评估要回答两个问题:模型在任务上表现如何(用对指标)、这个表现能不能推广到新数据(用对的验证方法)。常见误区是把训练集上的表现当成真实表现——模型可能只是”背下了”训练数据,遇到新数据就崩溃。

关键直觉:

  • 分类用准确率可能骗人:一个 99% 是正常邮件、1% 是垃圾邮件的场景,模型全部预测”正常”就有 99% 准确率——但它根本没学会区分。这种”类别不平衡”问题要靠精确率、召回率、F1、AUC-ROC 来公正评价。
  • 偏差-方差权衡:模型太简单会”学不会”(欠拟合/高偏差),太复杂会”死记硬背”(过拟合/高方差)。学习曲线能直观看出你卡在哪一头。
  • 交叉验证 = 不浪费数据:把数据切成 K 份,轮流用每份做验证集,其余做训练集,K 次结果的平均更可靠,特别在数据量不大时。

对一个二分类问题,所有预测结果可分为四种情况:

从这四个量推导出常用指标(纯文本公式):

指标公式含义与适用场景
准确率 Accuracy(TP + TN) / 总数整体预测对的比例;类别平衡时才有参考价值
精确率 PrecisionTP / (TP + FP)预测为正的里,实际有多少是正;“宁可放过不可误杀”时关注它
召回率 RecallTP / (TP + FN)实际为正的里,被抓出来多少;“宁可误杀不可放过”时关注它
F1 分数2 × P × R / (P + R)精确率与召回率的调和平均,平衡二者的单一指标
AUC-ROC——不同阈值下召回率 vs 假正例率的曲线下面积,衡量排序能力

精确率 vs 召回率怎么选? 癌症筛查要高召回(漏诊代价大,宁可多做检查);垃圾邮件过滤要高精确(误杀重要邮件代价大,宁可漏放几封垃圾)。两者的权衡由任务的实际代价决定。

F1 分数 = 精确率与召回率的调和平均

Section titled “F1 分数 = 精确率与召回率的调和平均”

调和平均(Harmonic Mean) 的定义是:对两个正数 P 和 R,其调和平均为 2PR / (P + R)。为什么用调和平均而不是算术平均 (P + R) / 2?因为调和平均对极端值更”敏感”——只要 P 或 R 中有一个很小,结果就会被狠狠拉低。

推导过程(从调和平均定义出发):

F1=2×(1P+1R)−1=2×PRR+P=2PRP+RF_1 = 2 \times \left(\frac{1}{P} + \frac{1}{R}\right)^{-1} = 2 \times \frac{PR}{R + P} = \frac{2PR}{P + R}

将 P = TP/(TP+FP) 和 R = TP/(TP+FN) 代入,可化简为只含 TP/FP/FN 的形式:

F1=2×TP2×TP+FP+FNF_1 = \frac{2 \times \text{TP}}{2 \times \text{TP} + \text{FP} + \text{FN}}

直观理解:如果 P = 0.01、R = 1.0,算术平均给出 0.505(看起来还行),但 F1 只有 0.0198(暴露了精确率极低的真相)。调和平均”惩罚”了这种偏科,这正是我们想要的。

何时该用 / 不该用 F1:

  • ✅ 正负类都不平衡,且两者同等重要时(如一般的二分类基准)
  • ❌ 假正例和假反例代价不对称时——用 F_beta(beta > 1 偏召回,beta < 1 偏精确)代替
  • ❌ 多分类时用 macro-F1(每类算 F1 再取算术平均)或 micro-F1(先汇总所有类的 TP/FP/FN 再算)

AUC(Area Under the ROC Curve,ROC 曲线下面积)有一个优雅的概率解释:

AUC=P(score(正样本)>score(负样本))\text{AUC} = P(\text{score}(\text{正样本}) > \text{score}(\text{负样本}))

即:随机取一个正样本和一个负样本,模型给正样本的分数高于负样本分数的概率。这意味着 AUC 衡量的是模型的排序能力——它能不能把正样本排在负样本前面,与具体阈值无关。

推导思路:ROC 曲线上的每一点对应一个阈值 t,坐标为 (FPR(t), TPR(t))。对所有阈值积分:

AUC=∫01TPR(FPR−1(x)) dx\text{AUC} = \int_0^1 \text{TPR}(\text{FPR}^{-1}(x)) \, dx

可以证明(通过交换积分顺序),这等价于对所有 (正样本 i, 负样本 j) 对做平均,统计 score(i) > score(j) 的比例。这正是上面的概率形式。

数值直觉:

  • AUC = 0.5 → 模型排序能力等价于随机猜(正负分数随机分布)
  • AUC = 1.0 → 所有正样本分数都高于所有负样本(完美排序)
  • AUC < 0.5 → 比随机还差(通常说明标签反了)

何时该用 / 不该用 AUC-ROC:

  • ✅ 类别较平衡、关注整体排序能力时
  • ❌ 类别极度不平衡时——此时 FPR 的分母(TN)巨大,FPR 永远很小,ROC 曲线看起来”虚高”。这种场景应改用 PR 曲线与 AUC-PR

R²(Coefficient of Determination,决定系数)衡量回归模型相对于”永远预测均值”这条基线的改善程度:

R2=1−SSresSStot=1−∑i(yi−y^i)2∑i(yi−yˉ)2R^2 = 1 - \frac{\text{SS}_{\text{res}}}{\text{SS}_{\text{tot}}} = 1 - \frac{\sum_i (y_i - \hat{y}_i)^2}{\sum_i (y_i - \bar{y})^2}
  • SS_res(残差平方和):模型预测值与真实值之差的平方和
  • SS_tot(总平方和):真实值与其均值之差的平方和,即”均值基线”的误差

解释:

  • R² = 1.0 → 完美预测(SS_res = 0)
  • R² = 0 → 模型等价于”永远预测均值”(没有任何 explanatory power)
  • R² < 0 → 模型比”永远预测均值”还差(通常意味着模型严重错误)

⚠️ 注意:在测试集上,R² 可以为负。这并非 bug——它正确地告诉你模型还不如基线。训练集上的 R² 则永远 ≥ 0。

Cohen’s Kappa:修正随机一致性的分类指标

Section titled “Cohen’s Kappa:修正随机一致性的分类指标”

Cohen’s Kappa(κ)衡量两个”评估者”(这里一个是模型、一个是真实标签)的一致程度,关键在于减去了”碰巧一致”的部分。在类别不平衡时,即使模型瞎猜多数类,准确率也会很高,而 Kappa 能识破这一点。

κ=po−pe1−pe\kappa = \frac{p_o - p_e}{1 - p_e}
  • p_o(observed agreement)= 实际一致率 = 准确率 = (TP + TN) / N
  • p_e(expected agreement)= 假设两者独立时的期望随机一致率,由各类的边缘分布计算

p_e 的计算(以二分类为例):

pe=(TP+FN)N×(TP+FP)N+(FP+TN)N×(FN+TN)Np_e = \frac{(\text{TP}+\text{FN})}{N} \times \frac{(\text{TP}+\text{FP})}{N} + \frac{(\text{FP}+\text{TN})}{N} \times \frac{(\text{FN}+\text{TN})}{N}

解读标准(Landis & Koch,1977):

  • κ < 0 → 一致性比随机还低(几乎不会出现)
  • κ = 0 → 等于随机水平
  • 0.4 < κ < 0.6 → 中等一致性
  • 0.6 < κ < 0.8 → 良好一致性
  • κ > 0.8 → 几乎完美一致

何时该用:类别不平衡严重、或者想消除”瞎猜多数类”带来的虚高准确率时。

MCC(Matthews Correlation Coefficient,Matthews 相关系数)综合考虑 TP/FP/FN/TN 四个值,产生一个单一指标。它的数学性质在所有二分类指标中最优雅:

MCC=TP×TN−FP×FN(TP+FP)(TP+FN)(TN+FP)(TN+FN)\text{MCC} = \frac{\text{TP} \times \text{TN} - \text{FP} \times \text{FN}} {\sqrt{(\text{TP}+\text{FP})(\text{TP}+\text{FN})(\text{TN}+\text{FP})(\text{TN}+\text{FN})}}
  • 取值范围 [-1, +1]:+1 完美、0 随机、−1 全错
  • 是一个φ系数(phi coefficient),本质上就是 2×2 列联表的皮尔逊相关系数
  • 即使类别极度不平衡也可靠——不像 F1 那样对 TN 不敏感

MCC vs F1 的关键差异:F1 公式里没有 TN,所以在”绝大多数都是负样本”的场景(TN 巨大),F1 可能给出误导性的好成绩,而 MCC 会正确反映模型在负样本上的表现。很多研究表明 MCC 是二分类任务中信息量最大的单一指标。

偏差-方差权衡(Bias-Variance Tradeoff):模型的总误差 = 偏差² + 方差 + 不可约噪声。欠拟合时偏差主导(模型表达能力不够),过拟合时方差主导(模型对训练数据太敏感)。正则化、增加数据、降低模型复杂度都能减小方差;增加特征、换更强模型能减小偏差。

偏差-方差分解是机器学习理论中最优雅的结果之一。它把模型在测试点 x 处的期望泛化误差分解为三个可解释的部分。

设定:真实关系为 y = f(x) + ε,其中 f(x) 是真实函数,ε 是噪声,E[ε] = 0,Var(ε) = σ²。我们用训练集 D 训练得到模型 f̂_D(x),不同训练集 D 得到不同的 f̂_D(x)。

在某个测试点 x₀ 处,期望平方误差为:

ED ⁣[(y−f^D(x0))2]E_D\!\left[(y - \hat{f}_D(x_0))^2\right]

注意这里的期望是对训练集 D 的随机性取的(y 本身因 ε 也是随机的)。推导过程:

步骤 1:展开平方E[(y−f^)2]=E[y2]−2E[y⋅f^]+E[f^2]步骤 2:分别处理每一项E[y2]=E[(f+ε)2]=f2+2f⋅E[ε]+E[ε2]=f2+σ2(因为 E[ε]=0, E[ε2]=σ2)E[y⋅f^]=E[(f+ε)⋅f^]=f⋅E[f^]+E[ε⋅f^](ε 与 f^ 独立→E[ε⋅f^]=0)=f⋅E[f^](E[f^]:=ED[f^D(x0)],模型预测的期望)E[f^2]=Var(f^)+(E[f^])2(方差的定义 Var(X)=E[X2]−(E[X])2)步骤 3:代回=(f2+σ2)−2f⋅E[f^]+Var(f^)+(E[f^])2=[f2−2f⋅E[f^]+(E[f^])2]+Var(f^)+σ2=[f−E[f^]]2⏟偏差2 (Bias2)+Var(f^)⏟方差+σ2⏟不可约噪声\begin{aligned} &\textbf{步骤 1:展开平方} \\ &\quad E[(y - \hat{f})^2] = E[y^2] - 2E[y \cdot \hat{f}] + E[\hat{f}^2] \\[6pt] &\textbf{步骤 2:分别处理每一项} \\ &\quad E[y^2] = E[(f + \varepsilon)^2] = f^2 + 2f \cdot E[\varepsilon] + E[\varepsilon^2] = f^2 + \sigma^2 \\ &\qquad (\text{因为 } E[\varepsilon]=0,\ E[\varepsilon^2]=\sigma^2) \\ &\quad E[y \cdot \hat{f}] = E[(f + \varepsilon) \cdot \hat{f}] = f \cdot E[\hat{f}] + E[\varepsilon \cdot \hat{f}] \\ &\qquad (\varepsilon \text{ 与 } \hat{f} \text{ 独立} \to E[\varepsilon \cdot \hat{f}]=0) \\ &\quad\quad = f \cdot E[\hat{f}] \qquad (E[\hat{f}] := E_D[\hat{f}_D(x_0)],\text{模型预测的期望}) \\ &\quad E[\hat{f}^2] = \text{Var}(\hat{f}) + (E[\hat{f}])^2 \qquad (\text{方差的定义 Var}(X) = E[X^2] - (E[X])^2) \\[6pt] &\textbf{步骤 3:代回} \\ &\quad = (f^2 + \sigma^2) - 2f \cdot E[\hat{f}] + \text{Var}(\hat{f}) + (E[\hat{f}])^2 \\ &\quad = [f^2 - 2f \cdot E[\hat{f}] + (E[\hat{f}])^2] + \text{Var}(\hat{f}) + \sigma^2 \\ &\quad = \underbrace{[f - E[\hat{f}]]^2}_{\text{偏差}^2\text{ (Bias}^2\text{)}} + \underbrace{\text{Var}(\hat{f})}_{\text{方差}} + \underbrace{\sigma^2}_{\text{不可约噪声}} \end{aligned}

最终结果:

E[(y−f^(x0))2]=Bias2(x0)+Var(x0)+σ2E[(y - \hat{f}(x_0))^2] = \text{Bias}^2(x_0) + \text{Var}(x_0) + \sigma^2

其中:

  • Bias(x₀) = E[f̂(x₀)] − f(x₀):模型预测的期望与真实值之差。偏差大 → 欠拟合(模型太简单,表达不了真实关系)
  • Var(x₀) = E[(f̂(x₀) − E[f̂(x₀)])²]:模型预测在不同训练集上的波动。方差大 → 过拟合(对训练数据太敏感)
  • σ²(不可约噪声,Irreducible Noise):数据本身的噪声,任何模型都无法消除

实践指导:

  • 模型复杂度 ↑ → Bias ↓、Var ↑(U 形误差曲线的左右两侧)
  • 增加数据量主要降低 Var(方差),对 Bias 影响不大
  • 增加模型复杂度(更深网络、更多特征)降低 Bias,但可能增加 Var
  • 正则化(L1/L2、dropout、early stopping)直接抑制 Var,代价是可能略增 Bias
  • 学习曲线(见下文代码)能帮你判断当前是 Bias 主导还是 Var 主导,从而决定该”加数据”还是”加复杂度”

铁律:测试集只能用一次。 在测试集上调超参等于”偷看答案”,评估会虚高。如果数据很少,用交叉验证代替固定验证集,但测试集仍然要严格隔离到最后。

上面介绍的是最基础的分类/回归指标。实际工作中还有一批专门针对特定场景的指标——不平衡数据、多分类排序、文本生成、语言模型——它们在各自领域是标配。

PR 曲线(Precision-Recall Curve,精确率-召回率曲线)以召回率为横轴、精确率为纵轴,画出不同阈值下的 (R, P) 点。其下面积 AUC-PR 在类别极度不平衡时比 AUC-ROC 更有区分度。

为什么?在正样本只有 1% 的场景中:

  • ROC 的 FPR = FP/(FP+TN),TN 巨大 → FPR 永远很小 → ROC 曲线”虚高”到接近左上角
  • PR 曲线的 Precision = TP/(TP+FP),直接受 FP 影响 → 只要 FP 多,Precision 立刻降 → 更真实地反映少数类的预测质量
经验法则:正负比 < 1:10 时,优先看 PR 曲线和 AUC-PR。

何时该用:欺诈检测、罕见疾病筛查、缺陷检测——凡是”正样本稀少”的场景。

Top-K Accuracy(Top-K 准确率):只要真实标签在模型预测概率最高的 K 个类别中,就算正确。

Top-K Acc = (预测概率 Top-K 中包含真实标签的样本数) / 总样本数
  • Top-1 就是普通准确率
  • Top-5 在 ImageNet 图像分类中是标配(1000 类中猜对前 5 个就算 OK)
  • 推荐系统中常用 Recall@K(推荐 K 个商品中用户实际喜欢了多少)

何时该用:类别很多(多分类/多标签)、或”猜个大概就行”的场景(推荐、搜索、图像检索)。

BLEU / ROUGE / METEOR(文本生成评估)

Section titled “BLEU / ROUGE / METEOR(文本生成评估)”

这三者是机器翻译、文本摘要、图像描述等文本生成任务的标准自动评估指标。

BLEU(Bilingual Evaluation Understudy,双语评估替补):

  • 核心思想:将模型输出与人工参考译文按 n-gram(连续 n 个词)做匹配,计算匹配比例
  • BLEU-n:n-gram 精确率(precision),BLEU-4 最常用
  • 引入 brevity penalty(简短惩罚):防止模型只输出极短句子来刷精确率
BLEU=BP×exp⁡ ⁣(∑nwn×log⁡pn)\text{BLEU} = \text{BP} \times \exp\!\left(\sum_n w_n \times \log p_n\right)

其中 pn=匹配的 n-gram 数/输出中的 n-gram 总数p_n = \text{匹配的 n-gram 数} / \text{输出中的 n-gram 总数},

BP={1if c>rexp⁡(1−r/c)if c≤r\text{BP} = \begin{cases} 1 & \text{if } c > r \\ \exp(1 - r/c) & \text{if } c \leq r \end{cases}

(cc = 输出长度,rr = 参考长度)

  • 优点:计算快、可复现、广泛用于机器翻译基准
  • 缺点:只看表面 n-gram 重叠,不关心语义;对同义词改写惩罚过重

ROUGE(Recall-Oriented Understudy for Gusting Evaluation):

  • 与 BLEU 偏精确率不同,ROUGE 偏召回率——参考译文中的 n-gram 有多少被模型输出覆盖
  • ROUGE-N:参考译文中 n-gram 的召回率
  • ROUGE-L:基于最长公共子序列(LCS)的 F 分数
  • 何时用:文本摘要任务的标准指标(参考文本通常较长,要衡量”覆盖了多少要点”)

METEOR(Metric for Evaluation of Translation with Explicit ORdering):

  • 在 n-gram 匹配基础上引入同义词匹配和词干还原(stemming)
  • 对语序和精确匹配给予不同权重,与人工评价相关性比 BLEU 更高
  • 何时用:需要更高的人工评价相关性时(代价是依赖外部同义词资源)

共同局限:BLEU/ROUGE/METEOR 都是”表面词重叠”指标,无法捕捉语义等价性。“猫坐在垫子上”和”小猫待在地毯上”语义一致但 n-gram 重叠为 0。现代 LLM 评估更多转向语义相似度(BERTScore)和 LLM-as-Judge。

Perplexity(PPL,困惑度)是自回归语言模型最经典的评估指标,衡量模型对一段文本的”困惑程度”。

数学定义——给定一段文本 w₁, w₂, …, w_N,模型的困惑度为交叉熵的指数:

PPL=exp⁡ ⁣(−1N∑i=1Nlog⁡P(wi∣w<i))\text{PPL} = \exp\!\left(-\frac{1}{N} \sum_{i=1}^{N} \log P(w_i \mid w_{<i})\right)

直观解释:

  • PPL = 模型在每个位置上”等效的有效选择数”。PPL = 10 意味着模型在每个词位置上像是在 10 个等概率候选中”犹豫”
  • PPL 越低 → 模型对真实文本的概率估计越高 → 模型”更不困惑”
  • 最低 PPL 理论上等于文本的真实熵(entropy)

何时该用 / 不该用:

  • ✅ 评估语言模型本身的建模能力(PTB、WikiText 等标准语料的 PPL 是经典基准)
  • ✅ 比较同一架构不同训练阶段的模型(如预训练过程中的监控指标)
  • ❌ 不能直接反映下游任务表现——PPL 低不代表问答/翻译/摘要质量好
  • ❌ 跨不同 tokenizer / 词汇表比较没有意义(PPL 依赖分词方式)

[!NOTE] Perplexity 与 信息论中的交叉熵直接相关:PPL = exp(交叉熵)。对语言模型来说,最小化交叉熵 = 最小化 PPL = 最大化数据的对数似然。

校准度(Calibration)与 Brier Score / ECE

Section titled “校准度(Calibration)与 Brier Score / ECE”

模型的置信度应该与实际正确率一致——一个说”我有 90% 把握”的预测,应该真的有 90% 的概率正确。这叫校准度(Calibration)。

Brier Score(布莱尔分数):衡量概率预测的均方误差,越小越好:

BS=1N∑i=1N(pi−oi)2\text{BS} = \frac{1}{N} \sum_{i=1}^{N} (p_i - o_i)^2

其中 pip_i = 模型预测的概率,oio_i = 实际结果(0 或 1)。

  • BS = 0 → 完美概率预测
  • BS 越小越好。可以分解为三部分:校准损失(calibration loss)+ 区分度(refinement)+ 不确定性

ECE(Expected Calibration Error,期望校准误差):将预测按置信度分桶,计算每桶的”平均置信度”与”平均准确率”之差的加权绝对值:

ECE=∑b=1B∣Bb∣N×∣conf(Bb)−acc(Bb)∣\text{ECE} = \sum_{b=1}^{B} \frac{|B_b|}{N} \times |\text{conf}(B_b) - \text{acc}(B_b)|

其中 BbB_b = 第 b 个置信度区间内的样本,conf(Bb)\text{conf}(B_b) = 该区间内的平均预测概率,acc(Bb)\text{acc}(B_b) = 该区间内的实际正确率。

ECE = 0 → 完美校准。ECE 大 → 模型”嘴上说很确定,实际没那么准”(过度自信)。

何时关注校准:医疗诊断、自动驾驶、风控——任何需要基于模型置信度做决策(而非仅排序)的场景。深度学习模型普遍过度自信(overconfident),需要通过温度缩放(temperature scaling)、Platt scaling 等后处理来校准。

可靠性图(Reliability Diagram):以置信度为横轴、实际准确率为纵轴画柱状图。完美校准的模型,所有柱子落在对角线上;偏离对角线说明该置信度区间存在系统性偏差。

传统的准确率 / F1 / BLEU 等指标在大模型时代面临前所未有的挑战。以下是近年来评估范式的重大变化。

LLM-as-Judge:用大模型评估大模型

Section titled “LLM-as-Judge:用大模型评估大模型”

传统评估指标(BLEU、ROUGE)无法衡量 LLM 生成内容的质量——因为它们只看表面词重叠。2023 年起兴起的 LLM-as-Judge(大模型评审)方法(代表工作:Zheng et al., 2023, “Judging LLM-as-a-Judge with MT-Bench and Chatbot Arena”)让一个强大的 LLM(如 GPT-4)充当裁判,对被评估模型的输出打分或做两两比较。

典型范式:

  • 成对比较(Pairwise):给两个模型的回答,让裁判模型选更好的一个
  • 单答打分(Pointwise):给一个回答,按多维度(有帮助性、安全性、准确性)打 1-10 分
  • 参考答案对比(Reference-guided):提供标准答案,裁判评估模型回答与标准答案的吻合度

已知问题:

  • 位置偏差(Position Bias):裁判可能偏好第一个或第二个回答 → 解决方案:交换顺序做两次,取一致结果
  • 冗长偏差(Verbosity Bias):裁判偏好更长的回答 → 需要控制长度
  • 自我偏好(Self-Bias):GPT-4 倾向于给 GPT-4 系列的回答打高分
  • 能力上限:裁判模型在需要超出自身能力的推理时不可靠(“弱裁判评强模型”问题)

经典基准(MMLU、GSM8K、HumanEval)在 2024-2025 年暴露出严重局限——饱和(顶级模型接近满分)和数据污染。新一代基准应运而生:

  • MMLU-Pro(Wang et al., 2024):在 MMLU 基础上扩充到 10 个选项(原为 4 个,降低猜对概率)、增加推理难度、覆盖 14 个领域。原本 90%+ 的模型在 MMLU-Pro 上骤降到 70% 左右
  • GPQA(Graduate-Level Google-Proof Q&A,Rein et al., 2023):博士级科学问答,专门设计成”Google 搜不到答案”,需要深度推理。专家在自己领域外也难以靠搜索回答
  • ARC-AGI(Abstraction and Reasoning Corpus for AGI,Chollet, 2019;2024 版重新关注):视觉抽象推理任务,衡量”学习新规则”的泛化能力。当前 LLM 在此基准上表现远低于人类——它暴露了 LLM 在真正 few-shot 泛化上的短板
  • SWE-bench(Jimenez et al., 2023):真实 GitHub issue 的代码修复任务,要求模型理解整个代码库。这是目前最接近”软件工程能力”的评估
  • LiveBench / LiveCodeBench(2024):持续更新题库,对抗数据污染——每月发布新题,确保模型不可能在训练时见过

评估的可复现性危机:数据污染与 Benchmark Leakage

Section titled “评估的可复现性危机:数据污染与 Benchmark Leakage”

2024 年的一个重大发现:许多公开基准的测试集已经泄漏进了主流 LLM 的训练数据。这导致排行榜上的高分部分是”背诵”而非”推理”。

  • 数据污染(Data Contamination):测试集出现在训练集中,模型记住了答案。表现为:在原始测试集上分数虚高,而在略有改写的版本上骤降
  • 检测方法:给测试样本做 paraphrase 或 perturbation,观察分数是否大幅下降;或检查模型能否逐字背诵测试集内容
  • 应对策略:动态评估(实时生成新题)、私有测试集(不公开发布,如 Kaggle 竞赛的隐藏测试集)、使用反事实 / 对抗变体

这一问题使得 2024 年前的许多 benchmark 成绩需要重新审视。社区正在推动动态基准和对抗性评估成为新标准。

人类偏好评估:Elo Rating 与 Bradley-Terry 模型

Section titled “人类偏好评估:Elo Rating 与 Bradley-Terry 模型”

LLM 的很多能力(有帮助性、安全风格、创意写作)无法用客观指标衡量,只能靠人类判断。Chatbot Arena(LMSYS,2023-)成为事实标准:用户输入一条 prompt,两个匿名模型的回答并排呈现,用户投票选出更好的一个。基于这些成对比较:

  • Elo Rating(埃洛等级分,源自国际象棋):每场比赛后,赢家分数上升、输家下降,幅度取决于两者的分差和期望胜率。模型在 Arena 上的 Elo 分数实时更新
  • Bradley-Terry 模型:假设每个模型 i 有一个实力参数 β_i,模型 i 战胜模型 j 的概率为:
P(i 胜 j)=exp⁡(βi)exp⁡(βi)+exp⁡(βj)=σ(βi−βj)P(i \text{ 胜 } j) = \frac{\exp(\beta_i)}{\exp(\beta_i) + \exp(\beta_j)} = \sigma(\beta_i - \beta_j)

这等价于逻辑回归——用所有成对比赛结果做极大似然估计,得到每个模型的 Bradley-Terry 分数。相比 Elo,Bradley-Terry 能利用全部历史数据联合优化,估计更稳定。

争议:人类偏好本身有噪声和偏差(偏好更长的回答、偏好礼貌但不正确的回答)。社区正在研究如何结合 LLM-as-Judge 与人类标注来降低成本。

  • 动态评估(Dynamic Evaluation):不使用固定题库,而是根据模型能力实时生成新难度的问题。代表:Dynabench(Li et al., 2023)、ARES。核心理念是”模型一旦在某个基准上饱和,该基准就不再有区分力,必须进化”
  • 对抗性评估(Adversarial Evaluation):专门设计能”难倒”模型的问题。包括对抗样本(输入微小扰动导致输出反转)、OOD 推理(训练分布外的问题)、红队测试(Red Teaming,专门探测安全漏洞和幻觉)
from sklearn.datasets import load_breast_cancer
from sklearn.ensemble import RandomForestClassifier
from sklearn.model_selection import cross_val_score, train_test_split
from sklearn.metrics import classification_report
X, y = load_breast_cancer(return_X_y=True)
X_tr, X_te, y_tr, y_te = train_test_split(X, y, random_state=42)
clf = RandomForestClassifier(random_state=42)
clf.fit(X_tr, y_tr)
# 1. 分类报告:精确率/召回率/F1 一目了然
print(classification_report(y_te, clf.predict(X_te)))
# 2. 5 折交叉验证:更稳健的准确率估计
scores = cross_val_score(clf, X, y, cv=5)
print(f"5 折准确率: {scores.mean():.3f} ± {scores.std():.3f}")
# 输出示例: 5 折准确率: 0.961 ± 0.023

回归任务对应的是 mean_squared_error(MSE)、mean_absolute_error(MAE)、r2_score(R²)。MSE 对大误差更敏感(平方放大),MAE 更鲁棒,R² 是”模型比’永远预测均值’好多少”的比例(1.0 完美,0 等于瞎猜)。

混淆矩阵可视化(seaborn heatmap)

Section titled “混淆矩阵可视化(seaborn heatmap)”

混淆矩阵(Confusion Matrix)可视化能一眼看出模型在哪两类之间容易混淆:

import matplotlib.pyplot as plt
import seaborn as sns
from sklearn.datasets import load_breast_cancer
from sklearn.ensemble import RandomForestClassifier
from sklearn.model_selection import train_test_split
from sklearn.metrics import confusion_matrix
X, y = load_breast_cancer(return_X_y=True)
X_tr, X_te, y_tr, y_te = train_test_split(X, y, random_state=42)
clf = RandomForestClassifier(random_state=42).fit(X_tr, y_tr)
cm = confusion_matrix(y_te, clf.predict(X_te))
plt.figure(figsize=(5, 4))
sns.heatmap(cm, annot=True, fmt='d', cmap='Blues',
xticklabels=['预测: 恶性', '预测: 良性'],
yticklabels=['实际: 恶性', '实际: 良性'])
plt.ylabel('真实标签'); plt.xlabel('预测标签')
plt.title('混淆矩阵')
plt.tight_layout(); plt.show()
# 对角线(TP/TN)越深越好,非对角线(FP/FN)越浅越好

混淆矩阵

ROC 和 PR 曲线对比——注意在类别不平衡时两者的差异:

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
from sklearn.metrics import (roc_curve, auc,
precision_recall_curve, average_precision_score)
# 造一个极度不平衡的数据集(正样本仅 5%)
X, y = make_classification(n_samples=5000, weights=[0.95, 0.05], random_state=42)
X_tr, X_te, y_tr, y_te = train_test_split(X, y, random_state=42)
clf = LogisticRegression().fit(X_tr, y_tr)
scores = clf.predict_proba(X_te)[:, 1] # 正类概率
# --- ROC 曲线 ---
fpr, tpr, _ = roc_curve(y_te, scores)
roc_auc = auc(fpr, tpr)
# --- PR 曲线 ---
precision, recall, _ = precision_recall_curve(y_te, scores)
pr_auc = average_precision_score(y_te, scores) # AUC-PR
fig, axes = plt.subplots(1, 2, figsize=(12, 5))
axes[0].plot(fpr, tpr, label=f'AUC-ROC = {roc_auc:.3f}')
axes[0].plot([0, 1], [0, 1], '--', color='gray', label='随机基线')
axes[0].set_xlabel('假正例率 FPR'); axes[0].set_ylabel('真正例率 TPR')
axes[0].set_title('ROC 曲线'); axes[0].legend()
axes[1].plot(recall, precision, label=f'AUC-PR = {pr_auc:.3f}')
axes[1].axhline(y=sum(y_te)/len(y_te), linestyle='--', color='gray', label='随机基线')
axes[1].set_xlabel('召回率 Recall'); axes[1].set_ylabel('精确率 Precision')
axes[1].set_title('PR 曲线'); axes[1].legend()
plt.tight_layout(); plt.show()
# 在不平衡数据上,ROC 看起来不错(AUC ~0.9+),但 PR 曲线暴露了
# 精确率在某些召回率区间急剧下降——这正是 PR 曲线更有区分力的地方

ROC 与 PR 曲线

学习曲线:判断过拟合还是欠拟合

Section titled “学习曲线:判断过拟合还是欠拟合”

学习曲线(Learning Curve)画出训练集大小 vs 训练/验证分数。两条线的形态直接告诉你模型处于什么状态:

import numpy as np
import matplotlib.pyplot as plt
from sklearn.model_selection import learning_curve
from sklearn.ensemble import RandomForestClassifier
from sklearn.datasets import load_breast_cancer
X, y = load_breast_cancer(return_X_y=True)
clf = RandomForestClassifier(random_state=42)
train_sizes, train_scores, val_scores = learning_curve(
clf, X, y, cv=5, train_sizes=np.linspace(0.1, 1.0, 10),
scoring='accuracy', n_jobs=-1
)
train_mean = train_scores.mean(axis=1)
val_mean = val_scores.mean(axis=1)
train_std = train_scores.std(axis=1)
val_std = val_scores.std(axis=1)
plt.figure(figsize=(8, 5))
plt.plot(train_sizes, train_mean, 'o-', label='训练集准确率')
plt.plot(train_sizes, val_mean, 's-', label='验证集准确率')
plt.fill_between(train_sizes, train_mean - train_std, train_mean + train_std, alpha=0.1)
plt.fill_between(train_sizes, val_mean - val_std, val_mean + val_std, alpha=0.1)
plt.xlabel('训练样本数'); plt.ylabel('准确率')
plt.title('学习曲线'); plt.legend(); plt.grid(True, alpha=0.3)
plt.tight_layout(); plt.show()
# 解读:
# - 训练分高、验证分低、差距大 → 过拟合(高方差)→ 加数据 / 降复杂度 / 正则化
# - 两条线都低且接近 → 欠拟合(高偏差)→ 加特征 / 换更强模型
# - 两条线都高且接近、趋于收敛 → 理想状态
# - 验证分仍在上升 → 加数据可能还有提升

学习曲线

对类别不平衡的数据,普通 KFold 可能某些折里完全没有少数类样本。分层抽样保证每折的类别比例与整体一致:

from sklearn.datasets import make_classification
from sklearn.linear_model import LogisticRegression
from sklearn.model_selection import cross_val_score, StratifiedKFold, KFold
import numpy as np
# 不平衡数据集:正类仅 5%
X, y = make_classification(n_samples=1000, weights=[0.95, 0.05], random_state=42)
clf = LogisticRegression()
# 普通 KFold:可能某折里几乎没有正样本
kfold = KFold(n_splits=5, shuffle=True, random_state=42)
scores_plain = cross_val_score(clf, X, y, cv=kfold, scoring='f1')
# StratifiedKFold:每折类别比例保持一致
skfold = StratifiedKFold(n_splits=5, shuffle=True, random_state=42)
scores_strat = cross_val_score(clf, X, y, cv=skfold, scoring='f1')
print(f'普通 KFold F1: {scores_plain.mean():.3f} ± {scores_plain.std():.3f}')
print(f'分层 KFold F1: {scores_strat.mean():.3f} ± {scores_strat.std():.3f}')
# 分层 KFold 的方差通常更小,估计更可靠——分类任务几乎总应该用它

以下示例展示如何用 PyTorch 计算一个语言模型在给定文本上的困惑度(Perplexity):

import torch
from transformers import AutoTokenizer, AutoModelForCausalLM
def compute_perplexity(model_name, text, device='cuda'):
"""计算语言模型在给定文本上的困惑度"""
tokenizer = AutoTokenizer.from_pretrained(model_name)
model = AutoModelForCausalLM.from_pretrained(model_name).to(device)
model.eval()
encodings = tokenizer(text, return_tensors='pt').to(device)
input_ids = encodings['input_ids']
# seq_len = input_ids.shape[1]
with torch.no_grad():
outputs = model(input_ids, labels=input_ids)
# HuggingFace 的 CausalLM 会自动算交叉熵损失
neg_log_likelihood = outputs.loss # 已经是平均交叉熵
perplexity = torch.exp(neg_log_likelihood)
return perplexity.item()
# 示例:比较两个模型在同一段文本上的困惑度
text = "机器学习是人工智能的一个分支,它使计算机能够从数据中学习规律。"
# ppl_small = compute_perplexity("gpt2", text) # 较小模型,PPL 通常更高
# ppl_large = compute_perplexity("gpt2-medium", text) # 较大模型,PPL 更低
# print(f"GPT-2 small PPL: {ppl_small:.2f}")
# print(f"GPT-2 medium PPL: {ppl_large:.2f}")
# PPL 越低 → 模型对这段文本的预测越自信 → 在该文本上"建模能力"越强

⚠️ 困惑度只能在相同 tokenizer 下比较两个模型。不同词汇表/分词方式的 PPL 数值没有可比性。PPL 低也不代表下游任务好——它是必要非充分条件。

  • 类别不平衡时禁用准确率:99:1 的数据分布下,全预测多数类就有 99% 准确率。这时看 F1、AUC-ROC,或者看少数类的精确率/召回率;极度不平衡(1:100 以上)时优先用 AUC-PR 和 MCC。
  • 单指标选哪个?MCC 信息量最大:MCC 同时考虑 TP/FP/FN/TN 四个值,在所有类别平衡条件下都不会被”欺骗”。需要向非技术读者报告时用 F1(更直觉),做严谨模型对比时用 MCC。
  • 交叉验证的折数:K=5 或 K=10 最常用。数据少时用更大的 K(如留一法 LOOCV)榨取更多信息,但计算更贵且方差更大。分层抽样(StratifiedKFold)保证每折类别比例一致,分类任务必用。
  • 时间序列不能随机划分:必须按时间切分——用过去数据训练、未来数据验证,否则相当于”用未来预测过去”,评估完全失效。
  • 超参调优用验证集,定稿后用测试集:网格搜索 / 贝叶斯优化在验证集上选超参,最终模型在测试集上只评估一次,结果才是可发表的。
  • 回归指标看场景:关注异常值用 MSE/RMSE,关注平均表现用 MAE,需要相对解释力用 R²。
  • 文本生成评估别只靠 BLEU/ROUGE:它们只看表面词重叠,与人工评价相关性有限。2024 年起主流做法是 BLEU/ROUGE 做快速筛选 + LLM-as-Judge 或 BERTScore 做质量评估。
  • 关注模型校准度:如果你的系统会根据模型置信度做决策(如”置信度 > 0.9 才自动审批”),必须检查校准度(ECE、Brier Score)。深度学习模型普遍过度自信,必要时用温度缩放校准。
  • LLM 评估要看 LiveBench 类动态基准:静态基准有数据污染风险。如果模型在 MMLU 上 90%+ 但在 MMLU-Pro 上只有 70%,说明有背诵成分。
  • 模型选择与超参调优:比较决策树 vs SVM vs 随机森林时,用交叉验证的分数决定选哪个;选定模型后用验证集调 max_depth、C 等超参。这是任何机器学习项目的标准流程。
  • 不平衡分类(欺诈检测、疾病筛查、故障预测):欺诈交易只占 0.1%,用精确率-召回率曲线(PR Curve)和 AUC-PR 比 ROC 更能反映真实表现。银行反欺诈、医院疾病早筛都依赖这些指标;需要单一对比指标时用 MCC。
  • 论文与竞赛报告标准:学术论文和 Kaggle 竞赛都有明确的评估指标(accuracy、F1、AUC、MCC、RMSE 等),结果必须用交叉验证或多随机种子平均来保证可复现性。
  • A/B 测试中的模型上线评估:离线指标(F1、AUC)只做初筛,线上效果最终要看业务指标(点击率、转化率)。模型评估方法论是离线评估的基础。
  • 风险决策系统的模型校准:信贷审批、医疗辅助诊断等场景不仅需要模型预测准,还需要置信度可靠——“90% 确信会违约”的客户确实应该有约 90% 的违约率。这类系统必须检查 ECE 和 Brier Score,必要时用温度缩放校准。
  • LLM 能力评估与排行榜:MMLU-Pro、GPQA、HumanEval、SWE-bench 等基准衡量 LLM 的知识、推理、编码能力;Chatbot Arena 用人类偏好的 Elo rating 衡量对话质量;Perplexity 用于监控预训练进度。现代 LLM 评估已经从”单一准确率”演变为多维度、多基准的综合评估体系。
类库语言说明
scikit-learn metricsPython全套分类/回归/排序指标,classification_report 一行出报告;含 cohen_kappa_score、matthews_corrcoef、brier_score_loss、roc_auc_score、average_precision_score
scikit-learn model_selectionPythonK 折/分层/留一交叉验证、网格搜索、随机搜索、learning_curve
seaborn / matplotlibPython混淆矩阵 heatmap、ROC/PR 曲线、学习曲线等可视化
sacrebleu / rouge-scorePythonBLEU / ROUGE 标准化实现(机器翻译、文本摘要评估)
evaluate(HuggingFace)Python统一接口调用 BLEU、ROUGE、BERTScore、Perplexity 等数十种指标
lm-evaluation-harness(EleutherAI)Python开源 LLM 评估框架,支持 MMLU、HellaSwag、GSM8K 等数十种 benchmark
YellowbrickPython可视化诊断工具,学习曲线、ROC 曲线、残差图开箱即用
scipy.statsPython模型比较的统计检验(t 检验、Wilcoxon 检验)
Weka / R caretJava / R传统机器学习评估工具包,适合教学与统计背景用户
术语英文解释
混淆矩阵Confusion MatrixTP/FP/FN/TN 四象限表,分类指标的基础
精确率Precision预测为正中实际为正的比例
召回率Recall实际为正中被正确预测的比例
F1 分数F1-score精确率与召回率的调和平均
AUC-ROCArea Under ROC CurveROC 曲线下面积,衡量分类器的排序能力;等于 P(score(正) > score(负))
AUC-PRArea Under PR CurvePR 曲线下面积,不平衡数据场景比 AUC-ROC 更可靠
Cohen’s KappaCohen’s Kappa修正随机一致性的分类一致度指标,消除”瞎猜多数类”的虚高
MCCMatthews Correlation Coefficient综合考虑 TP/FP/FN/TN 的单一相关指标,即使类别极度不平衡也可靠
R²(决定系数)Coefficient of Determination回归模型相对均值基线的改善比例,1.0 完美、0 等于基线
Top-K 准确率Top-K Accuracy真实标签在预测概率最高的 K 个类别中即算正确
BLEUBLEU基于 n-gram 精确率的机器翻译评估指标
ROUGEROUGE基于 n-gram 召回率的文本摘要评估指标
METEORMETEOR引入同义词和词干匹配的翻译评估指标,与人工评价相关性更高
困惑度Perplexity语言模型交叉熵的指数,衡量模型对文本的”困惑程度”,越低越好
Brier ScoreBrier Score概率预测的均方误差,衡量校准度和准确度
ECEExpected Calibration Error期望校准误差,衡量置信度与实际正确率的偏差
校准度Calibration模型置信度与实际正确率的一致程度
偏差-方差权衡Bias-Variance Tradeoff模型复杂度与泛化能力的权衡关系
交叉验证Cross-Validation数据分 K 折轮流验证的评估方法
过拟合Overfitting模型在训练集表现好、验证/测试集表现差(高方差)
欠拟合Underfitting模型在训练集和验证集都表现差(高偏差)
不可约噪声Irreducible Noise数据本身的噪声,任何模型都无法消除(偏差-方差分解中的 σ²)
数据污染Data Contamination测试集泄漏到训练集中,导致评估虚高
LLM-as-JudgeLLM-as-Judge用强大 LLM 充当裁判评估其他模型的输出质量
Elo RatingElo Rating基于成对比赛结果实时更新的能力评分系统,用于 Chatbot Arena

经典基础

  • 偏差-方差分解:理论推导见 Hastie et al.《The Elements of Statistical Learning》第 2 章和第 7 章,是理解过拟合的经典论述。
  • 不平衡学习:He & Garcia (2009) “Learning from Imbalanced Data” 综述,系统讨论重采样、代价敏感学习等方法。
  • 交叉验证的统计性质:关于 K 折与留一法方差的深入分析,见 Kohavi (1995) “A Study of Cross-Validation and Bootstrap for Accuracy Estimation and Model Selection”。
  • MCC vs F1 的系统比较:Chicco & Jurman (2020) “The advantages of the Matthews correlation coefficient (MCC) over F1 score and accuracy in binary classification evaluation”,论证 MCC 是二分类信息量最大的单一指标。
  • 校准度:Guo et al. (2017) “On Calibration of Modern Neural Networks”,系统分析深度网络过度自信问题并提出温度缩放校准法。

LLM 评估(2023–2025)

  • LLM-as-Judge:Zheng et al. (2023) “Judging LLM-as-a-Judge with MT-Bench and Chatbot Arena”(arXiv:2306.05685),开创用 GPT-4 评审模型输出的范式。
  • MMLU-Pro:Wang et al. (2024) “MMLU-Pro: A More Robust and Challenging Benchmark for LLMs”(arXiv:2406.01574),对 MMLU 的全面升级。
  • GPQA:Rein et al. (2023) “GPQA: A Graduate-Level Google-Proof Q&A Benchmark”(arXiv:2311.12022),博士级科学问答。
  • Chatbot Arena 与 Bradley-Terry:Chiang et al. (2024) “Chatbot Arena: An Open Platform for Evaluating LLMs by Human Preference”(arXiv:2403.04132),Arena 评分系统的统计方法。
  • 数据污染综述:Balloççe & Renoust (2024) 对 LLM benchmark contamination 的系统梳理,涵盖检测方法和影响分析。
  • SWE-bench:Jimenez et al. (2023) “SWE-bench: Can Language Models Resolve Real-World GitHub Issues?”(arXiv:2310.06770),真实软件工程评估。
  • LiveBench:White et al. (2024) “LiveBench: A Challenging, Contamination-Limited LLM Benchmark”(arXiv:2406.19314),持续更新的动态基准。

工具与平台

  • Chatbot Arena(https://chat.lmsys.org):LMSYS 维护的实时人类偏好评估平台,是 LLM 能力排名的事实标准。
  • Open LLM Leaderboard(Hugging Face):社区驱动的开源模型评估排行榜。
  • lm-evaluation-harness(EleutherAI):开源 LLM 评估框架,支持数十种 benchmark 的标准化评估。

相关文档