首发于AI Insight
「Show and Tell」——图像标注(Image Caption)任务技术综述

「Show and Tell」——图像标注(Image Caption)任务技术综述

所谓Image Caption,就是从图片中自动生成一段描述性文字,有点类似于我们小时候做过的“看图说话”,十分有趣。对于人来说,Image Caption是简单而自然的一件事,但对于机器来说,这项任务却充满了挑战性。原因在于机器不仅要能检测出图像中的物体,而且要理解物体之间的相互关系,最后还要用合理的语言表达出来。

随着深度学习技术的发展和COCO等图像标注数据集的出现,Image Caption相关的技术得到了快速的发展。本文就在这个领域中,选择了最具代表性的几篇论文进行讲解。在讲解的过程中会尽量注意论文间的发展和联系。

1. 从Encoder-Decoder结构谈起

在介绍Image Caption相关的技术前,有必要先来复习一下RNN的Encoder-Decoder结构。我们知道,在最原始的RNN结构中,输入序列和输出序列必须是严格等长的。但在机器翻译等任务中,源语言句子的长度和目标语言句子的长度往往不同,因此我们需要将原始序列映射为一个不同长度的序列。Encoder-Decoder模型就解决了这样一个长度不一致的映射问题,它的结构如下图所示:



w_{1},w_{2},w_{3}\text{...}w_{n} 是输入的单词序列,而 y_{1},y_{2},...y_{m} 为输出的单词序列,每个 w_{i}y_{i} 都是已经经过独热编码的单词,因此它们都是1xD的向量,其中D为程序中使用的单词表的长度。RNN的隐层状态(hidden state)用 h_{1},h_{2},h_{3}\text{...}h_{n} 表示。在实际应用中,我们往往不是把独热编码的 w_{1},w_{2},w_{3}\text{...}w_{n} 输入RNN,而是将其转换为对应的word embedding的形式,即图中的 x_{1},x_{2},x_{3}\text{...}x_{n} ,再输入RNN网络。在Encoder部分,RNN将所有的输入“编码”成一个固定的向量表示,即最后一个隐层状态 h_{n} , 我们就认为这个h_{n} 包含了原始输入中所有有效的信息,,Decoder在每一步都会利用 h_{n} 这个信息,进行“解码”,并输出合适的单词序列 y_{1},y_{2},...y_{m} 。这样,我们就完成了不同长度序列之间的转换工作。

Encoder-Decoder结构最初是在论文《Learning Phrase Representations using RNN Encoder–Decoder for Statistical Machine Translation》中提出并应用到机器翻译系统中的。有兴趣的同学可以参考原始论文了解其细节,这里我们还是回到Image Caption任务中来,看看如何把Encoder-Decoder结构用到Image Caption上。

2. Show and Tell: A Neural Image Caption Generator

在机器翻译任务中,输入输出都是单词序列,现在换一下,在Image Caption任务中,输入是图像,输出是单词序列,应该怎么建模呢?其实很简单,我们只需要将原来的Encoder RNN换成图像中使用的CNN结构,为图像提取一个“视觉特征”I,然后还是使用Decoder将这个I解码为输出序列就可以了,这就是论文《Show and Tell: A Neural Image Caption Generator》中的想法。

这篇论文算是做Image Caption任务早期的开山之作,它只把Encoder-Decoder结构做了简单修改,就在Image Caption任务上取得了较好的结果,下图是这篇论文中网络的具体结构。先看提取图像特征的CNN部分,由于这篇论文是谷歌出品的,因此这部分就使用了自家的Inception模型。再看Decoder部分,将RNN换成了性能更好的LSTM,输入还是word embedding,每步的输出是单词表中所有单词的概率,这些都是标准做法了,就不再赘述。


这篇论文为Image Caption任务提供了一种统一的思路,下面我们会连着介绍三篇论文,都是在这篇论文基础上的改进。

3. Show, Attend and Tell: Neural Image Caption Generation with Visual Attention

