You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

使用NLTK sentence_bleu计算中文句子BLEU值返回0的解决办法

解决NLTK sentence_bleu评估中文BLEU分数为0的问题

问题现象

使用NLTK的sentence_bleu()计算中文句子的BLEU分数时,结果始终为0,即使添加平滑方法也无效。但使用SacreBLEU的corpus_score()能得到正常结果(BLEU=4.79)。

错误原因

  1. 参数格式不符合NLTK要求
    NLTK的sentence_bleu对输入格式有严格要求:

    • references:必须是参考译文的列表,每个参考是分词后的token列表(支持多参考,格式为[[ref1_tokens], [ref2_tokens], ...])
    • hypothesis:必须是单个假设译文的token列表,而非字符串列表
      你当前传入的是模型生成后的字符串和字符串列表,完全不符合格式要求。
  2. 错误的参考分词方式
    你用model.generate()处理参考句子来获取分词结果,这是完全错误的——generate是文本生成接口,不是分词工具,导致参考文本被错误处理(从SacreBLEU输出的ref_len=1可看出,参考被处理成了长度为1的无效token序列)。

  3. 未正确处理中文分词
    中文句子必须先分词为token序列才能计算BLEU,直接使用整句字符串会导致计算逻辑完全错误。

解决方案

修正步骤

  1. 使用正确的分词工具(模型自带的tokenizer或jieba)对参考和假设句子进行分词,得到token列表。
  2. 按照NLTK要求的格式传入参数。
  3. 配合平滑函数解决短句子或低匹配度导致的0分问题。

修正后的完整代码

import nltk
from nltk.translate.bleu_score import SmoothingFunction
from transformers import BertTokenizer, BartForConditionalGeneration
from sacrebleu.metrics import BLEU

src = '樓上漏水耍花招不處理可以怎麼做'
ref = '上層漏水耍手段不去處理可以怎麼做'

checkpoint = 'fnlp/bart-base-chinese'
tokenizer = BertTokenizer.from_pretrained(checkpoint)
model = BartForConditionalGeneration.from_pretrained(checkpoint)

# 生成假设译文
hypothesis_str = ""
inputs = tokenizer(src, return_tensors="pt", truncation=True, max_length=100, return_token_type_ids=False)
outputs = model.generate(**inputs)
hypothesis_str = tokenizer.decode(outputs[0], skip_special_tokens=True)

# 正确分词:使用模型tokenizer保证分词一致性
# 参考译文格式:[[ref_tokens]](支持多参考,单参考时外层套列表)
ref_tokens = tokenizer.tokenize(ref)
references = [ref_tokens]

# 假设译文格式:单个token列表
hypothesis_tokens = tokenizer.tokenize(hypothesis_str)

# 带平滑计算BLEU
smooth_fn = SmoothingFunction()
nltk_bleu = nltk.translate.bleu_score.sentence_bleu(
    references,
    hypothesis_tokens,
    smoothing_function=smooth_fn.method3
)
print(f"NLTK BLEU分数: {nltk_bleu * 100:.2f}")

# 对比SacreBLEU结果
bleu = BLEU()
bleu_score = bleu.corpus_score(references=[[ref]], hypotheses=[hypothesis_str])
print(bleu_score)

代码说明

  • 用模型的tokenizer.tokenize()分词,保证和生成文本的分词逻辑一致;也可以替换为jieba分词,但需注意分词一致性。
  • 参考译文传入格式为[[ref_tokens]],满足NLTK多参考的参数要求。
  • 假设译文传入单个token列表,而非字符串列表。
  • 使用平滑方法3解决低匹配度场景下的0分问题,避免因某阶n-gram完全不匹配导致整体分数为0。

验证结果

运行修正后的代码,NLTK会输出接近SacreBLEU的分数(两者计算细节略有差异,但不会再出现0分)。

内容的提问来源于stack exchange,提问作者Raptor

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.11 10:07:51