机器学习流程中,「模型好不好」的判断如果本身就不靠谱,后续所有优化都是空中楼阁。从二分类的 AUC 到生成式任务的 LLM-as-Judge,评估方法论的跨度远超想象。本文给出一个可落地的评估体系框架。
评估体系全景
评估的目标不是「一个分数」,而是回答三个问题:模型在目标任务上多强?部署后能否稳定保持?回归风险在哪里? 完整评估体系分为四层:
离线评估(Offline Evaluation):在固定评测集上计算指标,快速、可复现,用于模型选型与迭代。
在线评估(Online Evaluation):通过 A/B 测试、影子部署(Shadow Deployment)在真实流量上对比,用于最终上线决策。
持续评估(Continuous Evaluation):监控生产环境中的指标漂移与数据漂移,触发再训练或回滚。
对齐与安全评估:对于大模型,还需要评估有害性、幻觉率、指令遵循等安全维度。
离线评估(选型) → 在线评估(上线) → 持续评估(监控)
↑ ↓
└────────────── 回归 / 再训练 ←────────┘
| 评估类型 | 数据来源 | 频率 | 决策作用 |
|---|---|---|---|
| 离线评估 | 固定评测集 | 每次迭代 | 模型选型 |
| 在线 A/B | 真实流量 | 上线前 | 上线放量 |
| 影子部署 | 真实流量(不引流) | 上线前 | 无风险对比 |
| 持续监控 | 生产流量 + 标签 | 持续 | 漂移告警/回滚 |
分类指标
分类任务的指标矩阵建立在混淆矩阵四要素之上:TP(正类预测为正)、FP(负类预测为正)、FN(正类预测为负)、TN(负类预测为负)。
$$Precision = \frac{TP}{TP+FP}, \quad Recall = \frac{TP}{TP+FN}, \quad F1 = \frac{2 \times Precision \times Recall}{Precision + Recall}$$
准确率(Accuracy) 在类别不平衡下严重失真:99:1 的正负比,全预测负类也有 99% 准确率。不平衡场景应优先看 Precision/Recall/F1。
| 指标 | 关注点 | 适用场景 | 缺点 |
|---|---|---|---|
| Accuracy | 整体正确率 | 类别均衡 | 不平衡失真 |
| Precision | 预测为正的可信度 | 垃圾邮件(误杀成本高) | 忽略漏报 |
| Recall | 正类的覆盖度 | 疾病筛查(漏诊成本高) | 忽略误报 |
| F1 | Precision/Recall 调和 | 均衡关注 | 无概率信息 |
| AUC-ROC | 排序能力 | 排序/阈值无关评估 | 对不平衡不敏感 |
AUC-ROC 度量模型区分正负类的排序能力,与阈值无关:随机模型的 AUC=0.5,完美模型=1.0。它尤其适合排序类任务(推荐、风控),且不受类别不平衡影响——但要注意 AUC 关注「相对排序」而非「绝对概率」,两个模型 AUC 相同概率分布可能完全不同。
from sklearn.metrics import (
precision_score, recall_score, f1_score,
roc_auc_score, roc_curve, confusion_matrix
)
y_true = [1, 0, 1, 1, 0, 1, 0, 0, 1, 0]
y_pred = [1, 0, 0, 1, 0, 1, 0, 1, 1, 0]
y_prob = [0.9, 0.2, 0.3, 0.8, 0.1, 0.85, 0.15, 0.6, 0.7, 0.05]
print("Precision:", precision_score(y_true, y_pred)) # 5/6
print("Recall:", recall_score(y_true, y_pred)) # 4/5
print("F1:", f1_score(y_true, y_pred)) # 0.727
print("AUC:", roc_auc_score(y_true, y_prob)) # 0.960
阈值选择:模型输出的是概率,阈值(默认 0.5)应按业务损益调整。风控场景用高阈值保 Precision(宁可漏报不放错);医疗筛查用低阈值保 Recall(宁可误报不漏诊)。阈值调优的标准工具是 Precision-Recall 曲线:找到 Precision 与 Recall 的交点或业务可接受的平衡点。
回归与概率校准
回归任务的核心指标是预测误差:
$$MAE = \frac{1}{n}\sum|y_i - \hat{y}_i|, \quad RMSE = \sqrt{\frac{1}{n}\sum(y_i - \hat{y}_i)^2}$$
RMSE 对异常值更敏感(平方放大),MAE 更稳健。相对误差用 MAPE(平均绝对百分比误差)或对称的 SMAPE,适用于量纲差异大的场景(如不同商品的销量预测)。
概率校准(Calibration) 解决的是「概率是否可信」问题:模型输出 0.8 的置信度,是否真的有 80% 的样本为正?ECE(Expected Calibration Error) 是衡量校准度的标准指标——把预测概率分桶,比较桶内平均预测概率与实际正例率之差。
$$ECE = \sum_{m=1}^{M} \frac{|B_m|}{n} \left| \text{acc}(B_m) - \text{conf}(B_m) \right|$$
import numpy as np
from sklearn.calibration import calibration_curve
def expected_calibration_error(y_true, y_prob, n_bins=10):
bins = np.linspace(0, 1, n_bins + 1)
ece = 0.0
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() # 桶内实际正例率
ece += mask.sum() / len(y_true) * abs(acc - conf)
return ece
# 校准后的模型应使 ECE 趋近 0
ece = expected_calibration_error(y_true, y_prob)
print(f"ECE = {ece:.3f}") # 越接近 0 校准越好
校准方法:Platt Scaling(逻辑回归拟合 logits→概率)与 Temperature Scaling(单参数缩放 logits)。对大模型,温度缩放是最常用的校准手段。
生成式评估:BLEU/ROUGE
生成任务(翻译、摘要、问答)的输出是文本,无法直接套分类指标。传统上使用基于重叠的自动指标:
BLEU:统计生成文本与参考文本的 n-gram 匹配率,侧重精确率,惩罚过短输出,常用于机器翻译。
ROUGE:统计参考文本中的 n-gram/最长公共子序列在生成文本中的覆盖,侧重召回率,常用于摘要。
$$ROUGE\text{-}L = \frac{LCS(X, Y)}{|Y|} \quad(LCS:最长公共子序列)$$
| 指标 | 侧重 | 对短输出 | 典型任务 | 局限 |
|---|---|---|---|---|
| BLEU | 精确率(n-gram 匹配) | 惩罚 | 机器翻译 | 忽略语义等价 |
| ROUGE-1/2 | 召回率(词/二元组) | 宽松 | 摘要 | 同义词不识别 |
| ROUGE-L | 最长公共子序列 | 宽松 | 摘要 | 句子顺序敏感 |
| METEOR | 同义词 + 词形还原 | 温和 | 翻译 | 依赖语言资源 |
| BertScore | 语义相似度(BERT) | 温和 | 摘要/问答 | 计算成本高 |
from nltk.translate.bleu_score import sentence_bleu
from rouge_score import rouge_scorer
reference = ["大模型评估需要结合自动指标与人工判断"]
generated = "大模型评估要结合自动指标和人工判断"
bleu = sentence_bleu([reference], generated, weights=(0.25, 0.25, 0.25, 0.25))
print(f"BLEU = {bleu:.3f}")
scorer = rouge_scorer.RougeScorer(["rouge1", "rouge2", "rougeL"], lang="zh")
scores = scorer.score(reference, generated)
print({k: v.fmeasure for k, v in scores.items()})
基于重叠的指标对「语义等价但措辞不同」的答案评分极低,而在开放式问答中这是常态。因此现代 LLM 评估中,BLEU/ROUGE 只作为辅助参考,主力是人工评估与 LLM-as-Judge。
人工评估与 LLM-as-Judge
人工评估(Human Evaluation) 是生成式任务的黄金标准,但成本高、不一致性大。生产实践通常对每个版本抽 100-300 条样本,由 3-5 名标注员按统一 Rubric 打分。
LLM-as-Judge:用强模型(如 GPT-4、Claude)对候选回答打分或比较,成本低、速度快、可复现,已成为大模型迭代的主要评估手段。
JUDGE_PROMPT = """你是评估员。比较模型回答与参考答案,按以下维度打分(1-5):
- 正确性(事实准确,无幻觉)
- 完整性(覆盖所有要点)
- 相关性(紧扣问题)
输出 JSON:{"correctness": n, "completeness": n, "relevance": n, "comment": "..."}"""
def llm_judge(question, answer, reference=None):
response = judge_llm.invoke([
{"role": "system", "content": JUDGE_PROMPT},
{"role": "user", "content": f"问题:{question}\n回答:{answer}\n参考答案:{reference or '无'}"}
])
return parse_json(response.content)
基准偏差(Positional Bias) 是 LLM-as-Judge 的已知陷阱:评审对排在前面的回答有偏好。缓解手段包括 Pairwise 比较 + 交换顺序(把 A/B 和 B/A 各评一次取一致结果)、以及使用专门训练的评审模型(如 Reward Model)。
| 评估方式 | 成本 | 速度 | 一致性 | 适用 |
|---|---|---|---|---|
| 人工评估 | 高 | 慢 | 中 | 最终验收、黄金标准 |
| LLM-as-Judge | 低 | 快 | 高 | 迭代回归、大规模筛选 |
| 自动指标 | 极低 | 极快 | 高 | 翻译/摘要等受限任务 |
| 混合 | 中 | 中 | 高 | 生产推荐 |
评测集构建
评测集的质量决定评估的可靠性,构建方法论包括:
Golden Set(黄金评测集):人工构造的标准问答/标注集,是离线评估的基石。数量 200-2000 条,覆盖正常样本、边界样本与困难样本。
对抗样本(Adversarial Examples):主动构造「容易骗过模型」的输入——同音词替换、错别字、双重否定、跨领域指代等,用于暴露模型的脆弱点。
分层覆盖:评测集应按业务分层(意图、领域、难度、语言),而不是随机抽样——随机抽样会让容易样本淹没困难样本,掩盖模型短板。
{
"test_suite": {
"normal_cases": 120, // 正常业务问题
"edge_cases": 40, // 边界(空输入、超长、非常规表达)
"adversarial": 30, // 对抗样本(错别字、歧义、诱导)
"domain_shift": 10 // 新领域样本
},
"labeling": {
"standard": "人工标注标准答案",
"difficulty": ["easy", "medium", "hard"],
"count_per_sample": 3
}
}
评估集污染(Contamination):大模型预训练数据可能包含公开评测集,导致分数虚高。缓解手段:使用未公开的私有评测集、监测模型对「背诵类」问题的异常高正确率、评测集定期更新。
数据分布对齐:离线评测集的分布必须与生产流量分布一致,否则离线指标与在线效果脱节。常用手段是采样生产日志构造评测集,并定期回流新样本。
离线 vs 在线评估
离线评估回答「理论上好不好」,在线评估回答「真实用户感受如何」。两者可能严重背离:
| 维度 | 离线评估 | 在线评估 |
|---|---|---|
| 数据 | 固定评测集 | 真实流量 |
| 环境 | 受控、可复现 | 生产环境、有噪声 |
| 指标 | 精确(AUC/F1) | 业务(转化率/留存) |
| 周期 | 分钟级 | 天级-周级 |
| 风险 | 无 | 影响线上 |
A/B 测试:把流量按比例分给对照(旧模型)与实验(新模型)两组,比较业务指标。要点:随机分配、样本量足够(用统计检验判断显著性)、控制混杂变量(同时段、同用户)。
影子部署(Shadow Deployment):新模型与线上模型同时处理相同请求,但新模型的输出只记录不返回用户,避免影响线上。收集影子数据后离线分析新模型的质量,无风险地获得「接近在线」的反馈。
import random
def ab_assign(user_id: str, exp_ratio: float = 0.2) -> str:
"""简单哈希分桶:保证同一用户始终进同一组。"""
return "experiment" if (hash(user_id) % 100) < exp_ratio * 100 else "control"
# 影子部署:新模型结果仅记录
for request in traffic:
online_result = prod_model(request) # 返回用户
shadow_result = candidate_model(request) # 仅记录,用于离线分析
log_to_store(request, online_result, shadow_result)
经验法则:离线指标是「必要非充分」条件——离线差的模型不值得上线,离线好的模型不一定在线好。重大模型变更必须经过在线 A/B,而小版本迭代可以用影子部署做低成本把关。
模型卡与基准报告
模型卡(Model Card) 是模型的可解释性文档,回答「这个模型能干什么、不能干什么、谁负责」:
| 模型卡要素 | 内容 |
|---|---|
| 模型概述 | 架构、参数量、训练数据 |
| 预期用途 | 目标场景、用户群体 |
| 评估结果 | 评测集与指标分数 |
| 局限性 | 已知失败模式、覆盖不足的领域 |
| 公平性 | 各子群体指标差异 |
| 安全与偏见 | 有害输出、偏见检测结果 |
| 使用与维护 | 部署方式、负责团队、再训练计划 |
基准报告(Benchmark Report) 记录每次评估的完整上下文,保证可复现:评测集版本、模型权重版本、推理超参(温度/top-p)、评估日期与评估工具版本。
# benchmark_report.yaml 示例
model:
name: "ChatQwen-7B-sft-v3"
base: "Qwen2.5-7B-Instruct"
checkpoint: "run_20260920_epoch2"
evaluation:
dataset: "golden_set_v2.1"
metric: ["accuracy", "faithfulness", "harmlessness"]
judge_model: "gpt-4o" # LLM-as-Judge 的评审模型
temperature: 0.0 # 评估用确定性采样
seed: 42
results:
accuracy: 0.882
faithfulness: 0.91
harmlessness_pass_rate: 0.99
date: "2026-09-25"
可复现性是评估报告的生命线:同一模型、同一评测集,若两次跑出不同分数,一定是评估流程引入了随机性(未固定 seed、评估时用了采样)。生产评估默认温度=0、固定 seed、固定推理框架版本。
持续评估流程与常见坑
上线不是评估的终点。持续评估闭环包括:
指标监控:记录在线业务指标 + 抽样回流评测(把生产请求抽样打标加入下一版评测集)。
漂移检测(Drift Detection):监控输入分布漂移(数据漂移)与预测分布漂移(概念漂移),用 PSI(Population Stability Index)或 KS 检验量化。
回归触发:当监控指标跌破阈值或漂移显著,触发再训练或回滚。
import numpy as np
def psi(expected: np.ndarray, actual: np.ndarray, n_bins: int = 10) -> float:
"""Population Stability Index:衡量两个分布的分桶差异。"""
eps = 1e-6
bins = np.linspace(0, 1, n_bins + 1)
e_hist, _ = np.histogram(expected, bins=bins, density=True)
a_hist, _ = np.histogram(actual, bins=bins, density=True)
e_hist += eps; a_hist += eps
e_pct = e_hist / e_hist.sum()
a_pct = a_hist / a_hist.sum()
return float(np.sum((a_pct - e_pct) * np.log(a_pct / e_pct)))
# 行业经验:PSI < 0.1 稳定;0.1-0.25 需关注;>0.25 需处理
score = psi(expected_dist, production_dist)
print(f"PSI = {score:.3f}")
常见坑清单:
- 评测集污染:评测样本出现在训练集中,指标虚高
- 指标与业务脱节:只优化 F1 却不管误报的业务损失
- 采样偏差:评测集分布与生产不一致
- LLM-as-Judge 偏差:位置偏差、自偏袒(评审偏好自己的输出风格)
- 随机性未控:不固定 seed/温度,分数不可复现
- 只在「晴天」评估:没有覆盖极端与罕见输入
- 一次性评估:无持续回流,模型悄然退化而不自知
评估的最终检验标准是:指标变化能正确预测业务变化。如果 F1 上升了但用户投诉率没变,说明评估指标没有抓住业务真正关心的质量维度。
总结
| 任务类型 | 推荐指标 | 评估手段 |
|---|---|---|
| 分类 | Precision/Recall/F1/AUC | 混淆矩阵 + 阈值调优 |
| 回归 | MAE/RMSE/MAPE | 误差分析 + 概率校准 |
| 排序 | AUC / MRR / NDCG | 离线排序评测 |
| 生成 | BLEU/ROUGE/BertScore | 自动指标 + 人工 + LLM-as-Judge |
| 大模型 | Faithfulness/Harmlessness | Golden Set + Judge + 安全评估 |
| 在线 | 业务指标 + A/B 显著性 | 影子部署 + 持续监控 |
模型评估的成熟度决定机器学习工程的成熟度。建立「离线评测集 → 在线 A/B → 持续监控」的完整闭环,用可复现、可对业务负责的指标驱动每一次迭代,是评估工程的核心要义。
继续阅读
探索更多技术文章
浏览归档,发现更多关于系统设计、工具链和工程实践的内容。