4. 基于BLEU的机器翻译评测
任务说明
本案例实现BLEU(Bilingual Evaluation Understudy)指标计算,并基于HuggingFace Transformers评测一个英译中模型在测试集上的翻译质量。BLEU通过比较模型译文与参考译文在n-gram层面的重合度来评估翻译质量,取值范围为0~1,越高代表译文与参考越接近。
环境依赖
pip install transformers sacrebleu datasets torch
完整实现
import torch
from transformers import AutoTokenizer, AutoModelForSeq2SeqLM
from datasets import load_dataset
import sacrebleu
# 1. 加载英译中模型与分词器
model_name = "Helsinki-NLP/opus-mt-en-zh"
tokenizer = AutoTokenizer.from_pretrained(model_name)
model = AutoModelForSeq2SeqLM.from_pretrained(model_name)
device = torch.device("cuda" if torch.cuda.is_available() else "cpu")
model.to(device)
# 2. 加载测试数据(WMT19中英测试集前20条,含英文原文与中文参考译文)
ds = load_dataset("wmt19", "zh-en", split="test[:20]")
# 注意:wmt19的zh-en方向,source为中文,target为英文,需反向使用
# 此处取英文为源语言,中文为参考译文
src_texts = [item["translation"]["en"] for item in ds]
ref_texts = [[item["translation"]["zh"]] for item in ds] # sacrebleu要求参考为列表的列表
# 3. 批量生成译文
def translate(texts, batch_size=8):
outputs = []
for i in range(0, len(texts), batch_size):
batch = texts[i:i+batch_size]
encoded = tokenizer(batch, return_tensors="pt", padding=True, truncation=True, max_length=128).to(device)
with torch.no_grad():
generated = model.generate(**encoded, max_new_tokens=128)
batch_out = tokenizer.batch_decode(generated, skip_special_tokens=True)
outputs.extend(batch_out)
return outputs
hyp_texts = translate(src_texts)
# 4. 计算BLEU
bleu = sacrebleu.corpus_bleu(hyp_texts, ref_texts)
print(f"BLEU score: {bleu.score:.2f}")
print(f"BLEU details: {bleu.precisions}")
# 5. 打印前3条对比示例
for i in range(3):
print(f"\n源文: {src_texts[i]}")
print(f"译文: {hyp_texts[i]}")
print(f"参考: {ref_texts[i][0]}")
运行方式
python bleu_eval.py
验证方法与判定标准
运行脚本后,观察输出:
- 程序正常结束且无报错,打印出BLEU分数(预期在10~30之间,具体取决于测试子集与模型能力);
- 打印的译文为中文且语义与源文相关,参考译文为人工标注的中文翻译;
- BLEU分数越高说明模型翻译质量越好,若分数为0则说明n-gram完全无重合,需检查数据方向或生成逻辑。
注意:由于模型下载与推理耗时,首次运行需联网下载模型权重(约300MB)。测试集仅取前20条以控制运行时间,完整评测可去掉切片。
常见问题
- 数据方向问题:wmt19的zh-en方向源语言为中文,本案例需英文作为输入,因此直接取translation字段中的en作为源文、zh作为参考,代码已做对应处理。
- 显存不足:若GPU显存不足,可将batch_size调小至2或4,或改用CPU推理(速度较慢)。
- BLEU为0:检查生成译文是否为空或全为特殊符号,可打印hyp_texts前几条确认。