在Encoder-Decoder结构中,Encoder把所有的输入序列都编码成一个统一的语义特征 h_{n} 再解码,因此, h_{n} 中必须包含原始句子中的所有信息,它的长度就成了限制模型性能的瓶颈。对于短句来说还好,但当句子较长时,一个 h_{n} 可能存不下那么多信息,就会造成翻译精度的下降。对此,论文《Neural machine translation by jointly learning to align and translate》提出了一种Attention机制,不再使用统一的语义特征,而让Decoder在输入序列中自由选取需要的特征,大大提高了Encoder-Decoder的模型性能。

在Image Caption任务中,我们同样可以利用Attention机制对原来的Encoder-Decoder机制进行改进,对应的论文就是这篇《Show, Attend and Tell: Neural Image Caption Generation with Visual Attention》了。显然这篇文章的标题山寨了我们之前提到的“Show and Tell”,将之改为“Show, Attend and Tell”,意即加入了Attention机制。

具体怎么来做呢?之前是用CNN提取了固定长度的向量特征I,实际上,我们可以利用CNN的空间特性,使用卷积层的feature map,给图片的不同位置都提取一个特征。举例来说,用 a = \{ a_{1},a_{2},...,a_{L}\},a_{i} \in R^{D} 表示我们提取的图片特征,一共 L 个位置,每个位置的特征为一个 D 维的向量,对于一个高、宽为14,通道数为256的feature map,对应的 L = 14 \times 14 = 196 , D=256

有了这些位置的特征,我们再让Decoder在解码时拥有在这196个位置特征中选择的能力,这就是Attention机制。设在第t阶段(通俗的讲,就是生成第t个单词时)传入Decoder RNN的上下文向量为 z_{t} ,RNN前一阶段的隐层状态为 h_{t - 1} 。这个上下文向量 z_{t} 就是 a = \{ a_{1},a_{2},...,a_{L}\} 的一个加权平均,具体地, z_{t}a = \{ a_{1},a_{2},...,a_{L}\} 的关系用下面的式子表达:

z_{t} = \sum_{i = 1}^{L}{\alpha_{t,i}a_{i}}

\alpha_{t,i} 就是衡量生成第t个单词时,第i个位置的图像特征所占的权重。这个权重实际是前一个隐层状态 h_{t - 1} 和第i个位置图像特征 a_{i} 的函数。具体的表达式为:

e_{\text{ti}} = f_{\text{att}}(a_{i},h_{t - 1})

\alpha_{t,i} = \frac{exp(e_{\text{ti}})}{\sum_{k = 1}^{L}exp(e_{\text{tk}})}

由于 \alpha_{t,i} 只和已有的信息 h_{t - 1}, a_{i} 有关,因此这些参数也是可以从数据中进行端到端的自动学习的。

值得一提的是,这个论文实际介绍了两种Attention机制,一种叫HardAttention,一种叫Soft Attention,我们这里只讲了标准的Soft Attention,Hard Attention比Soft Attention更有难度,限于篇幅原因不再展开介绍。实验证明,无论是使用Hard Attention还是Soft Attention,都提高了原始模型的性能。

另外,由于使用了Attention机制,我们可以根据权重系数 \alpha_{t,i} 的大小,得知在生成每个词时模型关注到了图片的哪个区域。下图展示了一些例子,每个句子都是模型自动生成的,在图片中用白色高亮标注了生成下划线单词时模型关注的区域:



4. What Value Do Explicit High Level Concepts Have in Vision to Language Problems?

除了使用Attention的机制改善Encoder-Decoder结构外,这篇文章又提供了另外一种改进原始模型的方式,即使用高层语义特征。

在前两篇论文中,都是使用CNN在做最终分类之前的卷积特征作为“图像语义”,但这篇文章认为,CNN在最终的分类层包含了大量诸如“图中有无人”、“图中有无桌子”这样的高层信息。这种高层语义与最终生成的语句非常相关,不能轻易舍弃。

