现代循环神经网络实战:机器翻译( 十 )


然后,计算精确度 p n p_n pn?可以使用以下公式:
p n = ∑ i : c i , … , i + n ? 1 ∈ c min ? ( freq ? ( c i , … , i + n ? 1 ) , max ? j = 1 m freq ? ( r j , … , j + n ? 1 ) ) ∑ i : c i , … , i + n ? 1 ∈ c freq ? ( c i , … , i + n ? 1 ) p_n = \frac{\sum_{\{i}:\{c}{\{i}, \ldots, \{i}+n-1}\in \{c}} \min(\{freq}(\{c}{\{i}, \ldots, \{i}+n-1}), \max_{\{j}=1}^{m} \{freq}(\{r}{\{j}, \ldots, \{j}+n-1}))}{\sum{\{i}:\{c}{\{i}, \ldots, \{i}+n-1}\in \{c}} \{freq}(\{c}{\{i}, \ldots, \{i}+n-1})} pn?=∑i:ci,…,i+n?1∈cfreq(ci,…,i+n?1)∑i:ci,…,i+n?1∈c?min(freq(ci,…,i+n?1),maxj=1m?freq(rj,…,j+n?1))?
其中分子表示预测序列和参考翻译的n-gram匹配的总次数,分母表示预测序列中n-gram的总数 。
换句话说,p n p_n pn?是两个数量的比值: 第一个是预测序列与标签序列中匹配的元语法的数量,第二个是预测序列中元语法的数量的比率 。
实现
def bleu(pred_seq, label_seq, k):#@save"""计算BLEU"""pred_tokens, label_tokens = pred_seq.split(' '), label_seq.split(' ')len_pred, len_label = len(pred_tokens), len(label_tokens)score = math.exp(min(0, 1 - len_label / len_pred))for n in range(1, k + 1):num_matches, label_subs = 0, collections.defaultdict(int)for i in range(len_label - n + 1):label_subs[' '.join(label_tokens[i: i + n])] += 1for i in range(len_pred - n + 1):if label_subs[' '.join(pred_tokens[i: i + n])] > 0:num_matches += 1label_subs[' '.join(pred_tokens[i: i + n])] -= 1score *= math.pow(num_matches / (len_pred - n + 1), math.pow(0.5, n))return score
测评
engs = ['go .', "i lost .", 'he\'s calm .', 'i\'m home .']fras = ['va !', 'j\'ai perdu .', 'il est calme .', 'je suis chez moi .']for eng, fra in zip(engs, fras):translation, attention_weight_seq = predict_seq2seq(net, eng, src_vocab, tgt_vocab, num_steps, device)print(f'{eng} => {translation}, bleu {bleu(translation, fra, k=2):.3f}')