QANet: Combining Local Convolution With Global Self-Attention For Reading Comprehension

Posted AI蜗牛之家

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了QANet: Combining Local Convolution With Global Self-Attention For Reading Comprehension相关的知识,希望对你有一定的参考价值。

文章目录

博主标记版paper下载地址:zsweet github
关于paper,在进入正题之前先吐槽一下,论文中说的所有矩阵都是按照tensorflow源码中的形势,所以row和column的在读论文时自己切换一下。。。

1.概述

过去几年中最成功的模型通常采用了两项关键要技术:

  • 处理顺序输入的循环模型
  • 应对长期交互的注意力要素。

Seo等人于2016年提出的的双向注意力流(Bidirectional Attention Flow,BiDAF)模型将这两项要素成功地结合在了一起,该模型在SQuAD数据集上取得了显著的效果。这些模型的一个缺点是,它们的循环特性使得它们在训练和推理方面的效率通常较低,特别是对于长文本而言。

QAnet模型设计的主要思想:卷积捕获文本的局部结构,而自注意力则学习每对单词之间的全局交互。附加语境疑问注意力(the additional context-query attention)是一个标准模块,用于为语境段落中的每个位置构造查询感知的语境向量(query-aware context vector),这在随后的建模层中得到使用。

CMU 和 Google Brain 新出的文章,SQuAD 目前的并列第一,两大特点:

  • 模型方面创新的用 CNN+attention 来完成阅读理解任务
    在编码层放弃了 RNN,只采用 CNN 和 self-attention。CNN 捕捉文本的局部结构信息( local interactions),self-attention 捕捉全局关系( global interactions),在没有牺牲准确率的情况下,加速了训练(训练速度提升了 3x-13x,预测速度提升 4x-9x)
  • 数据增强方面通过神经翻译模型(把英语翻译成外语(德语/法语)再翻译回英语)的方式来扩充训练语料,增加文本多样性

现在越来越觉得CNN、capsule、transformer相关非NLP技术在NLP领域的强大,以后多尝试在模型上使用这些结构!

2.模型结构

模型由五层结构组成:

  • input embedding layer
  • embedding encoder layer
  • context-query attention layer
  • model encoder layer
  • output layer

图2-1.模型结构

2.1.Input embedding layer

