用于视觉问答的深度模块化共同注意网络 《Deep Modular Co-Attention Networks for Visual Question Answering》

目录

  • 文献摘要介绍
  • 文献内容讲解
  • 网络框架详细介绍
  • 实验分析
  • 结论

本文有点长,请耐心阅读,定会有收货。自己是研究生一枚,如有不足,欢迎交流 附: 本文的代码地址

一、文献摘要介绍

    Visual Question Answering (VQA) requires a fine-grained and simultaneous understanding of both the visual content of images and the textual content of questions.Therefore, designing an effective ‘co-attention’ model to associate key words in questions with key objects in imagesis central to VQA performance. So far, most successful attempts at co-attention learning have been achieved by using shallow models, and deep co-attention models show little improvement over their shallow counterparts. In this paper, we propose a deep Modular Co-Attention Network (MCAN) that consists of Modular Co-Attention(MCA) layers cascaded in depth. Each MCA layer models the self-attention of questions and images, as well as the question-guided-attention of images jointly using a modular composition of two basic attention units. We quantitatively and qualitatively evaluate MCAN on the benchmark VQA-v2 dataset and conduct extensive ablation studies to explore the reasons behind MCAN’s effectiveness.Experimental results demonstrate that MCAN significantly outperforms the previous state-of-the-art. Our best single model delivers 70.63% overall accuracy on the test-dev set.

    首先文献作者介绍了动机,VQA需要细粒度化以及同时理解视觉(图像)内容和文本(问题)内容,因此设计了模块化协同注意力网络模型来结合问题中的关键词和图像中的关键目标。但是目前的协同注意力学习只用在了浅层模型,而深层模型在浅层问题上只有微弱的提升。这篇文章作者提出了深层协同注意力网络MCAN(由协同注意力模块MCA层串联构成)。每一个MCA层都能够对图像和问题的自我注意力( self-attention of questions and images)进行建模,以及问题-图像的引导注意力(question-guided-attention of images),最后作者还对该模型进行了评估。

二、文献内容讲解

    注意力机制目前表现出了非常好的效果,目前协同注意力在图像和文本表示中也有着不错的表现。但是,这种协同注意力机制只能够学习到多模态之间粗糙的交互,协同注意力也不够进行图像和问题关键词之间的关系推断。为了解决协同注意力不能够进行多模态之间的充分交互问题,目前提出了两个密集协同注意力模型(dense co-attention model)——BAN和DCN。有趣的是,这两个模型是可以串联在一起解决更深层次的视觉推理。但是这两个模型相较于浅层模型却仅有很小的性能提升,作者认为原因在于这两个模型没有同时在每一个模态中对密度自注意力建模。

    MCAN网络框架的设计灵感来自于Transformer模型,作者设置了两个注意力单元(general attention units):一个自注意力单元(self-attention (SA) unit)进行模态内部交互和一个导向注意力单元(guided-attention (GA) unit)进行模态之间交互。之后再用一个协同注意力模块层(Modular Co-Attention (MCA) layers)将两个单元串联起来,最后将多个模块层串联起来,组成MCAN网络(Modular Co-Attention Network (MCAN))。模型基于VQAv2数据集的精度如下图所示:
用于视觉问答的深度模块化共同注意网络 《Deep Modular Co-Attention Networks for Visual Question Answering》_第1张图片

1.相关工作

  • VQA
    VQA是近几年发展起来的新方向。一般处理思路就是将图像和问题先表示为全局特征,然后再用多模态融合模型进行答案的概率预测。目前问题的表示主要用LSTM,多模态融合主要用残差网络。目前融合造成的问题在于,对一张图进行全局特征表示也许会损失一些关键信息,而这些信息可能涉及到问题中的图像局部区域,解决办法大多还是用的注意力机制。

  • 协同注意力模型(Co-Attention Models)
    同时学习问题的文本注意力和图像的诗句注意力是有必要的,目前协同注意力网络网络是在每个模态中分别学习其注意力分布,且忽视了图像和文本的密集交互(dense attention)。这对多模态特征之间细粒度关系的理解造成了瓶颈。解决这一问题目前主要办法则是用密集的协同注意力网络。

2.模块化协同注意力层MCA(Modular Co-Attention Layer)

    MCA层是将两个注意力单元结合起来的一个模块,灵感来自于scaled dot-product attention,使用三种结合方式,将能够获得三种MCA变体(variants),首先看一下论文作者设计的网络的架构。
