QANet: Combine Local Convolution with Global Self-Attention for Reading Comprehension
简要信息:
序号 | 属性 | 值 |
---|---|---|
1 | 模型名称 | QANet |
2 | 所属领域 | 问答系统,自然语言处理 |
3 | 研究内容 | 机器阅读理解 |
4 | 核心内容 | self-attention; layer-normalization; CNN |
5 | GitHub源码 | https://github.com/search?q=QANet |
6 | 论文PDF | https://arxiv.org/pdf/1804.09541.pdf |
动机:
现如今引入端到端的方法用于解决文本问答(机器阅读理解)问题受益于成功地使用了循环神经网络和注意力机制。例如BiDAF
但缺点是其在训练时处理长文本时速度慢,不利于快速迭代、不适用大规模数据集,不利于实时反馈等。为了缓解这个问题,本文去除掉循环神经网络架构,替换为卷积网络和self-attention;
贡献和优势:
(1)我们的方法只需要训练3个小时,就可以达到和BiDAF训练15个小时一样的F1值。如果我们的方法继续训练到18小时,F1值则达到82.7;
(2)使用数据增强来提升模型效果。将英文语料翻译为其他语言再重新翻译回英文;
模型结构:
Input Embedding Layer
输入长度为
n
n
n 的context
C
C
C和长度为
m
m
m 的query
Q
Q
Q。使用300维度的GloVe预训练词向量,训练时固定不变。未登录词使用UNK表示并随机初始化;
字符embedding维度为200,最大字符数量为16,直接拼接起来形成字符矩阵,按行进行最大池化生成固定的200维度词表示,最后向量为字符向量和词向量拼接起来形成500维度的输入。输出部分则使用两层的highway network。
Embedding Encoder Layer
包括卷积层,自注意力层和前馈网络层(如上图右侧)
-
卷积层为深度可分离卷积网络(Depthwise Separable Convolutions),相比传统的卷积具有更好的记忆和泛化性能。卷积核大小为7,数量为128,每个encoder block包含4层卷积;
-
自注意力层为多头注意力机制,头数为8,自注意力公式为:
- 前馈网络层:采用一层全连接层
每个卷积层、自注意力层和前馈层之间均采用残差连接法和layernorm
残差连接: 某一层的输入为
x
x
x ,该层的函数为
f
f
f 该层的输出则为
x
+
f
(
l
a
y
e
r
n
o
r
m
(
x
)
)
x + f(layernorm(x))
x+f(layernorm(x)) 。
LayerNorm: 在一组batch中,对每个样本分别按照特征进行归一化,均值向量和标准差向量的维度变换为 [batch_size, feature_size] -> [batch_size],如下图。最终原始矩阵归一化后的维度为[batch_size, feature_size]。
LN与BN的区别 :BN是按照batch维度进行归一化的,即同一个特征对所有样本进行归一化,均值向量和标准差向量维度变换为 [batch_size, feature_size] -> [feature_size]。而LN则是按照特征维度进行归一化的。
参考:layer normalization讲解(及其与Batch Normal区别)https://zhuanlan.zhihu.com/p/54530247
在Encoder部分,对应Question和Context,分别只有一个block,输出的维度则是128;
Context-Query Attention Layer
- context-to-query: query的每个token与context进行相似度计算,相似度函数为 f ( q , c ) = W 0 [ q , c , q ⊙ c ] f(q,c) = W_0[q,c,q\odot c] f(q,c)=W0[q,c,q⊙c],相似度矩阵 S ∈ R n × m S\in R^{n\times m} S∈Rn×m,按行归一化后表示为 S r ∈ R n × m S_r\in R^{n\times m} Sr∈Rn×m 。context-to-query attention为 ( d d d 为特征维度):
A = S r Q T ∈ R n × d A=S_rQ^T\in R^{n\times d} A=SrQT∈Rn×d
- query-to-context: 表示每个context的token与query的注意力。对上面产生的相似度矩阵 S S S 按列归一化得到 S l ∈ R n × m S_l\in R^{n\times m} Sl∈Rn×m,query-to-context attention为
B = S l S r T C T ∈ R n × d B = S_l S_r^T C^T\in R^{n\times d} B=SlSrTCT∈Rn×d
Model Encoder Layer
如上图,一共有3层model encoder。每个输入为 [ c , a , c ⊙ a , c ⊙ b ] [c,a,c\odot a, c\odot b] [c,a,c⊙a,c⊙b],使用7个Embedding Encoder Block,每个block的卷积层为2,每参数均共享。3个model encoder参数共享;
Output Layer
输出部分则为start和end的概率分布,公式为:
损失函数为:
说明:预测的start和end的概率分布中,取出ground truth位置的预测概率。最小化损失函数,即最大化ground truth位置的预测概率。在pytorch中可以写为:
# 输入start和end的预测概率分布,维度为 [batch_size, 2, max_len]
ap = ...
# ground truth位置,维度为 [batch_size, 2]
y = use_cuda(torch.from_numpy(np.array(y)))
# 根据ground truth 的start和end位置,取出预测的概率值
prob = torch.gather(ap, -1, y.unsqueeze(-1)).squeeze() # [batch_size, 2]
# loss函数,1e-10为了防止出现log(0)。
loss = -torch.mean(torch.sum(torch.log(prob + 1e-10), -1))
在推理阶段,预测的start和end位置可以取最大的 p s 1 p e 2 p_s^1p_e^2 ps1pe2(两个概率的乘积值, s ≤ e s\leq e s≤e),使用动态规划查询。
实验效果如图所示: