vl_benchmark_tutorial

Chapter 10:评测协议、复现与报告(让结果可对比)

“如果不控制变量,你测量的不是模型的智能,而是随机噪声的振幅。” 在 VLM 领域,评测协议(Evaluation Protocol)的微小差异——比如是先Resize还是先Pad,是生成 “A” 还是计算 “A” 的概率——可能导致 leaderboard 上 5-10 个点的排位变化。本章将构建一套严谨的“实验法医学”框架,确保你的分数经得起推敲。

1. 开篇:评测的“蝴蝶效应”

在开始跑分之前,必须建立一个共识:**Benchmark 分数是一个函数 **。

大多数人只关注 ,却忽略了 和 的巨大影响。本章的目标是标准化 和 ,使得 成为唯一的变量。

本章学习目标

  1. 输入标准化:掌握动态分辨率、长宽比保留与 Tokenizer 的对齐机制。
  2. 推理确定性:理解 Greedy Search 与 PPL (Perplexity) 评测法的本质区别。
  3. 评分裁判学:深入 LLM-as-a-Judge 的偏见修正(位置偏见、长度偏见)。
  4. 报告规范:学会撰写“防弹”的实验报告,披露关键元数据。

2. 视觉输入的标准化协议

视觉编码器(Vision Encoder)对输入图像极其敏感。不同的预处理方式是“分数复现失败”的头号杀手。

2.1 分辨率策略:Crop vs. Pad vs. Dynamic

你必须在报告中明确指出使用了哪种策略:

ASCII 图解:预处理差异

原始图片 (宽图): [ 文字.......文字 ]

1. Center Crop:   [...文字...]      <-- 丢失两端信息 (致命错误)
2. Resize 暴力:   [文字.......文字]  <-- 物体被压扁 (OCR 识别率下降)
3. Letterbox:     [ 文字.......文字 ]
                  [     黑  边      ]  <-- 几何形状正确 (推荐)


3. 推理(Inference)协议的深水区

3.1 Prompt 模板的严格对齐

不要以为把问题塞进去就行了。模型训练时使用了特定的特殊符(Special Tokens),评测必须像素级对齐

3.2 生成式 (Generative) vs. 概率式 (PPL)

对于选择题(如 MMBench, MMMU),有两种截然不同的解题流派,分数不可直接对比:

流派 A:生成式 (Generative / CoT)

流派 B:概率式 (PPL-based / Logits)


4. 评分器(Scorer):从正则到大模型裁判

4.1 规则匹配的“肮脏工作”

在 VQAv2 或 OCRBench 中,简单的字符串匹配是不够的。你需要一套文本归一化(Normalization)流水线:

  1. 小写化"Cat" -> "cat"
  2. 去标点"It's 5.0." -> "its 50" (注意小数点陷阱)
  3. 数字转换"five" -> "5"
  4. 冠词移除"The dog" -> "dog"

常见陷阱:在 MathVista 中,如果答案是 1,000,你的正则只匹配数字,可能会提取成 1000 两个数,导致错误。必须处理千分位分隔符。

4.2 LLM-as-a-Judge 的偏见校准

当使用 GPT-4 或 Claude-3 作为裁判(如评测 LLaVA-Bench 或 MVBench)时,必须警惕以下偏见:


5. 本章小结:协议清单 (The Checklist)

在跑任何基准之前,请核对以下清单:

  1. 温度 (Temperature)必须为 0(除非评测多样性)。
  2. 随机种子 (Seed):固定 PyTorch, NumPy, Python 随机种子(虽然 GPU 上仍可能有微小扰动)。
  3. 图像处理:确认是 Pad 还是 Crop;确认归一化参数(mean/std)是否匹配训练代码。
  4. Prompt:确认是否应用了正确的 Chat Template。
  5. 停止符 (Stop Tokens):确认配置了正确的 EOS token,防止无限生成。
  6. 解析器:对于 MCQ,确认是提取 “A” 还是 “Option A”;对于填空,确认数字格式。

6. 练习题

基础题(巩固概念)