用于视觉问答的深度模块化共同注意网络 《Deep Modular Co-Attention Networks for Visual Question Answering》_第2张图片
    整个网络分为了三个模块:①对输入的图像和问题进行特征表示(representation);②提出两个协同注意力模型,即stacking和encoder-decoder,这两个模型都是由多个MCA层串联而成,能够对之前的问题特征和图像特征进行进一步提炼;③利用一个简单的多模态融合模型对两个特征进行融合,最后再将其输入到一个多标签类别分类器中进行正确答案的预测。
    接下来对该架构进行详细的分析,论文借鉴了Attention Is All You Need里面的Scaled Dot-Product Attention 和 Multi-Head Attention,我们介绍一下Attention Mechanism,为了能够详细理解今天讲的这篇论文,首先先介绍一下Attention的定义,然后对Scaled Dot-Product Attention 和 Multi-Head Attention进行讲解。
(1)Attention定义
    Attention用于计算"相关程度",例如在翻译过程中,不同的英文对中文的依赖程度不同,Attention通常可以进行如下描述,表示为将query(Q)和key-value pairs映射到输出上,其中query、每个key、每个value都是向量,输出是V中所有values的加权,其中权重是由Query和每个key计算出来的,计算方法分为三步:
1)计算比较Q和K的相似度,用f来表示:
在这里插入图片描述

2)将得到的相似度进行softmax归一化:
在这里插入图片描述

3)针对计算出来的权重,对所有的values进行加权求和,得到Attention向量:
在这里插入图片描述
计算相似度的方法有以下4种:
用于视觉问答的深度模块化共同注意网络 《Deep Modular Co-Attention Networks for Visual Question Answering》_第3张图片
    在本文中,我们计算相似度的方式是第一种,将Attention落实到具体,分别叫做 Scaled Dot-Product Attention 和 Multi-Head Attention。 计算self attention的第一步是从每个Encoder的输入向量上创建3个向量(在这个情况下,对每个单词做词嵌入)。所以,对于每个单词,我们创建一个Query向量,一个Key向量和一个Value向量。这些向量是通过词嵌入乘以我们训练过程中创建的3个训练矩阵而产生的。

(2)Scaled Dot-Product Attention

Scaled Dot-Product Attention的图示如下:
用于视觉问答的深度模块化共同注意网络 《Deep Modular Co-Attention Networks for Visual Question Answering》_第4张图片

  • First Step
         首先从输入开始理解,Scaled Dot-Product Attention里的Q, K, V从哪里来:按照我的理解就是给我一个输入X, 通过3个线性转换把X转换为Q,K,V。
    用于视觉问答的深度模块化共同注意网络 《Deep Modular Co-Attention Networks for Visual Question Answering》_第5张图片

两个单词,Thinking, Machines. 通过嵌入变换会X1,X2两个向量[1x4]。分别与Wq,Wk,Wv三个矩阵[4x3]做点乘得到,{q1,q2},{k1,k2},{v1,v2} 6个向量[1x3]。

  • Second Step
    用于视觉问答的深度模块化共同注意网络 《Deep Modular Co-Attention Networks for Visual Question Answering》_第6张图片

向量{q1,k1}做点乘得到得分(Score) 112, {q1,k2}做点乘得到得分96。

  • Third and Forth Steps
    用于视觉问答的深度模块化共同注意网络 《Deep Modular Co-Attention Networks for Visual Question Answering》_第7张图片

对该得分进行规范,除以8。这个在论文中的解释是为了使得梯度更稳定。之后对得分[14,12]做softmax得到比例 [0.88,0.12]。

  • Fifth Step
    用于视觉问答的深度模块化共同注意网络 《Deep Modular Co-Attention Networks for Visual Question Answering》_第8张图片

用得分比例[0.88,0.12] 乘以[v1,v2]值(Values)得到一个加权后的值。将这些值加起来得到z1。这就是这一层的输出。仔细感受一下,用Q,K去计算一个thinking对与thinking, machine的权重,用权重乘以thinking,machine的V得到加权后的thinking,machine的V,最后求和得到针对各单词的输出Z。

  • 矩阵表示
    用于视觉问答的深度模块化共同注意网络 《Deep Modular Co-Attention Networks for Visual Question Answering》_第9张图片

