from nltk.translate.bleu_score import corpus_bleu
#手工产生(标准)为一个句子
references =[[['there','is','a','cat','and','a','dog']]]#手工产生(标准)——三维列表、图像
candidates =[['there','is','a','cat','and','a','pig']]#电脑产生——二维列表#一组句子和一个句子之间的好坏与差异,是否相似。weights参数指的是:设置不同的n−gram的权重(1−gram,2−gram,3−gram,4−gram)# 第1个位置数值:用1−gram比较,将单词拆成1个一组,不考虑单词的顺序,将单词打乱,看一样的数量占比;)# 第2个位置数值:用2-gram比较,将单词拆成2个一组,there is、is a、a cat...看一样的数量占比;)# 第3个位置数值:用3−gram比较,将单词拆成3个一组,there is a、is a cat...看一样的数量占比;)# 第4个位置数值:用4−gram比较,将单词拆成4个一组,there is a cat、is a cat and...看一样的数量占比;)
score = corpus_bleu(references,candidates,weights=(0.25,0.25,0.25,0.25))print(score)#0.8091067115702212。数字越大,两个句子越相似。#手工产生(标准)为多个句子:原理为-分别于手工产生的句子相比较,取相似度最大的值,可以比较一维列表
references =[[['there','is','a','cat','and','a','dog'],['there','is','a','dog','and','a','cat']]]#手工产生——三维列表、图像
candidates =[['there','is','a','cat','and','a','pig']]#电脑产生——二维列表#一组句子和一个句子之间的好坏与差异,是否相似。weights参数指的是:设置不同的n−gram的权重(1−gram,2−gram,3−gram,4−gram)# 第1个位置数值:用1−gram比较,将单词拆成1个一组,不考虑单词的顺序,将单词打乱,看一样的数量占比;)# 第2个位置数值:用2-gram比较,将单词拆成2个一组,there is、is a、a cat...看一样的数量占比;)# 第3个位置数值:用3−gram比较,将单词拆成3个一组,there is a、is a cat...看一样的数量占比;)# 第4个位置数值:用4−gram比较,将单词拆成4个一组,there is a cat、is a cat and...看一样的数量占比;)
score = corpus_bleu(references,candidates,weights=(0.25,0.25,0.25,0.25))print(score)#0.8091067115702212。数字越大,两个句子越相似。
完整代码:预测一张图片的标题+评估test数据集的生成质量
import util
import numpy as np
from pickle import load
from nltk.translate.bleu_score import corpus_bleu
from keras.models import load_model
from keras.preprocessing.sequence import pad_sequences
defword_for_id(integer, tokenizer):"""
将一个整数转换为英文单词
:param integer: 一个代表英文的整数
:param tokenizer: 一个预先产生的keras.preprocessing.text.Tokenizer
:return: 输入整数对应的英文单词
"""for word, index in tokenizer.word_index.items():if index == integer:return word
returnNonedefgenerate_caption(model, tokenizer, photo_feature, max_length =40):"""
根据输入的图像特征产生图像的标题
:param model: 预先训练好的图像标题生成神经网络模型
:param tokenizer: 一个预先产生的keras.preprocessing.text.Tokenizer
:param photo_feature:输入的图像特征, 为VGG16网络修改版产生的特征
:param max_length: 训练数据中最长的图像标题的长度
:return: 产生的图像的标题
"""
in_text ='startseq'for i inrange(max_length):
sequence = tokenizer.texts_to_sequences([in_text])
sequence = pad_sequences(sequence,maxlen= max_length)[0].reshape(1,40)# print(photo_feature.shape)# print(sequence.shape)# print([photo_feature,sequence])
output = model.predict([photo_feature,sequence])# print('output',output)
integer = np.argmax(output)
word = word_for_id(integer,tokenizer)if word isNone:break
in_text = in_text +" "+ word
if word =="endseq":breakreturn in_text
defgenerate_caption_run():#调用generate_caption函数
filename ='Flickr_8k.testImages.txt'
test = util.load_ids(filename)print('Dataset: %d'%len(test))
test_captions = util.load_clean_captions('descriptions.txt', test)print('Captions: train number=%d'%len(test_captions))# photo features
test_features = util.load_photo_features('features.pkl', test)print('Photos: test=%d'%len(test_features))
filename ="model_0.h5"
model = load_model(filename)print("load model done...")# prepare tokenizer
tokenizer = load(open('tokenizer.pkl','rb'))# 神经网络需要的nxm,其实是np.shape眼里的mxn
caption = generate_caption(model,tokenizer,test_features['1258913059_07c613f7ff'].reshape(1,4096),40)print('1258913059_07c613f7ff 的预测结果result is:'+str(caption))#根据4个BLEU分数来评估所有test数据集
evaluate_model(model,test_captions,test_features,tokenizer,40)return caption
defevaluate_model(model, captions, photo_features, tokenizer, max_length =40):"""计算训练好的神经网络产生的标题的质量,根据4个BLEU分数来评估
Args:
model: 训练好的产生标题的神经网络
captions: dict, 测试数据集, key为文件名(不带.jpg后缀), value为图像标题list
photo_features: dict, key为文件名(不带.jpg后缀), value为图像特征
tokenizer: 英文单词和整数转换的工具keras.preprocessing.text.Tokenizer
max_length:训练集中的标题的最大长度
Returns:
tuple:
第一个元素为权重为(1.0, 0, 0, 0)的BLEU分数
第二个元素为权重为(0.5, 0.5, 0, 0)的BLEU分数
第三个元素为权重为(0.3, 0.3, 0.3, 0)的BLEU分数
第四个元素为权重为(0.25, 0.25, 0.25, 0.25)的BLEU分数
from nltk.translate.bleu_score import corpus_bleu
#手工产生(标准)为一个句子
references = [[['there','is','a','cat','and','a','dog']]]#手工产生(标准)——三维列表、图像
candidates = [['there','is','a','cat','and','a','pig']]#电脑产生——二维列表
#一组句子和一个句子之间的好坏与差异,是否相似。weights参数指的是:设置不同的n−gram的权重(1−gram,2−gram,3−gram,4−gram)
# 第1个位置数值:用1−gram比较,将单词拆成1个一组,不考虑单词的顺序,将单词打乱,看一样的数量占比;)
# 第2个位置数值:用2-gram比较,将单词拆成2个一组,there is、is a、a cat...看一样的数量占比;)
# 第3个位置数值:用3−gram比较,将单词拆成3个一组,there is a、is a cat...看一样的数量占比;)
# 第4个位置数值:用4−gram比较,将单词拆成4个一组,there is a cat、is a cat and...看一样的数量占比;)
score = corpus_bleu(references,candidates,weights=(0.25,0.25,0.25,0.25))
print(score) #0.8091067115702212。数字越大,两个句子越相似。
#手工产生(标准)为多个句子:原理为-分别于手工产生的句子相比较,取相似度最大的值,可以比较一维列表
references = [[['there','is','a','cat','and','a','dog'],['there','is','a','dog','and','a','cat']]]#手工产生——三维列表、图像
candidates = [['there','is','a','cat','and','a','pig']]#电脑产生——二维列表
#一组句子和一个句子之间的好坏与差异,是否相似。weights参数指的是:设置不同的n−gram的权重(1−gram,2−gram,3−gram,4−gram)
# 第1个位置数值:用1−gram比较,将单词拆成1个一组,不考虑单词的顺序,将单词打乱,看一样的数量占比;)
# 第2个位置数值:用2-gram比较,将单词拆成2个一组,there is、is a、a cat...看一样的数量占比;)
# 第3个位置数值:用3−gram比较,将单词拆成3个一组,there is a、is a cat...看一样的数量占比;)
# 第4个位置数值:用4−gram比较,将单词拆成4个一组,there is a cat、is a cat and...看一样的数量占比;)
score = corpus_bleu(references,candidates,weights=(0.25,0.25,0.25,0.25))
print(score) #0.8091067115702212。数字越大,两个句子越相似。
"""
actual, predicted =list(),list()#actual:给定的多个标题;predict:计算机预测产生的标题#step over the whole setfor key,caption_list in captions.items():# generate description
yhat = generate_caption(model,tokenizer,photo_features[key].reshape(1,4096),max_length)print(key,"的预测结果为:",yhat)#store actual and predicted
references =[d.split()for d in caption_list]
actual.append(references)#给定的多个标题
predicted.append(yhat.split())#计算机预测产生的标题#calculate BLEU score
blue1 = corpus_bleu(actual,predicted,weights=(1.0,0,0,0))
blue2 = corpus_bleu(actual, predicted, weights=(0.5,0.5,0,0))
blue3 = corpus_bleu(actual, predicted, weights=(0.3,0.3,0.3,0))
blue4 = corpus_bleu(actual, predicted, weights=(0.25,0.25,0.25,0.25))print('BLUE-1: %f'% blue1)print('BLUE-2: %f'% blue2)print('BLUE-3: %f'% blue3)print('BLUE-4: %f'% blue4)return blue1,blue2,blue3,blue4
if __name__ =="__main__":
generate_caption_run()