论文笔记:分层问题-图像共注意力问答(含pytorch实现)

整理了2017 Hierarchical Question-Image Co-Attention for Visual Question Answering)论文的阅读笔记

背景

  视觉问答(VQA)的注意力模型在此之前已经有了很多工作,这种模型生成了突出显示与回答问题相关的图像区域的空间地图。在本文中,作者认为除了建模“看哪里”或视觉注意力外,建模“听什么话”或提问注意力同样重要。因此提出了一种新的VQA共注意模型。
  主要贡献:提出了一种视觉注意和问题注意共同推理的机制,与以往的作品只关注视觉注意力不同,本文的模型在图像和问题之间具有天然的对称性,即使用图像表征来引导问题注意力,使用问题表征来引导图像注意力;建立了一个层次结构,在三个层次上共同关注图像和问题:(a)词级,(b)短语级和©问题级。在单词级别,通过嵌入矩阵将单词嵌入到向量空间中。在短语级,使用一维卷积用于捕获单字母、双字母和三字母中包含的信息。
在这里插入图片描述

模型

  具体来说,本文将单词表示与不同支持度的过滤器进行卷积,然后通过将各种n-gram响应汇集到单个短语级表示中来组合它们。在问题层面,使用递归神经网络对整个问题进行编码。对于该层次结构中问题表示的每一层,构建联合问题和图像共同注意图,然后将它们递归地组合在一起,最终预测答案的分布。

问题定义

  给定一个有T个单词的问题,其表示为 Q = q 1 , . . . , q T Q=q_1,...,q_T Q=q1,...,qT,其中 q T q_T qT是第t个单词的特征向量。我们将 q t w 、 q t p 、 q t s q_t^w、q_t^p、q_t^s qtwqtpqts分别表示为t位置的词嵌入、短语嵌入和问题嵌入。图像特征用 V = v 1 , . . . , v n V=v_1,...,v_n V=v1,...,vn表示,其中 v n v_n vn为空间位置n处的特征向量。层次结构中每一层图像和问题的共同关注特征记为 v r 、 q r v^r、q^r vrqr
  对于 Q = q 1 , . . . , q T Q=q_1,...,q_T Q=q1,...,qT,首先使用词编码得到 Q = q 1 w , . . . , q T w Q=q_1^w,...,q_T^w Q=q1w,...,qTw,为了计算短语特征,我们对词嵌入向量进行一维卷积。具体地说,在每个词的位置,我们用三种窗口大小的过滤器计算词向量的内积:unigram, bigram和trigram。对于第t个单词,窗口大小为s的卷积为 q ^ s , t p = t a n h ( W c s q t : t + s − 1 w )       s ∈ { 1 , 2 , 3 } \hat q_{s,t}^p=tanh(W_c^sq_{t:t+s-1}^w) \ \ \ \ \ s\in\{1,2,3\} q^s,tp=tanh(Wcsqt:t+s1w)     s{1,2,3}  给定卷积结果,然后在每个单词位置跨不同n-gram应用最大池化以获得短语级特征 q t p = m a x ( q ^ 1 , t p , q ^ 2 , t p , q ^ 3 , t p )          t ∈ { 1 , 2 , . . . , T } q_t^p=max(\hat q_{1,t}^p,\hat q_{2,t}^p,\hat q_{3,t}^p)\ \ \ \ \ \ \ \ t \in\{1,2,...,T\} qtp=max(q^1,tp,q^2,tp,q^3,tp)        t{1,2,...,T}  使用LSTM对最大池化后的序列 q t P q_t^P qtP进行编码。对应的问题级特征 q t s q_t^s qts是时刻t的LSTM隐藏向量。

模型结构

  到这个地方,我们就得到了三个层次上的问题特征(词级,短语级和问题级),以及是使用预训练模型提取的图片的token特征,本文提出了两种共同注意机制,它们在生成图像和问题注意图的顺序上有所不同。第一种机制是平行共同注意,它同时产生图像和问题注意。第二种机制是交替共同注意,在生成图像和问题注意之间依次交替:在这里插入图片描述