习题 1:为什么是 "Temperature = 0"? **问题**:许多研究员在复现 Benchmark 时,将 Temperature 设为 0。但在 HuggingFace 默认配置中,top-p 往往是 0.9。 1. 将 Temperature 设为 0 在数学上等同于什么解码策略? 2. 为什么 Benchmark 评测不喜欢 `do_sample=True`? **提示**:思考“科学实验”的基本要求——可重复性。
查看答案 1. **等同于 Greedy Search (贪婪搜索)**。即每一步都选择概率最大的那个 Token,没有任何随机性。 2. **原因**:Benchmark 的核心目的是对比模型能力,而不是运气。`do_sample=True` 会引入随机性,导致同一个模型跑两次分数不同(Variance),这会掩盖模型间的真实细微差距,且让 Debug 变得不可能。
习题 2:PPL vs Gen 模式选择 **问题**:你正在评测一个刚刚 Pre-training 完成、尚未进行 Instruction Tuning 的 Base VLM。你想测它在 MMBench(选择题)上的能力。 你应该使用 **Generative (生成式)** 还是 **PPL (概率式)** 方法?为什么? **提示**:Base 模型听得懂“请回答下列问题”这种指令吗?
查看答案 **答案:PPL (概率式)**。 **解析**:Base 模型只学会了预测下一个词,尚未学会遵循“指令”(Instruction Following)。如果你用 Prompt 问它“Answer the question with option letter”,它可能会续写一堆无关文本而不是输出 "A"。计算选项的 PPL 是最直接衡量其知识储备的方法,不受指令遵循能力的干扰。
习题 3:Center Crop 的受害者 **问题**:以下哪个 Benchmark 最容易受到图像预处理中 "Center Crop" (中心裁剪) 的负面影响? A. ImageNet (自然物体分类) B. DocVQA (文档问答) C. RefCOCO (中心目标指代) **提示**:文档的关键信息通常分布在哪里?
查看答案 **答案:B. DocVQA**。 **解析**:文档(如发票、表格)的页眉、页脚、边缘通常包含关键信息(如日期、页码、落款)。Center Crop 会直接切掉这些信息,导致模型物理上“看不见”答案。ImageNet 的物体通常在中心;RefCOCO 即使目标在边缘,至少不会全是文字。

挑战题(进阶实战)

习题 4:循环评测 (Circular Evaluation) 原理 **问题**:MMBench 提出了一种 "Circular Evaluation" 策略。对于一道题,它不仅仅问一次,而是将选项 A, B, C, D 轮转打乱顺序(例如变成 B, C, D, A),问模型多次。 这样做试图解决什么问题?如果一个模型在乱序后的回答不一致,MMBench 是如何惩罚的? **提示**:如果模型只是单纯喜欢选 "A"(Bias),打乱后它还会选同一个**内容**对应的选项吗?
查看答案 **答案**: 1. **解决的问题**:**位置偏见 (Position Bias)** 和 **选项偏好**。有些模型无论题目是什么,都倾向于选第一个选项(A),或者因为训练数据中 "C" 较多而瞎猜 C。 2. **惩罚机制**:MMBench 要求模型在所有轮转(Shift)中,必须都指向同一个**内容**(例如第一次选 A,第二次 A 变成了 D,模型得选 D)。如果模型在任何一次轮转中失败,该题得分为 0(Fail-at-first)。这极大增加了通过难度,但更能反映鲁棒性。
习题 5:Tokenization 导致的“空格陷阱” **问题**:在使用生成式评测提取答案时,你发现模型输出了 `"A"`(注意前面没空格),而 Ground Truth 期望匹配的是 `" A"`(带前导空格)。在 LLaMA tokenizer 中,`"A"` 和 `" A"` 是完全不同的两个 Token ID。 这会导致什么后果?在编写 Regex 时应如何防御? **提示**:Tokenizer 对句子开头的词和中间的词处理不同。
查看答案 **后果**:直接导致 String Match 失败,或者如果是 Constrained Decoding(限制输出 Token),模型可能因为想输出带空格的 A 却被限制只能输出不带空格的 A 而报错或性能下降。 **防御**: 1. **Regex**:使用 `r"^\s*([A-D])"`,显式允许前面有 0 个或多个空白字符。 2. **Normalization**:在比较前,对 `pred` 和 `gt` 都执行 `.strip()` 操作。
习题 6:CoT 的解析噩梦 **问题**:在评测 MathVista 时,你开启了 CoT(思维链)。模型输出: `"Calculating... x = 5. Therefore, option B is correct because 5 is larger than 3. Wait, I made a mistake, 5 is actually smaller than 6. So the answer is A."` 如果你使用简单的关键词搜索 `r"answer is ([A-D])"`,你会提取到 "B" 还是 "A"?如何设计更鲁棒的逻辑? **提示**:模型具有“自我修正”行为时,真理通常在最后。
查看答案 **分析**:简单的正则可能会匹配到第一个 "answer is" 附近的 B(或者是隐含的 B)。 **鲁棒逻辑**: 1. **Last-Match Principle**:总是扫描整个字符串,取**最后一次**出现的匹配项。 2. **Negative Lookahead**:排除掉诸如 "not A", "incorrectly chose B" 等否定句式(这很难,通常用规则 1 就够了)。 3. **专用提取模型**:最稳妥的方式是将整段话喂给一个极小的 LLM(如 GPT-3.5-Turbo),Prompt 为:“Identify the final choice decided by the user in this text.”

7. 常见陷阱与错误 (Gotchas)

1. 显存溢出与 batch_size=1 的诅咒

2. 半精度 (FP16) 的数值溢出

3. “Image Token” 的数量硬编码

4. 忽视了 System Prompt 的污染