Skip to content

微调后评估与回归 ​

摘要:微调优化的只是单一分布,最大风险是「任务变好、其他崩坏」。本文给出三层评测(通用基准 MMLU/HellaSwag 防遗忘、MT-Bench 防指令漂移、自建 eval 验任务)、把评测接进 CI 的 eval gate、私有 golden set 防污染,以及回归判定与回滚。工具:lm-evaluation-harness(EleutherAI)、FastChat/MT-Bench、lighteval。版本:([版本相关])。

适用版本与前提 ​

  • 工具:lm-eval(EleutherAI lm-evaluation-harness)、lm-eval 0.4.x、fschat(MT-Bench judge)、lighteval
  • 模型:任意 HuggingFace 格式 checkpoint,含 LoRA 适配器(可直接评,无需合并)
  • 环境:Python 3.12 + CUDA 12 示例([版本相关],以官方安装说明为准)

核心概念:为什么必须评测 ​

「训出来了」≠「变好了」

训练 loss 下降、RL reward 上升都可能伴随真实质量下降(奖励黑客、熵崩塌)。只有 held-out 评测能区分「真改进」与「过拟合/退化」。微调典型失败模式:MMLU 相对基座掉 > 3 分 = 知识被压缩;MT-Bench 降但训练 loss 更低 = 指令遵循漂移;自建 eval 过但用户投诉 = 分布不匹配。

三层评测覆盖不同失败模式:

层工具/集检测什么
通用基准MMLU / HellaSwag / TruthfulQA灾难性遗忘(知识/常识回归)
指令遵循MT-Bench(GPT-4 判分)多轮指令遵循漂移
任务评测自建 golden set你的真实任务是否真变好

架构与原理:eval gate ​

可复现是底线

分数只有在「同一 harness 版本、同一 prompt、同一 few-shot、同一 metric、同一 dtype」下才可比。每个评测集需 pin 版本与 task revision;自建集用私有 golden set(不会被训练数据污染)。对一个未去污染的基准,分数视为「未知」而非「高」。

生产实践 ​

评测门禁(eval gate)

  • 通用基准:MMLU 5-shot(对齐原论文)、HellaSwag/ARC/TruthfulQA 监控。MMLU 相对基座跌幅 > 3 分需警惕,> 5 分基本判定遗忘严重。
  • MT-Bench:80 道多轮题由强模型判分,检测指令遵循;需 API key(judge 一般调用 GPT-4 级模型)。
  • 自建 eval:用你的真实输入/期望输出构造,定义成功率/忠实度阈值(社区实践常设 faithfulness ≥ 0.90、answer relevance ≥ 0.85 之类门禁,[阈值依业务定])。
  • CI 化:把评测写成 pytest 风格(DeepEval/Ragas/promptfoo 等),回归即阻断发布。监控生产侧质量与反馈,对 faithfulness 下降而非 GPU 利用率报警。

操作步骤:跑 MMLU 对比 ​

bash
# 安装(版本以官方为准,[版本相关])
pip install lm-eval
lm_eval --version   # 期望 0.4.x;[未实测具体输出]

# 微调后 checkpoint
lm_eval --model hf \
  --model_args pretrained=/path/to/checkpoint,dtype=bfloat16 \
  --tasks mmlu --num_fewshot 5 \
  --batch_size auto --output_path ./results/ft.json

# 基座(算 delta)
lm_eval --model hf \
  --model_args pretrained=meta-llama/Llama-3.1-8B,dtype=bfloat16 \
  --tasks mmlu --num_fewshot 5 \
  --batch_size auto --output_path ./results/base.json
python
# 逐项对比 MMLU 跌幅,标注 >3 分的学科
import json
ft = json.load(open("./results/ft.json"))
base = json.load(open("./results/base.json"))
for task, r in ft["results"].items():
    b = base["results"].get(task, {}).get("acc,none", 0)
    f = r.get("acc,none", 0)
    if abs(f - b) > 0.03:
        print(f"{task}: {f-b:+.3f} (base={b:.3f}, ft={f:.3f})")  # [示例逻辑,实际输出依运行]

直接评 LoRA 适配器

lm-eval 支持直接评 PEFT 适配器,无需合并:

bash
lm_eval --model hf \
  --model_args pretrained=meta-llama/Llama-3.1-8B-Instruct,peft=/path/to/lora-adapter \
  --tasks mmlu

用 vLLM 后端可大幅加速生成类任务:--model vllm --model_args pretrained=./merged,tensor_parallel_size=4。

验证 ​

bash
# 1) 先 --limit 10 验证抽取与判分逻辑正确,再跑全量
# 2) --check_integrity 校验基准数据未被破坏
# 3) 对比 base vs ft 的 MMLU/HellaSwag;领域基准应升、通用基准跌幅受控
# 4) 自建 golden set 跑通过率,与历史基线比对

回滚与清理 ​

评测不通过的处理

  • 评测门禁未通过 = 不发布;回退到上一通过版本或回到训练/改数据阶段。
  • 评测产物(分数 JSON、样本)需与 checkpoint 版本一同留存,便于审计与复现。
  • 删除实验 checkpoint 前确认其未通过门禁且无人引用;大目录删除注意 IO。

故障排查 ​

  • 分数不可比:确认 harness 版本、few-shot、dtype、batch 一致;vLLM 与 HF 后端偶有差异,用 model_comparator.py 校验。
  • MMLU 虚高:疑似训练数据污染评测集,用私有 golden set 复核,并对语料重新去污染。
  • MT-Bench 判分不稳:judge 模型版本固定;对边界样本人工抽检。
  • 自建 eval 全过但线上差:评测集与线上分布不匹配,扩充边界/失败样本。

安全与合规 ​

评测中的安全与数据边界

  • 评测数据污染:公开基准可能已泄入训练数据导致虚高;必须用私有 golden set 兜底,并去污染。
  • 评测集 PII:自建 golden set 若含真实用户数据,需脱敏与访问控制,等同训练数据要求。
  • judge 调用合规:MT-Bench 调外部 judge API 会把题目发出去,确认不含机密;或改用本地 judge 模型。
  • 越权:评测平台若多租户,checkpoint 与评测结果需按租户隔离,避免跨团队可读。

成本与性能(估算,[未实测]) ​

评测项规模成本
MMLU(全 57 科)单卡跑7B,bf16约数十分钟~1h GPU
MT-Bench80 题 + judge APIAPI 调用费为主,几美元内
自建 golden set依规模计算可忽略

成本备注

三层评测合计通常 < 30 分钟 GPU + 少量 judge API 费,相比一次微调(数小时~数天)成本极低,却能在上线前拦住绝大多数回归。评测应作为 CI 门禁常态化,而非上线后补救。GPU 利用率与 judge 延迟是主要耗时点。[时长为估算,非实测]

参考资料 ​

基于 VitePress 构建 · 托管于阿里云 ECS