平行共注意力

  该共注意力机制通过计算图像和问题在所有图像位置和问题位置对的特征之间的相似度来连接图像和问题。具体来说,给定图像特征映射 V ∈ R d × N V\in R^{d×N} VRd×N和问题表示 Q ∈ R d × N Q\in R^{d×N} QRd×N,亲和矩阵 C ∈ R T × N C \in R^{T×N} CRT×N的计算方式为: C = t a n h ( Q T W b V ) C=tanh(Q^TW_bV) C=tanh(QTWbV)  在计算这个亲和力矩阵之后,计算图像(或问题)注意力的一种可能的方法是简单地最大化其他模态位置上的亲和力,即 α v [ n ] = m a x i ( C i , n ) α^v[n]=max_i(C_{i,n}) αv[n]=maxi(Ci,n) α q [ t ] = m a x j ( C t , j ) α^q[t]=max_j(C_{t,j}) αq[t]=maxj(Ct,j)。但是作者提出了一种方法,把相似关联矩阵看成是feature, 并且学习去预测image和question的注意力图,即: H v = t a n h ( W v V + ( W q Q ) C ) H^v=tanh(W_vV+(W_qQ)C) Hv=tanh(WvV+(WqQ)C) H q = t a n h ( W q Q + ( W v V ) C T ) H^q =tanh(W_qQ+(W_vV)C^T) Hq=tanh(WqQ+(WvV)CT) α v = s o f t m a x ( w h v T ) α^v=softmax(w_{hv}^T) αv=softmax(whvT) α q = s o f t m a x ( w h q T H q ) α^q=softmax(w_{hq}^TH^q) αq=softmax(whqTHq)  其中, α v ∈ R N α^v\in R^N αvRN α q ∈ R T α^q\in R^T αqRT分别为每个图像区域vn和单词qt的注意概率,亲和矩阵C将问题注意空间转换为图像注意空间。基于上述关注权重,将图像和问题的关注向量计算为图像特征和问题特征的加权和: v ^ = ∑ n = 1 N α n v v n \hat v=\sum_{n=1}^Nα_n^vv_n v^=n=1Nαnvvn q ^ = ∑ t = 1 T α t q q t \hat q=\sum_{t=1}^Tα_t^qq_t q^=t=1Tαtqqt

交替共注意力

  在这种注意机制中,依次在生成图像和问题注意之间交替进行。简而言之,这包括三个步骤(如图2b所示):1)将问题总结为单个向量q;2)根据总结的问题特征关注图像;3)根据注意力的图像特征注意问题。
  具体地说,本文定义了一个注意操作 x ^ = A ( x : g ) \hat x=A(x:g) x^=A(x:g),以图像(或问题)特征X和来源于问题(或图像)的注意引导g为输入,输出注意力加强的图像(或问题)特征向量,即:
H = t a n h ( W x X + ( W g g ) 1 T ) H=tanh(W_xX+(W_gg)1^T) H=tanh(WxX+(Wgg)1T) α x = s o f t m a x ( w h x T H ) α^x=softmax(w_{hx}^TH) αx=softmax(whxTH) x ^ = ∑ α i x x i \hat x=\sumα_i^xx_i x^=αixxi  其中, 1 T 1^T 1T是全1矩阵的转置, α x α_x αx是对特征X的注意力权重。
  共注意力在问题特征的三个层次上进行,得到 v ^ r \hat v^r v^r q ^ r \hat q^r q^r r ∈ { w , p , s } r\in\{w,p,s\} r{w,p,s}。本文将VQA视为分类任务。根据所有三个层次的共出席图像和问题特征来预测答案。使用多层感知器(MLP)对注意力特征进行递归编码: h w = t a n h ( W w ( q ^ w + v ^ w ) ) h^w=tanh(W_w(\hat q^w+\hat v^w)) hw=tanh(Ww(q^w+v^w)) h p = t a n h ( W p [ ( q ^ p + v ^ p ) , h w ] ) h^p=tanh(W_p[(\hat q^p+\hat v^p),h^w]) hp=tanh(Wp[(q^p+v^p),hw]) h p = t a n h ( W s [ ( q ^ s + v ^ s ) , h p ] ) h^p=tanh(W_s[(\hat q^s+\hat v^s),h^p]) hp=tanh(Ws[(q^s+v^s),hp]) p = s o f t m a x ( W h h s ) p=softmax(W_hh^s) p=softmax(Whhs)其中,p是最终答案的概率。
在这里插入图片描述

实验

  在两个数据集上评估了所提出的模型:VQA数据集和COCO-QA数据集。表1是VQA数据集结果,表2是COCO-QA数据集结果。在这里插入图片描述在这里插入图片描述
  其中, O u r s p Ours^p Oursp表示平行共注意机制, O u r s α Ours^α Oursα表示交替共注意机制。
消融实验:

  1. Image Attention alone,与之前的作品类似,我们没有使用任何问题注意力。这种比较的目的是验证我们的改进不是正交贡献的结果。(比如更好的优化或更好的CNN特征)。
  2. Question Attention alone,仅进行提问注意,不进行图像注意。
  3. W/O Conv,其中不执行卷积和池化来表示短语。相反,我们在单词级输出的顶部堆叠另一个单词嵌入层。
  4. W/O W-attention,没有单词级别的共同注意。我们用均匀分布来代替单词级别的注意力。短语和问题级的共同关注仍然是建模的。
  5. W/O p-attention,其中不执行短语级别的共同注意,并且短语级别的注意设置为统一。单词和问题级的共同关注仍然被建模。
  6. W/O q-attention,不执行问题级别的共同注意。我们用均匀分布来代替问题级别的关注。单词和短语级别的共同关注仍然被建模。在这里插入图片描述

可视化

  COCO-QA数据集上的图像和问题共同关注图的可视化。从左至右:原始图像和问题对、词级共同注意图、短语级共同注意图和问题级共同注意图。在这里插入图片描述

pytorch实现

  一个比较清晰的pytorch实现版本:

import torch
import torch.nn as nn
import torch.nn.functional as fn
import torch.nn.utils.rnn as rnn
​
​
class CoattentionNet(nn.Module):
    """
    Predicts an answer to a question about an image using the Hierarchical Question-Image Co-Attention
    for Visual Question Answering (Lu et al, 2017) paper.
    """
    def __init__(self, num_embeddings, num_classes, embed_dim=512, k=30):
        super().__init__()
​
        self.embed = nn.Embedding(num_embeddings, embed_dim)
​
        self.unigram_conv = nn.Conv1d(embed_dim, embed_dim, 1, stride=1, padding=0)
        self.bigram_conv  = nn.Conv1d(embed_dim, embed_dim, 2, stride=1, padding=1, dilation=2)
        self.trigram_conv = nn.Conv1d(embed_dim, embed_dim, 3, stride=1, padding=2, dilation=2)
        self.max_pool = nn.MaxPool2d((3, 1))
        self.lstm = nn.LSTM(input_size=embed_dim, hidden_size=embed_dim, num_layers=3, dropout=0.4)
        self.tanh = nn.Tanh()
​
        self.W_b = nn.Parameter(torch.randn(embed_dim, embed_dim))
        self.W_v = nn.Parameter(torch.randn(k, embed_dim))
        self.W_q = nn.Parameter(torch.randn(k, embed_dim))
        self.w_hv = nn.Parameter(torch.randn(k, 1))
        self.w_hq = nn.Parameter(torch.randn(k, 1))#self.W_w = nn.Parameter(torch.randn(embed_dim, embed_dim))
        #self.W_p = nn.Parameter(torch.randn(embed_dim*2, embed_dim))
        #self.W_s = nn.Parameter(torch.randn(embed_dim*2, embed_dim))
​
        self.W_w = nn.Linear(embed_dim, embed_dim)
        self.W_p = nn.Linear(embed_dim*2, embed_dim)
        self.W_s = nn.Linear(embed_dim*2, embed_dim)
​
        self.fc = nn.Linear(embed_dim, num_classes)def forward(self, image, question):                    # Image: B x 512 x 196
        question, lens = rnn.pad_packed_sequence(question)
        question = question.permute(1, 0)                  # Ques : B x L
        words = self.embed(question).permute(0, 2, 1)      # Words: B x L x 512
​
        unigrams = torch.unsqueeze(self.tanh(self.unigram_conv(words)), 2) # B x 512 x L
        bigrams  = torch.unsqueeze(self.tanh(self.bigram_conv(words)), 2)  # B x 512 x L
        trigrams = torch.unsqueeze(self.tanh(self.trigram_conv(words)), 2) # B x 512 x L
        words = words.permute(0, 2, 1)
​
        phrase = torch.squeeze(self.max_pool(torch.cat((unigrams, bigrams, trigrams), 2)))
        phrase = phrase.permute(0, 2, 1)                                    # B x L x 512
​
        hidden = None
        phrase_packed = nn.utils.rnn.pack_padded_sequence(torch.transpose(phrase, 0, 1), lens)
        sentence_packed, hidden = self.lstm(phrase_packed, hidden)
        sentence, _ = rnn.pad_packed_sequence(sentence_packed)
        sentence = torch.transpose(sentence, 0, 1)                          # B x L x 512
​
        v_word, q_word = self.parallel_co_attention(image, words)
        v_phrase, q_phrase = self.parallel_co_attention(image, phrase)
        v_sent, q_sent = self.parallel_co_attention(image, sentence)#h_w = self.tanh(torch.matmul((q_word + v_word), self.W_w))
        #h_p = self.tanh(torch.matmul(torch.cat(((q_phrase + v_phrase), h_w), dim=1), self.W_p))
        #h_s = self.tanh(torch.matmul(torch.cat(((q_sent + v_sent), h_p), dim=1), self.W_s))
​
        h_w = self.tanh(self.W_w(q_word + v_word))
        h_p = self.tanh(self.W_p(torch.cat(((q_phrase + v_phrase), h_w), dim=1)))
        h_s = self.tanh(self.W_s(torch.cat(((q_sent + v_sent), h_p), dim=1)))
​
        logits = self.fc(h_s)return logits
​
    def parallel_co_attention(self, V, Q):  # V : B x 512 x 196, Q : B x L x 512
        C = torch.matmul(Q, torch.matmul(self.W_b, V)) # B x L x 196
​
        H_v = self.tanh(torch.matmul(self.W_v, V) + torch.matmul(torch.matmul(self.W_q, Q.permute(0, 2, 1)), C))                            # B x k x 196
        H_q = self.tanh(torch.matmul(self.W_q, Q.permute(0, 2, 1)) + torch.matmul(torch.matmul(self.W_v, V), C.permute(0, 2, 1)))           # B x k x L#a_v = torch.squeeze(fn.softmax(torch.matmul(torch.t(self.w_hv), H_v), dim=2)) # B x 196
        #a_q = torch.squeeze(fn.softmax(torch.matmul(torch.t(self.w_hq), H_q), dim=2)) # B x L
​
        a_v = fn.softmax(torch.matmul(torch.t(self.w_hv), H_v), dim=2) # B x 1 x 196
        a_q = fn.softmax(torch.matmul(torch.t(self.w_hq), H_q), dim=2) # B x 1 x L
​
        v = torch.squeeze(torch.matmul(a_v, V.permute(0, 2, 1))) # B x 512
        q = torch.squeeze(torch.matmul(a_q, Q))                  # B x 512return v, q
  • 43
    点赞
  • 27
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 2
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

一本糊涂张~

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值