彻底弄懂QANet


本文在翻译论文《QANET: COMBINING LOCAL CONVOLUTION WITH GLOBAL SELF-ATTENTION FOR READING COMPRE- HENSION》的同时,加入了一些自己的理解,希望可以帮助大家更好的理解这个机器阅读理解的架构。当然了,如果你真的希望深入研究机器阅读理解的话,还推荐你看一下BERT。

Abstract

当前及其阅读理解和问答领域的端到端模型主要都是基于包含Attention的循环神经网络,虽然他们取得了不错的成绩,但是他们的训练和预测方面的性能太差了。 QANet是一种问答问答架构,他不需要循环网络构成,而是仅由CNN和self-Attention组成。CNN对于局部信息进行捕获,Self-Attention对全局信息进行捕获。
在SQuAD 1.1中,训练速度提高了3~13倍,预测速度提高了4~9倍,同时我们的精度可以与循环模型相媲美,高效率使得我们可以使用更多的数据进行训练,我们利用神经翻译网络进行了数据增强,使得F1打到84.6,显著高于之前公布的最优值81.8

Introduction

阅读理解和问答吸引了越来越多的注意力,在过去的几年中,端对端模型在这些领域做出了许多充满希望的突破,成功的模型通常采用了两种技术:

  1. 循环模型来处理序列输入
  2. 用Attention机制进行长距离信息交互

BiDAF双向注意力流模型将这两项要素成功地结合在了一起,该模型在SQuAD数据集上取得了显著的效果。这些模型的一个缺点是,它们的循环特性使得它们在训练和推理方面的效率通常较低,特别是对于长文本而言。昂贵的训练不仅会导致实验的周期延长,限制研究人员进行快速迭代,还会使模型难以被用于更大的数据集中。与此同时,缓慢的推理速度阻碍了机器理解系统在实时应用中的部署。

在本文中,为了提高速度,我们的目标是去除这些循环特性,作为替代,我们仅仅使用卷积和self-attention组成编码块。首先分开编码context和query,然后使用standard attention学习这两个编码块之间的联系,将经过attention的向量再次经过我们的编码块编码,最后解码计算出每一个位置是answer的开头和结尾的概率。

我们设计这个架构的主要动机如下:卷积捕获文本的局部结构,而自注意力则学习每对单词之间的全局交互。额外的context-query attention模块是一个标准模块,用来构建一个感知问题的语境向量,在接下来的model中会用到我们的架构的前馈特性极大地提高了模型的效率。在基于SQuAD数据集的实验中,我们模型的训练速度提高了3至13倍,推理速度提高了4至9倍。作一个简单的比较,我们的模型可以在3个小时的训练中达到与BiDAF模型(Seo等人于2016年提出)相同的精确度(F1值为77.0),在此之前,这一过程需花费15个小时的时间。加速增益还允许我们使用更多的迭代来训练模型,以获得比竞争模型更好的结果。例如,如果我们允许我们的模型进行18个小时的训练,它在开发集(dev set)上的F1值达到了82.7,这比Seo等人于 2016年提出的模型,表现得要好很多,并且与已发布过的最佳结果相媲美。

Model

3.1 description

给定有n个词的Context,C = \( \{c_1, c_2, ..., c_n\} \) ,m个词的Query,Q =\( \{q_1, q_2, ..., q_m\} \),输出一个Span集,S =\( \{c_i, c_{i+1}, ..., c_{i+j} \} \),Span的含义是从Context中抽取一段连续的片段作为答案。在接下来的文章中使用x代表输入的词向量,即x ∈ C, Q

3.2 structure

模型主要分为5个部分,可用图1表示:

  • an embedding layer
  • an embedding encoder layer
  • a context-query attention layer
  • a model encoder layer
  • an output layer

3.3 Input Embedding Layer

采用word embedding + char embedding的方式。 word embedding 用的是300维度的Glove预训练好的,在训练的时候设置为trainable进行fix。
所有不在词典中的词用代替,是随机初始化的,在训练过程中训练。 char embedding使用200维度的随机初始化向量,在训练中训练,每个词限制有16个char,超过截断,不足padding。这样每个单词会得到一个200*16的矩阵,取这个矩阵每一行的最大值(经过一个max-pooling),就可以得到一个fixed-size=200的向量代表每一个单词。
word-embedding和char-embedding的拼接方式:在word的结尾直接拼接上char的,即300+200=500维度的一个向量。将这个500维度的向量通过一个highway网络,就是Input embedding layer层的输出。

ps1:highway network

HighWay网络主要用于解决深层网络难以训练的问题。
假设一层普通的深度网络的输入是x,这层网络使用了一个非线性函数\( H \),参数是\( W_h \),网络的输出是\( y \),可以表示成: \[ y = H(x,W_h) \] 对于Highway来说,额外定义两个非线性函数:\( T(x,W_t) \)和\( C(x,W_c) \),其中T是transform gate(变换门),C是carry gate(携带门)。现在表示成: \[ y = H(x,W_h) \cdot T(x,W_t) + x \cdot C(x,W_c) \] T意味着y有多少信息是x变换而来的,C意味着y有多少信息是不经变换直接携带过来的。通常令C=1-T

3.4 Embedding Encoder Layer

这部分只用到了一个encoder block,这个block的构造如下图2所示:

其实就是图1的右半部分。Block主要包含:[convolution-layer × K + self-attention-layer + feed-forward-layer],假设每一部分的输入是x,处理函数为f,那么每一部分的输出可以表示为: \[ f(layernorm(x))+x \] 这里使用了残差思想和Layer Normalization。其中残差的思想也是为了解决网络过深不好训练的问题,对于普通网络,任意堆叠的两层网络,我们希望找到的是一个映射H(x)对应的残差元,我们添加一个快捷连接,从输入到输出,这里的快捷连接默认为恒等映射,此时的问题就从寻找映射H(x)到F(x);这里类似于在数学上,你直接去解一个方程较为复杂,你就把它分解成两个简单问题和的形式,分别去解决。对应于残差的初始定义,在统计学中,为实际观测值与估计值(拟合值)的差值,这里则是直接的映射H(x)与快捷连接x的差值。 在Embedding Encoder Layer层中,K=4,即使用了4层conv,但是需要注意的是这不是普通的卷积层而是depthwise separable convolutions。

ps2:残差网络

彻底弄懂残差网络Residual Network

ps3: depth-wise separable convolutions(深度可分离卷积)


深度可分离卷积跟传统卷积操作相比,就是其过程是可以分离成两大部分的:

  • 第一步:假设原来的卷积核是33N的,那么深度可分离卷积就先用N个3*3的卷积核一对一卷积输入的N个feature Map,不求和,生成了N个结果
  • 第二步:用11N的卷积核卷积前面的N个结果即可

ps4: position encoding

当前模型跟循环网络的序列模型相比,最大的不足之处就是不能把序列的位置信息编码进去。对于当前结构来说,调整句子的顺序,对结果完全没有影响,但是我们知道,对于NLP来说,序列的顺序是极为重要的信息。为了弥补这个不足,Google提出了position embedding的方法,这其实是一组公式,之前的主流做法是随机初始化一个位置向量,然后通过训练去得到位置向量,但是谷歌的大量实验告诉我们,这组公式算出来的向量跟训练出来的向量效果相似,因此使用公式直接计算显然能减少开销。 \[ PE_{(pos,2i)} = sin(\frac{pos}{10000^{\frac{2i}{d_{model}}}}) \] \[ PE_{(pos,2i+1)} = cos(\frac{pos}{10000^{\frac{2i}{d_{model}}}}) \] 使用cos和sin的原因是: \[ sin(\alpha + \beta) = sin\alpha cos \beta + cos\alpha sin\beta \] \[ cos(\alpha + \beta) = cos\alpha cos\beta - sin\alpha sin\beta \] 这表明a+b的位置可以有a和b的变换得到,从而能表达相对位置的信息。

ps5: self-attention

一文读懂「Attention is All You Need」| 附代码实现

3.5 Context-Query Attention Layer

首先计算Context和Query的相似度,相似度结果用矩阵S表示,计算公式为: \[ S_{tj} = \alpha (H_{:t},U_{:j}) \] \[ \alpha (H_{:t},U_{:j}) = w^T _S(h,u,h \bigodot u) \] 其中H是含有t个word的context矩阵,一般来说是上游layer传递下来的矩阵,可能是encoder之后的,可能是embedding之后的,在这里就是3.4 encoder传递下来的context矩阵,U是还有J个word的Query矩阵,a是一个可训练的函数,这个函数里面的w是一个可训练的权值,\( \bigodot \)是element-wise multiplication

ps6: element-wise multiplication

两个矩阵对应元素的乘积,假如 \[ a=[1,2,3]\] \[ b = [4,5,6] \] 那么\( a \bigodot b = [4,10,18] \)

综上,我们用f表示求相似度矩阵的操作: \[ f(q,c) = W_0[q,c,q\bigodot c] \] 那么context-to-query的attention这样计算: \[ A = \overline{S} \cdot Q^T \in R^{nxd} \] 其中\( \overline{S} \)是对S的每一行用softmax进行归一化后的矩阵。query-to-context的attention计算如下: \[ B = \overline{S} \cdot \overline{\overline{S}^T} \cdot C^T \] 其中\( \overline{\overline{S}} \)是对S的每一列进行归一化后的矩阵

3.6 Model Encoder Layer

在每一个位置的输入是:\( [c,a,c\bigodot a,c\bigodot b] \),c是context的矩阵,a和b分别对应3.5中的矩阵A和B的一行,然后通过3个model encoder block,只不过这里block里面是卷积层数为2的7个encoder block拼接成的

3.7 Output Layer

分别预测每个位置是answer span的起始点和结束点的概率,分别记为p1、p2,计算公式如下: \[ p^1 = softmax(W_1[M_0;M_1]) \] \[ p^2 = softmax(W_2[M_0;M_2]) \] 其中\( W _1 \) 、\( W_2\)是两个可训练变量,\( M_0 \) 、\( M_1\)、\( M_2 \)分别对应图1中三个model encoder block(自底向上)

最终的目标函数是: \[ L(\theta) = -\frac{1}{N} \sum_i ^N [log(p^1 _{y^1 _i}) + log(p^2 _{y^2 _i})] \] 其中\( y^1 _i \)、\( y^2 _i \)分别为第i个样本的groudtruth的起始位置和结束位置。

Reference

1.《QANET: COMBINING LOCAL CONVOLUTION WITH GLOBAL SELF-ATTENTION FOR READING COMPRE- HENSION》
2. https://blog.csdn.net/qq34499130/article/details/80282999
3. https://blog.csdn.net/qq
30478885/article/details/78828734
4. https://kexue.fm/archives/4765
5. https://yq.aliyun.com/articles/342508?utmcontent=m39938
6. 《Attention Is All You Need》


分享博文


评论博文


Next article :   彻底弄懂残差网络Residual Network