实际做法中,作者把这个高层语义理解为一个多标签分类问题。在Image Caption任务中,需要知道图片里面有哪些物体,由于一张图片中的物体数目会有很多,因此图片和物体标签就是一个一对多的关系,而不是通常的一对一的关系。为此,我们需要对原先的CNN结构做出适当调整。在通常的一对一关系中,我们在卷积特征后使用一个softmax即可,而在一对多关系中,假设我们要找出c类物体,那么就分别使用c个softmax层。设第i张图片的标签 y_{i} = \{ y_{i1},y_{i2},...,y_{\text{ic}}\} 。其中每个 y_{\text{ij}} 要么是0,要么是1,1表示该图片具有标签j(如图中有人),0表示该图片不具有标签j。又设c个softmax层的输出各个标签的概率 p_{i} = \{ p_{i1},p_{i2},...,p_{\text{ic}}\} ,那么最终的损失就是:

J = \frac{1}{N}\sum_{i = 1}^{N}{\sum_{j = 1}^{c}l}og(1 + exp( - y_{\text{ij}}p_{\text{ij}}))

在训练时,首先在所有描述中提取出现最频繁的c个单词作为总标签数,每个图像的训练数据直接从其描述单词中取得。训练完成后,就可以针对每张图片提取高层的语义表达向量 V_{\text{att}}(I) (如下图所示)。简单来说,这个高层语义向量 V_{\text{att}}(I) 实际就表示图像中出现了哪些物体。


得到 V_{\text{att}}(I) 后,就直接将其送入Decoder进行解码。Decoder的结构和最初的那篇论文中的结构完全一致。如在下图中,蓝色的线就是之前直接使用的卷积特征 CNN(I) ,而红色线就是这篇文章提出的 V_{\text{att}}(I)实验证明,使用 V_{\text{att}}(I) 代替 CNN(I) 可以大幅提高模型效果。

5. Mind’s Eye: A Recurrent Visual Representation for Image Caption Generation

之前的两篇论文,《Show, Attend and Tell: Neural Image Caption Generation with Visual Attention》以及《What Value Do Explicit High Level Concepts Have in Vision to Language Problems?》,一个是给RNN加上了Attention结构,一个是改进了CNN提取的特征,都是比较好理解的。而这篇文章比较fancy,较多地改动了Decoder部分RNN的本身的结构,使得RNN网络不仅能将图像特征翻译为文字,还能反过来从文字得到图像特征,此外还顺带提高了性能,我们一起来看下是怎么做的。

下图就是这篇文章中使用的Decoder RNN。 v 表示图像特征, s_{t} 表示第t阶段RNN的隐层状态,而 w_{t} 是第t阶段生成的单词。 v,s_{t},w_{t} 这三个量都是之前的模型中存在的,而作者又再这些量的基础上加入了 u_{t}\tilde{v} 。其中 u_{t} 表示的是“已经生成的文字”的隐变量,作用是记住已经生成单词中包含的信息。这个量在每次生成 w_{t} 时都会使用到,作为给模型的提示。此外,作者还要求在每个阶段都可以使用 u_{t} 去还原视觉信息 v ,通过 u_{t} 计算的视觉信息就是 \tilde{v} ,在训练尽可能要求 \tilde{v} \approx v换句话说,我们已经生成的文字都要尽可能地去表达视觉信息,才能做到这样的还原。


W_{t} = \{ w_{1},w_{2},...,w_{t}\} ,表示在第t阶段已经生成的所有t个单词。 U_{t} = \{ u_{1},u_{2},...,u_{t}\} 是已经生成的单词表达信息的隐变量。这篇文章的核心就是,我们之前建模的都是 P(w_{t}|v,W_{t - 1},U_{t - 1}) ,即在图像信息和已经生成单词的条件下找寻下一个单词的概率,而这篇文章建模的是 P(w_{t},v|W_{t - 1},U_{t - 1}) ,由于这是 w_{t},v 的联合分布,因此我们不仅可以生成文字,还可以反过来利用文字生成图像特征。

如下图,我们在生成文字的时候,不需要用到 \tilde{v} ,因此将其去掉即可:


在利用文字生成图像特征时,没有下面的 vs_{t} ,同样将之去除:


6. From Captions to Visual Concepts and Back