之前的例子是单个向量的运算例子。这张图展示的是矩阵运算的例子。输入是一个[2x4]的矩阵(单词嵌入),每个运算是[4x3]的矩阵,求得Q,K,V。

用于视觉问答的深度模块化共同注意网络 《Deep Modular Co-Attention Networks for Visual Question Answering》_第10张图片

Q对K转制做点乘,除以dk的平方根。做一个softmax得到合为1的比例,对V做点乘得到输出Z。那么这个Z就是一个考虑过thinking周围单词(machine)的输出。

    注意看这个公式, QK^T其实就会组成一个word2word的attention map!(加了softmax之后就是一个合为1的权重了)。比如说你的输入是一句话 “i have a dream” 总共4个单词,这里就会形成一张4x4的注意力机制的图:
用于视觉问答的深度模块化共同注意网络 《Deep Modular Co-Attention Networks for Visual Question Answering》_第11张图片

这样一来,每一个单词就对应每一个单词有一个权重

注意encoder里面是叫self-attention,decoder里面是叫masked self-attention。

这里的masked就是要在做language modelling(或者像翻译)的时候,不给模型看到未来的信息。
用于视觉问答的深度模块化共同注意网络 《Deep Modular Co-Attention Networks for Visual Question Answering》_第12张图片

mask就是沿着对角线把灰色的区域用0覆盖掉,不给模型看到未来的信息。

    详细来说,i作为第一个单词,只能有和i自己的attention。have作为第二个单词,有和i, have 两个attention。 a 作为第三个单词,有和i,have,a 前面三个单词的attention。到了最后一个单词dream的时候,才有对整个句子4个单词的attention。
用于视觉问答的深度模块化共同注意网络 《Deep Modular Co-Attention Networks for Visual Question Answering》_第13张图片

mask做完softmax后就像这样,横轴合为1

(3) Multi-Head Attention
    Multi-Head Attention就是把Scaled Dot-Product Attention的过程做H次,然后把输出Z合起来。它的结构图如下:
用于视觉问答的深度模块化共同注意网络 《Deep Modular Co-Attention Networks for Visual Question Answering》_第14张图片
我们还是以上面的形式来解释:
用于视觉问答的深度模块化共同注意网络 《Deep Modular Co-Attention Networks for Visual Question Answering》_第15张图片

我们重复记性8次相似的操作,得到8个Zi矩阵

用于视觉问答的深度模块化共同注意网络 《Deep Modular Co-Attention Networks for Visual Question Answering》_第16张图片

为了使得输出与输入结构对标 乘以一个线性W0 得到最终的Z。

    介绍完上面的工作接下来,接下来我们对SA和GA两个注意力单元就能够很好的理解了。

三、网络框架详细介绍

(1)SA和GA单元(Self-Attention and Guided-Attention Units):
用于视觉问答的深度模块化共同注意网络 《Deep Modular Co-Attention Networks for Visual Question Answering》_第17张图片
详细代码如下:

# 计算注意力
    def att(self, value, key, query, mask):
        d_k = query.size(-1)

        # 注意力计算公式 f=A(q,K,V)=softmax(Qk/d) V
        scores = torch.matmul(
            query, key.transpose(-2, -1)
        ) / math.sqrt(d_k)

        if mask is not None:
            scores = scores.masked_fill(mask, -1e9)  # masked_fill
        # 注意力图
        att_map = F.softmax(scores, dim=-1)
        att_map = self.dropout(att_map)  # dropout 0.1

        return torch.matmul(att_map, value)

之后再引入multi-head attention,它由h个平行的“head”组成:
用于视觉问答的深度模块化共同注意网络 《Deep Modular Co-Attention Networks for Visual Question Answering》_第18张图片
下面是multi-head attention里面的代码

