Chapter 10:评测协议、复现与报告(让结果可对比)
“如果不控制变量,你测量的不是模型的智能,而是随机噪声的振幅。” 在 VLM 领域,评测协议(Evaluation Protocol)的微小差异——比如是先Resize还是先Pad,是生成 "A" 还是计算 "A" 的概率——可能导致 leaderboard 上 5-10 个点的排位变化。本章将构建一套严谨的“实验法医学”框架,确保你的分数经得起推敲。
1. 开篇:评测的“蝴蝶效应”
在开始跑分之前,必须建立一个共识:Benchmark 分数是一个函数 。
- : 模型权重 (Model)
- : 提示词与预处理 (Prompt & Preprocessing)
- : 数据集版本 (Dataset)
- : 评分逻辑 (Scorer)
大多数人只关注 ,却忽略了 和 的巨大影响。本章的目标是标准化 和 ,使得 成为唯一的变量。
本章学习目标:
- 输入标准化:掌握动态分辨率、长宽比保留与 Tokenizer 的对齐机制。
- 推理确定性:理解 Greedy Search 与 PPL (Perplexity) 评测法的本质区别。
- 评分裁判学:深入 LLM-as-a-Judge 的偏见修正(位置偏见、长度偏见)。
- 报告规范:学会撰写“防弹”的实验报告,披露关键元数据。
2. 视觉输入的标准化协议
视觉编码器(Vision Encoder)对输入图像极其敏感。不同的预处理方式是“分数复现失败”的头号杀手。
2.1 分辨率策略:Crop vs. Pad vs. Dynamic
你必须在报告中明确指出使用了哪种策略:
- Center Crop (中心裁剪):
- 做法:将图片短边缩放到 224/336,然后切出中间的正方形。
- 后果:极度危险。对于自然图像(ImageNet)有效,但对于 OCR、图表、文档任务,会直接切掉边缘的文字或坐标轴,导致“瞎猜”。
-
适用:仅限老旧的分类任务;现代 VLM 评测严禁使用。
-
Letterbox Padding (黑边/白边填充):
- 做法:保持原始长宽比缩放,不足部分填色(通常是
[122, 122, 122]或黑色)。 - 后果:保留了完整语义,但引入了无意义的背景 Token,可能干扰注意力机制。
-
Rule of Thumb:这是目前最稳健的默认选择。
-
AnyRes / Dynamic Resolution (动态分辨率):
- 做法:类似 LLaVA-NeXT 或 Monkey,将大图切成多个 patch(如 网格),加上一张缩略图。
- 后果:计算量成倍增加,但细节感知力极强。
- 协议要求:必须报告“最大切片数 (Max Crops)”。
ASCII 图解:预处理差异
原始图片 (宽图): [ 文字.......文字 ]
1. Center Crop: [...文字...] <-- 丢失两端信息 (致命错误)
2. Resize 暴力: [文字.......文字] <-- 物体被压扁 (OCR 识别率下降)
3. Letterbox: [ 文字.......文字 ]
[ 黑 边 ] <-- 几何形状正确 (推荐)
3. 推理(Inference)协议的深水区
3.1 Prompt 模板的严格对齐
不要以为把问题塞进去就行了。模型训练时使用了特定的特殊符(Special Tokens),评测必须像素级对齐。
- Base Model (基座模型):通常不支持对话模式。
- 错误做法:
User: <image> Describe this. -
正确做法:Text Completion 模式,例如
<image> A picture of(让模型续写)。 -
Instruct Model (指令微调模型):
- Chat Template:必须复用训练时的模板(LLaMA-2, Vicuna, ChatML 等)。
- System Prompt:如果在训练时加了
"You are a helpful assistant.",评测时尽量加上,否则模型分布会偏移。
3.2 生成式 (Generative) vs. 概率式 (PPL)
对于选择题(如 MMBench, MMMU),有两种截然不同的解题流派,分数不可直接对比:
流派 A:生成式 (Generative / CoT)
- 操作:输入问题,让模型生成文本。
- 提取:用正则从文本中找 "A" 或 "B"。
- 优点:支持思维链(CoT),推理能力强。
- 缺点:模型可能罗嗦半天不说选项,或者输出 "Option 1" 导致解析失败。
流派 B:概率式 (PPL-based / Logits)
- 操作:不让模型生成。计算模型给定
Question后,接续Choice A、Choice B、Choice C的全句概率(Loss)。 - 判定:谁的 Loss 最小(概率最大),就选谁。
- 优点:无解析误差,纯粹考察模型对答案的置信度。
- 缺点:不支持 CoT,无法利用推理步骤。
- 协议建议:对于 Base Model 用 PPL;对于 Chat Model 用 Generative。
4. 评分器(Scorer):从正则到大模型裁判
4.1 规则匹配的“肮脏工作”
在 VQAv2 或 OCRBench 中,简单的字符串匹配是不够的。你需要一套文本归一化(Normalization)流水线:
- 小写化:
"Cat"->"cat" - 去标点:
"It's 5.0."->"its 50"(注意小数点陷阱) - 数字转换:
"five"->"5" - 冠词移除:
"The dog"->"dog"
常见陷阱:在 MathVista 中,如果答案是
1,000,你的正则只匹配数字,可能会提取成1和000两个数,导致错误。必须处理千分位分隔符。
4.2 LLM-as-a-Judge 的偏见校准
当使用 GPT-4 或 Claude-3 作为裁判(如评测 LLaVA-Bench 或 MVBench)时,必须警惕以下偏见:
- 位置偏见 (Position Bias):如果是二选一对比,裁判倾向于认为第一个出现的答案更好。
-
解决方案:交换测试 (Pairwise Permutation)。跑两遍:(A vs B) 和 (B vs A)。只有当裁判两次都判同一个赢,才算赢;一胜一负算平局。
-
自我偏好 (Self-Preference):GPT-4 往往觉得 GPT-4V 的输出风格最好。
-
解决方案:在论文中披露使用的裁判模型版本。
-
长度偏见 (Verbosity Bias):废话越多的回答,裁判往往给分越高。
- 解决方案:在 Judge Prompt 中明确惩罚冗余信息,或者要求“简洁准确”。
5. 本章小结:协议清单 (The Checklist)
在跑任何基准之前,请核对以下清单:
- 温度 (Temperature):必须为 0(除非评测多样性)。
- 随机种子 (Seed):固定 PyTorch, NumPy, Python 随机种子(虽然 GPU 上仍可能有微小扰动)。
- 图像处理:确认是 Pad 还是 Crop;确认归一化参数(mean/std)是否匹配训练代码。
- Prompt:确认是否应用了正确的 Chat Template。
- 停止符 (Stop Tokens):确认配置了正确的 EOS token,防止无限生成。
- 解析器:对于 MCQ,确认是提取 "A" 还是 "Option A";对于填空,确认数字格式。
6. 练习题
基础题(巩固概念)
习题 1:为什么是 "Temperature = 0"?
问题:许多研究员在复现 Benchmark 时,将 Temperature 设为 0。但在 HuggingFace 默认配置中,top-p 往往是 0.9。
- 将 Temperature 设为 0 在数学上等同于什么解码策略?
- 为什么 Benchmark 评测不喜欢
do_sample=True?
提示:思考“科学实验”的基本要求——可重复性。
查看答案
- 等同于 Greedy Search (贪婪搜索)。即每一步都选择概率最大的那个 Token,没有任何随机性。
- 原因: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),打乱后它还会选同一个内容对应的选项吗?
查看答案
答案:
- 解决的问题:位置偏见 (Position Bias) 和 选项偏好。有些模型无论题目是什么,都倾向于选第一个选项(A),或者因为训练数据中 "C" 较多而瞎猜 C。
- 惩罚机制: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 而报错或性能下降。 防御:
- Regex:使用
r"^\s*([A-D])",显式允许前面有 0 个或多个空白字符。 - 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)。 鲁棒逻辑:
- Last-Match Principle:总是扫描整个字符串,取最后一次出现的匹配项。
- Negative Lookahead:排除掉诸如 "not A", "incorrectly chose B" 等否定句式(这很难,通常用规则 1 就够了)。
- 专用提取模型:最稳妥的方式是将整段话喂给一个极小的 LLM(如 GPT-3.5-Turbo),Prompt 为:“Identify the final choice decided by the user in this text.”
7. 常见陷阱与错误 (Gotchas)
1. 显存溢出与 batch_size=1 的诅咒
- 现象:为了加速评测,你开启了
batch_size > 1。结果发现,位于 Batch 后面的样本分数显著低于单独跑的分数。 - 原因:Padding Side Effect。VLM 的视觉编码器通常不支持 Masking,或者 LLM 部分对左侧 Padding (Left Padding) 处理不当,导致 Padding Token 干扰了注意力计算。
- 调试:在 VLM 评测中,默认推荐 Batch Size = 1。虽然慢,但最安全。如果必须 Batch,请务必验证 Padding Side(通常应该是 Left Padding for generation)。
2. 半精度 (FP16) 的数值溢出
- 现象:模型输出全是乱码或
NaN,或者在某些特定图片上概率为 0。 - 原因:原始的 float16 范围很小。某些 VLM(特别是 CogVLM 或部分 LLaVA 变体)在中间层激活值很大,导致溢出。
- 对策:永远优先使用 BF16 (BFloat16),如果硬件(如 V100)不支持,必须小心 scaling 或回退到 FP32。
3. "Image Token" 的数量硬编码
- 现象:你换了一张分辨率不同的图,代码报错
Shape mismatch。 - 原因:有些代码硬编码了
<image>对应的 token 数量(比如 256 个或 576 个)。 - 对策:不要手动插入
<image>占位符的重复次数,应使用模型自带的tokenizer.image_token_len属性或处理函数来自动填充。
4. 忽视了 System Prompt 的污染
- 现象:评测数学题,模型却一直试图“像海盗一样说话”或者过于简略。
- 原因:加载模型时默认带入了该库全局配置的 System Prompt(可能是为了 Demo 设置的趣味 Prompt)。
- 对策:评测时显式将 System Prompt 设为空字符串
""或标准的"You are a helpful assistant."。