简介
介绍基于注意力机制的图像标题生成模型的原理和实现
原理
输入是一张图片,输出是一句对图片进行描述的文本,这就是图像标题生成
基本思路是先通过预训练的图像分类模型,从某一个卷积层得到原始图片的表示,或者称为上下文contexts
例如从VGG19的拿到原始图片的表示,shape为,即512张的小图
这样一来,可以理解为将原始图片分成共196个小块,每个小块对应一个512维的特征
根据contexts使用LSTM逐步生成单词,即可产生原始图片对应的描述文本
在生成每一个单词时,应该对196个块有不同的偏重,即所谓的注意力机制
就像我们人一样,考虑下一个词时,对图片的不同区域会有不同的关注度,相关性更强的区域会获得更多的注意力即更高的权重
根据注意力权重对196个512维的特征进行加权求和,即可得到基于注意力机制的上下文context
和之前介绍过的联系起来,图像标题生成便属于one to many这种情况
数据
使用COCO2014数据,http://cocodataset.org/#download,训练集包括8W多张图片,验证集包括4W多张图片,并且提供了每张图片对应的标题
每张图片的标题不止一个,因此训练集一共411593个标题,而验证集一共201489个标题,平均一张图片五个标题
实现
基于以下项目实现,https://github.com/yunjey/show-attend-and-tell
训练
首先是训练部分代码
加载库
加载数据,因为一张图片可能对应多个标题,因此以一个图片id和一个标题为一条数据。对于图片内容,保留中心正方形区域并缩放;对于标题,长度超过20个词则去除
查看一下标题标注
整理词典,一共23728个词,建立词和id之间的映射,并使用到三个特殊词
将标题转换为id序列
使用图像风格迁移中用过的来提取图像特征,加载vgg19模型并定义一个函数,对于给定的输入,返回vgg19各个层的输出值,通过实现网络的重用,将的输出作为原始图片的表示
基于以上contexts,实现初始化、词嵌入、特征映射等部分
依次生成标题中的每个词,包括计算注意力和context、计算选择器、lstm处理、计算输出、计算损失函数几个部分
在损失函数中加入注意力正则项,定义优化器
训练模型,将一些tensor的值写入events文件,便于后续使用tensorboard查看
使用以下命令可以在tensorboard中查看历史训练数据
经过20轮训练后,损失函数曲线如下
验证
接下来是验证部分代码,即在验证集上生成每张图片的标题,然后和标注进行对比和评估
在生成每一个词的时候,可以选择概率最大的词,即贪婪的做法,但不一定最优,因为当前概率最大的词并不能保证之后产生的序列整体概率最大
也不能像中文分词中那样使用viterbi算法,因为viterbi算法要求整个序列的概率分布已知,才能使用动态规划找到最大概率路径
但生成标题的时候,是一个词一个词地生成,而且选择的类别等于词典的大小,远远超出中文分词序列标注中的四分类,因此不可能穷尽所有可能的序列
一种折中的做法是使用beam search,涉及一个参数beam size,举个例子,当beam size等于3时
- 生成第一个词时,保留概率最大的三个词
- 生成第二个词时,在以上三个词的基础上,进一步生成九个词,保留九个序列中概率最大的三个
- 生成第n个词时,基于上一步保留下来的三个序列,进一步生成九个词,保留新的九个序列中概率最大的三个
- 就好比一棵树,每一次所有的树枝都会进一步长出三个子树枝,然后对于所有树枝,保留最好的三个,其他全部砍掉
- 重复以上过程,直到生成了结束词,或者生成的序列达到了最大长度
验证部分的大多数代码和训练部分相同
加载库
加载数据
整理正确答案
加载训练部分整理好的词典
加载vgg19模型
验证部分需要定义几个placeholder,因为要使用到beam search,所以每生成一个词就需要输入一些相关的值
生成部分,不需要循环,重复一次即可,后面进行beam search时再进行多次输入数据并得到输出
加载训练好的模型,对每个batch的数据进行beam search,依次生成每一个词
这里beam size设为1主要是为了节省时间,验证共花了10个小时,具体应用时可以适当加大beam size
将标题生成结果写入文件,便于后续评估
调用以下项目进行评估,https://github.com/tylin/coco-caption,评估指标包括BLEU、Rouge、Cider三个
其中BLEU在图像标题生成、机器翻译等任务中用得比较多,可以简单理解为1-gram、2-gram、3-gram、4-gram的命中率
吴恩达深度学习微专业课中关于BLEU的介绍,http://mooc.study.163.com/course/2001280005?tid=2001391038#/info
评估结果如下,适当加大beam size可以进一步提高各项指标
- Bleu_1:0.6878
- Bleu_2:0.4799
- Bleu_3:0.3347
- Bleu_4:0.2355
- ROUGE: 0.5304
- CIDEr: 0.7293
使用
最后,通过以下代码在本机上使用训练好的模型,为任意图片生成标题
整体代码结构和验证部分比较类似,但是由于只需要对一张图片生成标题,所以beam search部分的代码简化很多
标题生成结果如下,非常准确地涵盖了新娘、新郎、摆pose、拍照等关键词,并且注意力可视化也很好地反映了生成每个词时模型对图片不同区域的关注度
参考
- Show, Attend and Tell: Neural Image Caption Generation with Visual Attention:https://arxiv.org/abs/1502.03044
- TensorFlow Implementation of “Show, Attend and Tell”:https://github.com/yunjey/show-attend-and-tell