BLEU源码笔记
本文参考代码为coco-caption
回顾
详细解释参见我的这篇博客,本文仅仅是代码解释
BLEU是2002年提出的一个机器翻译的自动度量,它从n-gram准确率的角度对比机器翻译和人工翻译的结果,计算公式为
B
L
E
U
=
B
P
exp
(
∑
n
=
1
N
w
n
log
p
n
)
BLEU = BP\exp\big(\sum_{n=1}^Nw_n\log p_n\big)
BLEU=BPexp(n=1∑Nwnlogpn)
其中
B
P
=
{
1
if c>r
e
(
1
−
r
/
c
)
else
BP= \begin{cases} 1& \text{if c>r}\\ e^{(1-r/c)}& \text{else} \end{cases}
BP={1e(1−r/c)if c>relse
比如当我计算下例的bleu值时
candidate = "It is a guide to action which ensures that the military always obeys the commands of the party."
reference1 = "It is a guide to action that ensures that the military will forever heed Party commands."
reference2 = "It is the guiding principle which guarantees the military forces always being under the command of the Party."
reference3 = "It is the practical guide for the army always to heed the directions of the party."
得到的结果即为(对原句进行大小写和标点的处理)
BLEU1:0.9444444444444444,
BLEU2:0.7453559924999299,
BLEU3:0.6240726989348756,
BLEU4:0.5045666840058485
需要注意的是,这里的BLEUi是上面公式中 N = i N=i N=i的结果,而非仅仅是 p i p_i pi(我一开始这么以为是因为发现BLEU1= p 1 p1 p1,但BLEU2不等于 p 2 p_2 p2,以为官方代码出错了,结果和自己写的代码怎么比都不对,后来才发现这只是N=1的特殊情况)
在coco-caption中的对应代码为
bleus = []
bleu = 1.
for k in range(n):
bleu *= float(comps['correct'][k] + tiny) \
/ (comps['guess'][k] + small)
bleus.append(bleu ** (1./(k+1)))
ratio = (self._testlen + tiny) / (self._reflen + small) ## N.B.: avoid zero division
if ratio < 1:
for k in range(n):
bleus[k] *= math.exp(1 - 1/ratio)
其中tiny
、small
均为防止分子分母为0而添加的微小值,comps['correct'][k]
就是正确的k-gram(clip之后)数量,comps['guess'][k]
就是candidate
中k-gram的数量,ratio
就是公式中的BP
这里实际上对计算公式做了些变形
B
L
E
U
=
B
P
exp
(
∑
n
=
1
N
w
n
log
p
n
)
=
B
P
∏
n
=
1
N
e
w
n
log
p
n
=
B
P
∏
n
=
1
N
(
e
log
p
n
)
w
n
=
B
P
(
∏
n
=
1
N
p
n
)
w
n
\begin{aligned} BLEU &= BP\exp\big(\sum_{n=1}^Nw_n\log p_n\big)\\ &=BP\prod_{n=1}^Ne^{w_n\log p_n}\\ &=BP\prod_{n=1}^N(e^{\log p_n})^{w_n}\\ &=BP(\prod_{n=1}^Np_n)^{w_n}\\ \end{aligned}
BLEU=BPexp(n=1∑Nwnlogpn)=BPn=1∏Newnlogpn=BPn=1∏N(elogpn)wn=BP(n=1∏Npn)wn
此时与代码中变量bleu
的连乘和加入到列表bleus
中使用的指数就相互对应了
这是计算一句candidate和多句references的方法,如果对于整个candidate和references的集合计算整体的bleu,其计算方法就是将每一对的comps
中对应的元素加起来,如前文所说,comps
包括comps['correct'][k]
就是正确的k-gram(clip之后)数量,comps['guess'][k]
就是candidate
中k-gram的数量,comps['reflen']
就是BP计算公式中的r
,comps['testlen']
就是BP计算公式中的’c’,将它们逐个加起来,然后整体返回到上面的代码中计算即可