欢迎来到《看图说话实战教程》系列第四节。在这一节中,我们开始评估训练好的看图说话模型。
评估指标
在正式进入模型评估实现之前,让我们简单地聊一聊看图说话模型的评估指标。
1. BLEU
看图说话任务的Caption Generation类似于机器翻译任务中的目标语言序列生成。因此,看图说话任务可以采用机器翻译任务的指标对序列生成质量进行评估。机器翻译任务常用的评估指标之一是 BLEU
(BiLingual Evaluation Understudy),意为双语评估替补。Understudy意思就是代替人进行翻译结果的评估。毕竟人工处理过于耗时费力。BLEU算法由IBM研究科学家 Kishore Papineni 于2002年在其论文《BLEU: A Method for Automatic Evaluation of Machine Translation》中首次提出的。
当我们评估一段机器翻译的源语言(如英语)到目标语言(如中文)的序列时,评判机器翻译好坏的准则就是:机器翻译结果越接近专业人士翻译的结果,则翻译得越好。BLEU算法的基本设计思想也是如此。实际上,BLEU算法就是用来判断两个句子的相似程度,做法是:将一句机器翻译的话与其对应的几个参考翻译作比较,计算出一个综合分数,分数越高说明机器翻译得越好。
我们称模型生成的句子为候选句子 (candidate),语料库中的句子为参考句子 (reference)。BLEU算法会计算candidate与reference之间的相似分数。BLEU分数取值范围在0.0到1.0之间,如果两个句子完美匹配 (perfect match),那么BLEU值为1.0;反之,如果两个句子完全不匹配 (perfect mismatch),那么BLEU值为0.0。
2. 优缺点
BLEU算法的优点非常明显:
- 计算代价小,速度快;
- 容易理解;
- 与语言无关(这意味着你可以使用全世界任意的语言来测试);
- 与人类评通过计算
- 被学术界和工业界广泛采用。
但其缺点也不能被忽略:
- 不考虑语言表达(语法)上的准确性;
- 测评精度会受常用词的干扰;
- 短译句的测评精度有时会较高;
- 没有考虑同义词或相似表达的情况,可能会导致合理翻译被否定;
要知道,BLEU算法是做不到百分之百地准确,它只能做到个大概判断,它的目标也只是给出一个快且不差的自动评估解决方法。
Kishore Papineni在其论文中提出了一种改进方法——修正的N-Grams精度——以确保它考虑到参考句子reference文本中单词的出现,而非奖励生成大量合理翻译单词的候选结果。为了提升多个句子组成的block的翻译效果,论文通过正则化N-Grams进行改进。更多的细节参见论文。
3. 计算BLEU分数
Python自然语言工具包库(NLTK)提供了BLEU评分的实现,你可以使用它来评估生成的文本,通过与参考文本对比。
3.1 语句BLEU分数
NLTK提供了sentence_bleu()
函数,用于根据一个或多个参考语句来评估候选语句。
from nltk.translate.bleu_score import sentence_bleu
reference = [['this', 'is', 'a', 'test'], ['this', 'is', 'test']]
candidate = ['this', 'is', 'a', 'test']
score = sentence_bleu(refernce, candidate)
print(score) # 输出1.0,完全匹配
3.2 语料库BLEU分数
NLTK还提供了一个称为corpus_bleu()
的函数来计算多个句子(如段落或文档)的BLEU分数。
# two references for one document
from nltk.translate.bleu_score import corpus_bleu
references = [[['this', 'is', 'a', 'test'], ['this', 'is' 'test']]]
candidates = [['this', 'is', 'a', 'test']]
score = corpus_bleu(references, candidates)
print(score) # 输出1.0
3.3 累加和单独的BLEU分数
NLTK中提供的BLEU评分方法允许你在计算BLEU分数时为不同的n元组指定权重。这使你可以灵活地计算不同类型的BLEU分数,如单独和累加的n-gram分数。
单独的N-Gram分数
单独的N-gram分数是对特定顺序的匹配n元组的评分,例如单个单词(称为1-gram)或单词对(称为2-gram或bigram)。权重被指定为一个数组,其中每个索引对应相应次序的n元组。仅要计算1-gram匹配的BLEU分数,你可以指定1-gram权重为1,对于2元,3元和4元指定权重为0,也就是权重为(1,0,0,0)。
# n-gram individual BLEU
from nltk.translate.bleu_score import sentence_bleu
reference = [['this', 'is', 'a', 'test']]
candidate = ['this', 'is', 'a', 'test']
print('Individual 1-gram: %f' % sentence_bleu(reference, candidate, weights=(1, 0, 0