#multi-head attention
class MHAtt(nn.Module):
    def __init__(self, __C):
        super(MHAtt, self).__init__()
        self.__C = __C
        # 相当于定义 head = A(qW^Q,kW^K,vW^V)
        self.linear_v = nn.Linear(__C.HIDDEN_SIZE, __C.HIDDEN_SIZE)  # 定义v
        self.linear_k = nn.Linear(__C.HIDDEN_SIZE, __C.HIDDEN_SIZE)  # 定义k
        self.linear_q = nn.Linear(__C.HIDDEN_SIZE, __C.HIDDEN_SIZE)  # 定义q
        self.linear_merge = nn.Linear(__C.HIDDEN_SIZE, __C.HIDDEN_SIZE)  # 定义合并

        self.dropout = nn.Dropout(__C.DROPOUT_R)  # 定义丢弃率:0.1

    # 前向
    def forward(self, v, k, q, mask):
        n_batches = q.size(0)  # 表示计算多少次

        v = self.linear_v(v).view(
            n_batches,
            -1,
            self.__C.MULTI_HEAD,  # # Multi-head的数量:8
            self.__C.HIDDEN_SIZE_HEAD  # 64
        ).transpose(1, 2)  # 1 2 维转置

        k = self.linear_k(k).view(
            n_batches,
            -1,
            self.__C.MULTI_HEAD,  # # Multi-head的数量:8
            self.__C.HIDDEN_SIZE_HEAD
        ).transpose(1, 2)

        q = self.linear_q(q).view(
            n_batches,
            -1,
            self.__C.MULTI_HEAD,  # # Multi-head的数量:8
            self.__C.HIDDEN_SIZE_HEAD
        ).transpose(1, 2)

        atted = self.att(v, k, q, mask)  # 公式计算注意力
        atted = atted.transpose(1, 2).contiguous().view(
            n_batches,
            -1,
            self.__C.HIDDEN_SIZE
        )

        atted = self.linear_merge(atted)

        return atted

用于视觉问答的深度模块化共同注意网络 《Deep Modular Co-Attention Networks for Visual Question Answering》_第19张图片
用于视觉问答的深度模块化共同注意网络 《Deep Modular Co-Attention Networks for Visual Question Answering》_第20张图片
下面来分析一下里面的代码:

  • SA的代码
class SA(nn.Module):
    def __init__(self, __C):
        super(SA, self).__init__()

        self.mhatt = MHAtt(__C)  # 多头注意力
        self.ffn = FFN(__C)  # FFN

        self.dropout1 = nn.Dropout(__C.DROPOUT_R)  # 丢弃
        self.norm1 = LayerNorm(__C.HIDDEN_SIZE)  # 规范化

        self.dropout2 = nn.Dropout(__C.DROPOUT_R)  # 丢弃
        self.norm2 = LayerNorm(__C.HIDDEN_SIZE)  # 规范化

    def forward(self, x, x_mask):
        x = self.norm1(x + self.dropout1(
            self.mhatt(x, x, x, x_mask)
        ))

        x = self.norm2(x + self.dropout2(
            self.ffn(x)
        ))

        return x
  • SGA的代码
# -------------------------------
# ---- Self Guided Attention ----
# -------------------------------

class SGA(nn.Module):
    def __init__(self, __C):
        super(SGA, self).__init__()

        self.mhatt1 = MHAtt(__C)
        self.mhatt2 = MHAtt(__C)
        self.ffn = FFN(__C)

        self.dropout1 = nn.Dropout(__C.DROPOUT_R)
        self.norm1 = LayerNorm(__C.HIDDEN_SIZE)

        self.dropout2 = nn.Dropout(__C.DROPOUT_R)
        self.norm2 = LayerNorm(__C.HIDDEN_SIZE)

        self.dropout3 = nn.Dropout(__C.DROPOUT_R)
        self.norm3 = LayerNorm(__C.HIDDEN_SIZE)

    # att(self, value, key, query, mask):
    def forward(self, x, y, x_mask, y_mask):
        x = self.norm1(x + self.dropout1(
            self.mhatt1(x, x, x, x_mask)  # 图片自注意力
        ))

        x = self.norm2(x + self.dropout2(
            self.mhatt2(y, y, x, y_mask)  # 问题-图片注意力
        ))

        x = self.norm3(x + self.dropout3(
            self.ffn(x)
        ))

        return x

(2)模块合成(Modular Composition for VQA):
用于视觉问答的深度模块化共同注意网络 《Deep Modular Co-Attention Networks for Visual Question Answering》_第21张图片
Fig 3a中,输入问题特征,通过一个identity mapping到输出特征;Fig 3b中多增加了一个SA层来进行问题模态的内部交互;Fig 3c中,增加了另一个SA层进行图像模态的内部交互。以上的三种模态并未覆盖所有的MCA组合方式,作者对其他的组合方式也进行了探究,但是并没有达到理想的效果,所以这里就不过多介绍了。

(3)深度协同注意力学习(Deep Co-Attention Learning):