Input embedding layer和BIDAF一模一样
具体顺序是:

  • 英文字母随机初始化每个字母的char-embedding(当然对中文的char-embedding最好是pretrain的),并对query和context进行lookup
  • 对query和context的char-embedding过CNN,提取每个字之间的特征;
  • 对query和context的pretrain的word-embedding进行lookup
  • word-embedding和char-embedding进行concatenation
  • 对concat的向量过两层highway,提取并保留原来的特征。(关于highway可参考博客highway netword

word embedding+character embedding,word embedding从预先训练好的词向量中读取,每个词向量维度为 p 1 p_1 p1假设词w对应的词向量为 x w x_w xw
character embedding随机初始化,维度为 p 2 p_2 p2,将每个词的长度padding or truncating到 k k k,则词w也可以表示成一个 p 2 ∗ k p_2*k p2k的矩阵,经过卷积和max-pooling后得到一个 p 2 p_2 p2维的character-level的词向量,记为 x c x_c xc
  将 x w x_w xw​和 x c x_c xc​拼接,得到词w对应词向量 [ x w ; x c ] ∈ R p 1 + p 2 [x_w;x_c]\\inR^p_1+p_2 [xw;xc]Rp1+p2​,最后将拼接的词向量通过一个两层的highway network,其输出即为embedding层的输出。训练过程中,word embedding固定,character embedding随模型一起训练。

2.2 Embedding Encoder Layer

重点是这一层上的改变,由一个stacked model encoder block而成(这部分只用了1个stacked model encoder block且里面只有一个encoder block,每个encoder block里面4个卷积层,每个卷积层的filter number是128、高度是7),每个 block 的结构是:[convolution-layer x # + self-attention-layer + feed-forward-layer]

单个block结构自底向上依次包含位置编码(position encoding)卷积(conv)层self attention层前馈网络(fnn)层,具体参考图下图:

图2-2-1.Encoder block
每个基本操作(conv/self-attention/ffn)都放在残差块(residual block)里,具体各层参数参考原论文。原论文对这里卷积层和self-attention层的作用解释是: 卷积能够捕获上下文局部结构,而self-attention则可以捕捉文本之间全局的互作用

这里出去CNN之外,几乎照搬的是transformer,关于transformer可以查看我之前的文章:paper:Attention Is All You Need(模型篇) ,那接下来说下这里的CNN部分,卷积用的 separable convolutions 而不是传统的 convolution,因为更加 memory efficient,泛化能力也更强。核心思想是将一个完整的卷积运算分解为 Depthwise ConvolutionPointwise Convolution 两步进行,两幅图简单过一下概念:

  • 先做 depthwise conv, 卷积在二维平面进行,filter 数量等于上一次的 depth/channel,相当于对输入的每个 channel 独立进行卷积运算,然后就结束了,这里没有 ReLU
    假设输入是 64 ∗ 64 64*64 6464的3通道图片,使用 3 ∗ 3 ∗ 1 3*3*1 331大小的卷积核,filter 数量等于上一层的depth,对输入的每个 channel 独立进行卷积运算,得到与上层depth相同个数的feature map。对应到图里即3个filter分别对3个channel进行卷积,得到3个feature map。如下图:
图2-2-2.depthwise conv
- 然后是pointwise convolution,和常规卷积运算类似,卷积核的尺寸为 1×1×M,M等于上一层的depth。它会将上一步的feature map在深度方向上进行加权组合,生成新的feature map,有几个filter就有几个feature map。如图3所示,输入depth为3,卷积核大小为$1*1*3$,使用4个filter,最终生成4个feature map。

图2-2-2.pointwise convolution

动画见https://www.slideshare.net/DongWonShin4/depthwise-separable-convolution

编者按:
如果看过capsule的童鞋,应该还记得capsule是cnn的一个升级,所以在这里我也在想,如果把这里面的cnn替换成capsule会不会有奇效。之后有时间尝试

2.3.Context-Query Attention Layer

几乎所有 machine reading comprehension 模型都会有,而这里依旧用了 context-to-query 以及 query-to-context 两个方向的 attention:

  • 先计算相关性矩阵,
  • 再归一化计算 attention 分数,
  • 最后与原始矩阵相乘得到修正的向量矩阵。

这里的attention步骤和BIDAF也有点像,context-to-query完全相同,但是在query-to-context的时候稍有不同。

根据上一层得到的context和query的encoder表示来计算context-to-query attention和query-to-context attention矩阵。分别用C和Q来表示编码后的context和query, C ∈ R n ∗ d C \\in R^n*d CRnd Q ∈ R m ∗ d Q \\in R^m*d QRmd。则步骤如下:

  • 首先计算context和query单词之间的相似度,结果矩阵记为S, S ∈ R n × m S\\inR^n×m SRn×m。其中相似度计算公式为: f ( q , c ) = W 0 [ q , c , q ⊙ c ] f(q,c)=W_0[q,c,q⊙c] f(q,c)=W0[q,c,qc]
    其中:q、c分别为单个单词的中间表示, W 0 W_0 W0是一个可训练的参数。
  • 用softmax对S的行、列分别做归一化得到 S ˉ \\barS Sˉ S ˉ ˉ \\bar\\barS Sˉˉ,则 context-to-query attention矩阵A= S ˉ ⋅ Q T ∈ R n ∗ d \\barS·Q^T \\in R^n*d SˉQTRnd,query-to-context attention矩阵B= S ˉ ⋅ S ˉ ˉ T ⋅ C T ∈ R n ∗ d \\barS·\\bar\\barS^T·C^T \\in R^n*d SˉSˉˉTCTRnd(参考DCN模型)。

2.4.Model Encoder Layer

和 BiDAF 差不多,不过这里依旧用 CNN 而不是 RNN。这一层的每个位置的输入是 [c, a, c⊙a, c⊙b],a, b 是 attention 矩阵 A,B 的行,参数和embedding encoder layer大致相同,但是cnn 层数不一样,这里是每个 block 2 层卷积,一共7个block,并且一共用了3个这样的组合stack,并且这三个stack共享参数
更易懂地说,这里的Model Encoder Layer包含三个stacked model encoder blocks,每个stack model encoder blocks包含7个block,每个block的结构如图2-1,而每个block内部包含2个cnn卷积(也就是[convolution-layer x # + self-attention-layer + feed-forward-layer]里面的#=2)。

2.5 Output layer

分别预测每个位置是answer span的起始点和结束点的概率,分别记为 p 1 p^1 p1 p 2 p^2 p2,计算公式如下:
p 1 = s o f t m a x ( W 1 [ M 0 ; M 1 ] ) p^1=softmax(W_1[M_0;M_1]) p1=softmax(W1[M0;M1])
p 2 = s o f t m a x ( W 2 [ M 0 ; M 2 ] ) p^2=softmax(W_2[M_0;M_2]) p2=softmax(W2[M0;M2])

其中 W 1 W_1 W1 W 2 W_2 W2是两个可训练变量, M 0 M_0 M0 M 1 M_1 M1 M 2 M_2 M2依次对应结构图中三个model encoder block的输出(自底向上)。
目标函数:
L ( θ ) = − 1 N ∑ i N [ l o g ( p y i 1 1 ) + l o g ( p y i 2 2 ) ] L(θ)=-\\frac1N\\sum_i^N[log(p_y_i^1^1)+log(p_y_i^2^2)] L(θ)=N1iN[log(pyi11)+log(pyi22)]
其中 y i 1 y_i^1 ytypescript combining_events.ts

[RxJS] Combining Streams with CombineLatest

jieba plus(synonyms combining)

CodeForces 618A Slime Combining

Write Combining Buffer

[RxJS] Replace zip with combineLatest when combining sources of data