最后还有一篇不得不提到的《From Captions to Visual Concepts and Back》。这篇为微软出品,是和第一篇谷歌的论文同时期的文章,它们都去参加了微软的Image Caption比赛(MS COCO caption challenge),总的结果是并列第一(如下图),在具体的小指标上各有上下,都是属于开创性的工作。之所以放到最后讲是因为它并不属于Encoder-Decoder架构,而是采用传统的语言建模方式。


在图像特征提取方面,这篇文章和《What Value Do Explicit High Level Concepts Have in Vision to Language Problems?》类似,都是从图像中提取可能存在的单词,再对语言进行建模。不同点在于,之前那篇文章采用的是多标签学习的方式,而这篇文章采用的是多示例学习(Multiple Instance Learning)的方法,不仅可以从图像中提取可能的单词,而且可以把单词对应到具体的图像区域。

首先来简单介绍下多示例学习。多示例学习实际是一种半监督算法。考虑这样一种训练数据:我们有很多个数据包(bag),每个数据包中有很多个示例(instance)。我们只有对bag的正负类标记,而没有对instance的正负例标记。当一个bag被标记为正时,这个包里一定有一个instance是正类,但也有可能其他instance是负类,当一个bag被标记为负类时,它里面的所有instance一定是负类。我们的目标是训练一个分类器,可以对instance的正负进行判别。

多示例学习在现实中其实很常见。如一篇文章违禁时通常是因为该文章具有某些违禁词,但我们可能无法知道具体是哪个词违禁。在这个例子中,bag就是文章,instance就是单词。又如在医学图像领域,CT图被标定为有无病症,而一个人有病症是因为在CT图的某个区域被检测为病灶区域。我们往往只有CT图的标注,但没有CT图中每个区域的标注。这时,bag就是CT图像,而instance就是CT图中的小区域。

在这篇论文中,就是使用多示例学习来处理从图片出提取单词这一问题。对每一个单词来说,标注中含有该单词的图片就是正例的bag,图中的区域就是instance。由此,我们使用多示例学习方法进行两步迭代,第一步是利用当前算法,选出正例bag中最有可能是正例的instance、以及负例bag的instance,第二步是利用选出的instance进行训练,更新训练。这样迭代下去,就可以对图片的区域进行分类了。这样我们就可以从图片的区域中提取所需要的单词(如下图)。在实际操作的时候,使用的是一种针对目标检测改进版的多示例学习方法Noisy-OR MIL,细节可以参考论文《Multiple instance boosting for object detection》。



在图像中提取好单词后,这篇文章就采用一种传统的方法来进行语言建模。设在图片中提取的单词都放在一个集合 \tilde{V} 中,自动生成的图片标注为 \{ w_{1},w_{2},w_{3}....\} ,我们的目标就是去建模 P(w_{l}|w_{1},w_{2},w_{3},....w_{l - 1},\tilde{V_{l}}) ,其中 \tilde{V_{l}} \subset \tilde{V} ,表示生成第l个单词时,还没有使用的单词。

建模 P(w_{l}|w_{1},w_{2},w_{3},....w_{l - 1},\tilde{V_{l}}) 的方法是使用一些特征提取函数从 w_{l},w_{1},w_{2},w_{3},....w_{l - 1},\tilde{V_{l}} 这些单词中提取一些特征,如文中使用了 w_{i} 是否属于 \tilde{V_{l}} 、n-Gram关系等特征,每个特征提取函数设为 f_{k} ,对每个要生成的单词,就可以得到一个打分 \sum_{k}^{}{\lambda_{k}f_{k}(w_{l},w_{1},w_{2},w_{3},....w_{l - 1},\tilde{V_{l}})} ,最后使用softmax函数将这些打分转换为概率即可。

7. 总结

本文选取了Image Caption领域中比较重要的5篇文章进行了介绍。第一篇论文首先使用了Encoder-Decoder结构对此问题进行建模,接下来三篇文章分别从不同的角度对第一篇论文做出了改进。最后介绍的论文并没有采用Encoder-Decoder结构,而是采用传统的方式对语言进行建模,也具有一定启发意义。

编辑于 2017-07-15

文章被以下专栏收录