如何在nltk计算BLEU Score时忽略brevity penalty?
计算不含长度惩罚(Brevity Penalty)的BLEU分数
核心实现方法
NLTK的sentence_bleu接口本身支持手动指定长度惩罚值,要完全忽略brevity penalty的影响,只需要在调用函数时传入brevity_penalty=1.0参数即可。因为长度惩罚在BLEU公式中是作为乘子存在的,当乘子为1时,不会对最终的n-gram几何平均分数产生任何缩放效果,等价于完全移除了长度惩罚的计算逻辑。
修改后的可运行代码示例:
import nltk from nltk.translate.bleu_score import sentence_bleu # 注意参数格式要求: # 参考文本需要是「分词后token列表组成的嵌套列表」,比如单条参考的格式为 [['我', '爱', '北京', '天安门']] # 候选文本是分词后的一维token列表,比如 ['我', '爱', '北京', '广场'] # 传入brevity_penalty=1.0关闭长度惩罚 score1 = sentence_bleu(ref1, cand, brevity_penalty=1.0)
底层逻辑说明
- 默认的BLEU计算公式拆分为两部分:
最终分数 = 各阶n-gram精度的几何平均值 × 长度惩罚系数 - 不手动指定惩罚值时,函数会自动计算惩罚系数:如果候选文本长度大于等于参考文本长度,惩罚系数为1;如果候选文本短于参考文本,惩罚系数为
math.exp(1 - 参考文本长度 / 候选文本长度),该值小于1,会拉低最终得分。 - 手动传入
brevity_penalty=1.0后,函数会跳过自动计算惩罚系数的流程,直接使用1作为乘子,最终得到的分数就是纯由n-gram精度计算出的结果,完全不受文本长度差的影响。
低版本NLTK兼容方案
如果使用的NLTK版本较早,未开放brevity_penalty参数的入参支持,可以手动拆分计算流程,跳过长度惩罚的计算步骤:
from nltk.translate.bleu_score import modified_precision import math def calculate_bleu_without_bp(refs, cand, weights=(0.25, 0.25, 0.25, 0.25)): # 逐阶计算n-gram修改精度 precision_list = [modified_precision(refs, cand, n) for n in range(1, len(weights)+1)] # 直接计算几何平均,跳过长度惩罚环节 log_score = math.fsum(weight * math.log(prec) for weight, prec in zip(weights, precision_list)) return math.exp(log_score) # 调用方式与原接口一致 score1 = calculate_bleu_without_bp(ref1, cand)
内容的提问来源于stack exchange,提问作者NobinPegasus
相关产品推荐
相关产品推荐

