

























本文讲解 BLEU 的算法思想、计算公式、常见误区,以及为什么「翻译对了,分数却不高」。
在 QA 任务里,标准答案往往唯一且很短,用 Exact Match(EM) 就够了:归一化后完全一致即判对。
翻译任务不同。同一句英文可以有多条合法中文译文:
| 参考译文 | 模型译文 | 语义 |
|---|---|---|
| 早上好 | 早上好呀 | ✅ 正确 |
| 谢谢 | 多谢 | ✅ 正确 |
| 回头见 | 再见 | ✅ 基本正确 |
EM 会把后两种情况全部判错。我们需要一种指标:不要求逐字相同,但越接近参考译文,分数越高。
BLEU(Bilingual Evaluation Understudy,2002 年 Papineni 等人提出)就是机器翻译领域最经典的自动评测指标之一。核心思路很简单:
看模型译文里,有多少 n-gram(连续的 n 个词/字)也出现在参考译文里。
BLEU 由三部分组成:
BLEU = BP × exp( Σ wₙ × log(pₙ) )
其中:
| 符号 | 含义 |
|---|---|
| pₙ | n-gram 修正精确率(modified precision) |
| wₙ | 各阶 n-gram 的权重,默认 1~4 gram 各 0.25 |
| BP | 简短惩罚(Brevity Penalty),防止模型「说太短」刷分 |
下面分开讲。
把句子切成连续片段:
句子: "I love you"
1-gram: I | love | you
2-gram: I love | love you
3-gram: I love you
中文没有空格时,可以按字切(本仓库 metrics_lib.py 就是这样做的):
句子: "我爱你"
1-gram: 我 | 爱 | 你
2-gram: 我爱 | 爱你
3-gram: 我爱你
普通精确率:候选译文里某个 n-gram 出现几次,就算几次命中。
修正版:每个 n-gram 的命中次数 不能超过 它在参考译文里出现的次数。
例子
the the the the thethe the the the普通算法:候选里 4 个 the 都算命中 → 精确率 100%(不合理)
修正算法:参考里 the 最多计 5 次,候选 4 个 the 全部有效 → 4/4
若候选是 the the the the the the(6 个 the),只有 5 个能计分 → 5/6
这样可以防止模型通过重复高频词「刷分」。
BLEU 默认同时看 1-gram、2-gram、3-gram、4-gram,各权重 0.25,再取几何平均:
BLEU_core = (p₁ × p₂ × p₃ × p₄) ^ 0.25
直觉:
若候选译文 比参考译文短很多,即使每个词都「命中」,也可能是漏译。BLEU 用 BP 惩罚过短输出:
若 len(候选) >= len(参考):
BP = 1
否则:
BP = exp(1 - len(参考) / len(候选))
候选越短,BP 越接近 0,总分被压低。
参考译文:cat sat on mat(4 词)
候选译文:cat cat on mat(4 词)
| 阶 | 候选 n-gram 总数 | 命中数(修正后) | pₙ |
|---|---|---|---|
| 1 | 4 | 4(cat 计 1 次) | 4/4 = 1.0 |
| 2 | 3 | 2(on mat 命中,cat cat 无效重复) |
2/3 ≈ 0.67 |
| 3 | 2 | 1(cat on mat 不连续匹配) |
1/2 = 0.5 |
| 4 | 1 | 0 | 0/1 = 0 |
4-gram 为 0 时,若无平滑,几何平均直接为 0。NLTK 默认加 平滑(smoothing),避免短句一律得 0 分——但短句分数仍往往偏低。
# src/L3_EvalHarness/common/metrics_lib.py
def compute_bleu(candidate: str, reference: str) -> float:
from nltk.translate.bleu_score import SmoothingFunction, sentence_bleu
ref = [list(reference)] # 参考:按字符列表
hyp = list(candidate) # 候选:按字符列表
return float(
sentence_bleu(ref, hyp, smoothing_function=SmoothingFunction().method1)
)
要点:
sentence_bleu,默认 1~4 gram、等权重SmoothingFunction().method1 缓解短句 4-gram 为 0 的问题相关 demo:
这是初学者最容易困惑的地方,并不代表「翻译只有 38 分质量」。
mini_translate.jsonl 里大多是 2~3 个汉字:
| 参考 | 模型(完全正确) | EM | BLEU(实测) |
|---|---|---|---|
| 我爱你 | 我爱你 | 1 | ~0.56 |
| 谢谢 | 谢谢 | 1 | ~0.32 |
即使 一字不差,3 字句也凑不满 4-gram,几何平均后分数很难接近 1.0。这是算法特性,不是模型差。
def exact_match(pred, expected):
return normalize(pred) == normalize(expected) # 去标点、统一大小写等
| 参考 | 模型 | EM | BLEU |
|---|---|---|---|
| 你好吗 | 你好吗? | ✅ 对 | ~0.40(多了一个字) |
EM 去掉标点后算对;BLEU 逐字比较,标点也算差异。
demo42 某次运行:
| 题 | expected | Prompt A | EM | BLEU |
|---|---|---|---|---|
| t5 | 回头见 | 再见 | ❌ | ~0.09 |
| t5 | 回头见 | (一大段 Markdown 解释) | ❌ | ~0.007 |
语义接近的「再见」EM 错、BLEU 低;冗长解释几乎不得分。
结论:在本 demo 的设定下,EM 更适合当硬指标选 winner;BLEU 适合看「和参考的重叠程度」,但 短中文句上的绝对值不能和论文里英译法的长句 BLEU 直接比。
flowchart LR subgraph 任务 QA[短答案 QA] TR[翻译 / 摘要] end subgraph 指标 EM[Exact Match] BLEU[BLEU] ROUGE[ROUGE-L] end QA --> EM TR --> BLEU TR --> ROUGE
| 指标 | 比较方式 | 优点 | 缺点 |
|---|---|---|---|
| EM | 归一化后完全一致 | 简单、可解释 | 翻译同义改写全错 |
| BLEU | n-gram 重叠 + 短句惩罚 | 业界标准、可部分给分 | 短句偏低、单参考、不看语义 |
| ROUGE-L | 最长公共子序列 F1 | 对语序/片段匹配更稳 | 仍不理解语义 |
本仓库 compute_rouge_l 对中文按字算 LCS,避免英文分词工具把整句当一个词导致 ROUGE=0。
更进一步的方案:多参考译文 BLEU、COMET/BERTScore 等语义指标、LLM-as-Judge——适合产品级评测,超出 mini harness 范围。
BLEU = 你的译文和参考译文在 1~4 gram 上重叠多少,再惩罚说得太短;分数越高越像参考,但不等于语义一定对。
在 L3 Harness 里:
sentence_bleu 文档此内容由惯性聚合(RSS阅读器)自动聚合整理,仅供阅读参考。 原文来自 — 版权归原作者所有。