欢迎来到《看图说话实战教程》系列第三节。在这一节中,我们正式进入看图说话深度模型的构建与训练。
1. 加载数据
我们在教程第二节已经对看图说话模型所需的原始图片及文本数据进行了预处理,并另存为文件形式。此时,我们需要将这些数据加载进来,开始喂给我们的模型。
使用训练集中所有的图片及其文字描述来训练看图说话模型。训练过程中使用验证集来监测模型性能表现并决定何时保存模型。使用测试集来验证模型的实际效果。
Flickr8k
数据集已经包含了拆分好的训练集、验证集与测试集,我们不必在程序中显示地进行拆分。训练集、验证集与测试集分别保存在了 Flickr_8k.trainImages.txt
、Flickr_8k.devImages.txt
与 Flickr_8k.testImages.txt
三个文件当中。数据形式如下所示:
2513260012_03d33305cf.jpg
2903617548_d3e38d7f88.jpg
3338291921_fe7ae0c8f8.jpg
488416045_1c6d903fe0.jpg
2644326817_8f45080b87.jpg
218342358_1755a9cce1.jpg
2501968935_02f2cd8079.jpg
2699342860_5288e203ea.jpg
2638369467_8fc251595b.jpg
2926786902_815a99a154.jpg
...
我们定义一个函数加载这些预定义好的图片数据集:
def load_set(filename):
doc = load_doc(filename)
dataset = list()
# 按行处理
for line in doc.split('\n'):
# 跳过空行
if len(line) < 1:
continue
# 获取图片标志符(ID)
identifier = line.split('.')[0]
dataset.append(identifier)
return set(dataset)
# 加载训练集
filename = 'Flickr8k_text/Flickr_8k.trainImages.txt'
train = load_set(filename)
print('Dataset: %d' % len(train))
接下来最重要的一个步骤就是加载已经经过预处理的图片的文字描述,同时生成模型所需的文字序列。这些文字描述保存在 descriptions.txt
文件中。
模型生成图片文字描述的过程是每次一个字。先前生成好的文字又将被当做新的输入来预测下一个单词,直到遇到序列终止符号才停止生成新的单词。因此,我们需要两个符号分别标记序列生成过程开始与结束。
在这篇教程中,我们使用字符串 startseq
与 endseq
来表示序列生成开始与结束。因此,在加载处理好的图片文字描述的过程中需要生成模型所需的数据形式。
我们定义一个函数来完成这样的过程:
def load_clean_descriptions(filename, dataset):
doc = load_doc(filename)
descriptions = dict()
for line in doc.split('\n'):
tokens = line.split()
image_id, image_desc = tokens[0], tokens[1:]
if image_id in dataset:
if image_id not in descriptions:
descriptions[image_id] = list()
desc = 'startseq ' + ' '.join(image_desc) + ' endseq'
descriptions[image_id].append(desc)
return descriptions
# 加载文字描述
train_descriptions = load_clean_descriptions('descriptions.txt', train)
print('Descriptions: train=%d' % len(train_descriptions))
接下来,我们需要加载VGG模型处理过的图片的特征向量文件,保存在了 features.pkl
文件中。我们定义一个函数完成这个功能:
def load_photo_features(filename, dataset):
all_features = load(open(filename, 'rb'))
# 过滤特征
features = {
k: all_features[k] for k in dataset}
return features
# 加载图片特征向量
train_features = load_photo_features('features.pkl', train)
print('Photos: train=%d' % len(train_features))
至此,我们已经完成了模型所需数据的加载过程。代码运行结果如下:
Dataset: 6,000
Descriptions: train=6,000
Photos: train=6,000
但是,除了VGG模型生成好的图片的特征向量可以被模型直接使用之外,图片的文字描述