问题和图像的表示(Question and Image Representations):
    图像表示是一个区域视觉特征的集合,采用自下而上(bottom-up)的方式,这些特征是用在Visual Genome数据上训练好的Faster R-CNN(里面核心是ResNet-101)。作者设置了一个置信阈值来判断是否为活动目标,且目标的数量介于[10,100],对于第i个目标,他是由卷积层进行平均池化(mean-pooling)得到的特征,记为Xi,最终就可以将图像表示为一个特征矩阵X。
问题表示是将输入的问题先划分为单词,最多为14个单词,之后再用300维的GloVe word embeddings方法(在大规模语料库上预训练而成)将每一个单词转化为一个向量。然后,词嵌入再输入一个单层的LSTM网络(有个隐藏单元)。最后输出一个问题的特征矩阵Y。

    将前面得到的图像特征X和问题特征Y作为输入,传入到一个由L个MCA层串联而成的注意力网络中进行协同注意力学习。对于MCA层,每一层的输入都是前一层的输出:
用于视觉问答的深度模块化共同注意网络 《Deep Modular Co-Attention Networks for Visual Question Answering》_第22张图片
两个深度协同注意力网络可以用下图表示:
用于视觉问答的深度模块化共同注意网络 《Deep Modular Co-Attention Networks for Visual Question Answering》_第23张图片
     stacking模型是由多个MCA层串联成的,输出的是最终的图像特征和问题特征。encoder-decoder模型思路来自于Transformer模型,编码器是由L个SA单元来学习问题特征,解码器是用SGA单元,根据问题特征来学习图像特征。
上面描述具体到代码就是下面的。

# ------------------------------------------------
# ---- MAC Layers Cascaded by Encoder-Decoder ----
# ----编码器-解码器级联的MAC层----
# ------------------------------------------------
'''
class MCA_ED(nn.Module):
    def __init__(self, __C):
        super(MCA_ED, self).__init__()

        self.enc_list = nn.ModuleList([SA(__C) for _ in range(__C.LAYER)])  # 编码器由6层SA单元组成
        self.dec_list = nn.ModuleList([SGA(__C) for _ in range(__C.LAYER)])  # 解码器由6层SGA单元组成

    def forward(self, x, y, x_mask, y_mask):
        # Get hidden vector
        # 获得隐藏层向量  att(self, value, key, query, mask)
        for enc in self.enc_list:
            x = enc(x, x_mask)  # Encoder部分 输入X输出X

        for dec in self.dec_list:
            y = dec(y, x, y_mask, x_mask)  # Decoder部分 输入X,Y输出Y

        return x, y

(4)多模态融合和分类输出(Multimodal Fusion and Output Classifier):
在这里插入图片描述
用于视觉问答的深度模块化共同注意网络 《Deep Modular Co-Attention Networks for Visual Question Answering》_第24张图片
分别获得的两种特征用线性多模态融合函数进行融合:
用于视觉问答的深度模块化共同注意网络 《Deep Modular Co-Attention Networks for Visual Question Answering》_第25张图片
    融合后的特征z用sigmoid函数映射到一个向量s中,最后loss函数用二值交叉熵(binary cross-entropy)计算N类答案的分类结果。

四、实验分析

    作者将MCAN模型用在了VQAv2数据集上,下面直接展示作者做的一些ablation study。

    首先是对于不同模块的实验:
用于视觉问答的深度模块化共同注意网络 《Deep Modular Co-Attention Networks for Visual Question Answering》_第26张图片
     然后是探究MCA层数L(1,2, 4,6)的多少对VQA准确度的的影响:
用于视觉问答的深度模块化共同注意网络 《Deep Modular Co-Attention Networks for Visual Question Answering》_第27张图片
     然后是不同阶段的注意力结果:
用于视觉问答的深度模块化共同注意网络 《Deep Modular Co-Attention Networks for Visual Question Answering》_第28张图片
     最后还有一张注意力的权重体现图:
用于视觉问答的深度模块化共同注意网络 《Deep Modular Co-Attention Networks for Visual Question Answering》_第29张图片

五、结论

用于视觉问答的深度模块化共同注意网络 《Deep Modular Co-Attention Networks for Visual Question Answering》_第30张图片
    本论文基于SA-GA单元注意力,进行深度网络框架的串联,分析方法值得借鉴。
参考:https://mp.weixin.qq.com/s/RLxWevVWHXgX-UcoxDS70w

你可能感兴趣的:(计算机视觉)