论文笔记-CNN与自然语言处理

最近在参加 AI challenge 观点型阅读理解的比赛。数据集形式如下:

最开始尝试的模型主要包括几个部分: - Embedding: 使用预训练的中文词向量。
- Encoder: 基于 Bi-GRU 对 passage,query 和 alternatives 进行编码处理。
- Attention: 用 trilinear 的方式,并 mask 之后得到相似矩阵,然后采用类似于 BiDAF 中的形式 bi-attention flow 得到 attened passage.
- contextual: 用 Bi-GRU 对 attened passage 进行编码,得到 fusion.
- match 使用 attention pooling 的方式将 fusion 和 enc_answer 转换为单个 vector. 然后使用 cosin 进行匹配计算得到最相似的答案。

目前能得到的准确率是 0.687. 距离第一名差了 0.1...其实除了换模型,能提升和改进的地方是挺多的。 - 可以用 ELMO 或 wordvec 先对训练集进行预训练得到自己的词向量。
- attention 层可以使用更丰富的方式,很多paper 中也有提到。甚至可以加上人工提取的特征。比如苏剑林 blog 中提到的。 - 还有个很重要的就是 match 部分, attention pooling 是否可以换成其他更好的方式?

但是,不断尝试各种模型的前提也要考虑速度吧。。rnn 实在是太慢了,所以决定试试 CNN 的方式来处理 NLP 的任务。

关于使用 CNN 来处理阅读理解的任务的大作还是挺多的,这里主要介绍这两篇:
- Facebook: Convolutional Sequence to Sequence Learning
- Fast Reading Comprehension with ConvNets

ConvS2S

paper: Convolutional Sequence to Sequence Learning

这篇 paper 对应的 NLP 任务是机器翻译,除了用 CNN 对 sentence 进行编码之外,其核心是在 decoder 的时候也使用 CNN. 对于阅读理解来说,能够借用的是其编码 sentence 的方式。但这里作为学习,也多了解一下 decoder 吧~

对文本来说,看到 CNN 我们首先想到的是 cnn 能有效利用局部信息,提取出局部特征,所以适合做文本分类。但是对于 机器翻译、阅读理解这样的需要考虑全局信息的任务,CNN 似乎看起来并不那么有效。而且在 decoder 的时候,词的生成是 one by one 的,下一个词的生成是依赖于上一个词的。所以在 decoder 中使用 RNN 也是很自然而然的。

Facebook 的这篇 paper 就改变了这些传统的思维,不仅用 CNN 编码全局信息,而且还能 decoder.

Motivation

Multi-layer convolutional neural networks create hierarchical representations over the input sequence in which nearby input elements interact at lower layers while distant elements interact at higher layers.
多层 CNN 具有层级表示结构,相邻的词之间在较低层的 layer 交互,距离较远的词在较高层的 layer 交互(交互的目的就是语义消歧)。

Hierarchical structure provides a shorter path to capture long-range dependencies compared to the chain structure modeled by recurrent networks, e.g. we can obtain a feature representation capturing relationships within a window of n words by applying only O(n/k) convolutional operations for kernels of width k, compared to a linear number O(n) for recurrent neural networks.
层级结构提供了一个更短的路径来获取长期依赖。比如相距为 n 的两个词,在 rnn 中交互需要的步数是 O(n),在层级 CNN 中需要 O(n/k).这样减少了非线性的操作,降低了梯度消失的情况。所以这两个词的交互效果会更好~

Inputs to a convolutional network are fed through a constant number of kernels and non-linearities, whereas recurrent networks apply up to n operations and non-linearities to the first word and only a single set of operations to the last word. Fixing the number of nonlinearities applied to the inputs also eases learning.
输入到 CNN 中每个词都会经历固定的 kernel 和 非线性操作。而输入到 RNN 的,第一个词需要经过 n 个 operations,最后一个词只经历了一个 operations. 作者认为固定的操作更容易学习。
这一点我个人认为并不一定就是合理的,本来一个句子中不同词的重要性就是不一样的。

 Model Architecture

模型分为以下几个部分:
- position embedding
- convolution block structure
- Multi-step attention

position encoding

这部分在很多地方都出现过了,在没有 rnn 的情况下,都会用 PE 来编码位置信息。但是在这篇 paper 中,作者通过实验发现,PE 作用似乎并不是很重要。

convolution blocks

作者使用的是门激活机制, GLU, gate linear units.

来自于 paper: Language modeling with gated convolutional networks
在这篇 paper 中,作者用无监督的方式,来训练语言模型,将 CNN 得到的语言模型与 LSTM 进行对比。

也就是: \[h_l=(X*W+b)\otimes \sigma(X*V+c)\]

The output of each layer is a linear projection X ∗ W + b modulated by the gates σ(X ∗ V + c). Similar to LSTMs, these gates multiply each element of the matrix X ∗W+b and control the information passed on in the hierarchy.

如果是 LSTM-style,应该是 GTU: \[h_i^l=tanh(X*W+b)\otimes \sigma(X*V+c)\]

作者将两者进行了对比,发现 GLU 效果更好。

residual connection: 为了得到更 deep 的卷积神经网络,作者增加了残差链接。

\[h_i^l=v(W^l[h_{i-k/2}^{l-1},...,h_{i+k/2}^{l-1}]+b_w^l)+h_i^{l-1}\]

卷积的整个过程:

论文中举了这样一个例子:
> For instance, stacking 6 blocks with k = 5 results in an input field of 25 elements, i.e. each output depends on 25 inputs. Non-linearities allow the networks to exploit the full input field, or to focus on fewer elements if needed.
这个怎么算的呢?看下图:

从上图中可以看到,当 k=3 时,3 个 blocks,第三层中的每一个输入都与输入中的 7 列有关。所以计算方式是 k + (k-1)* (blocks-1).

一维卷积和二维卷积的区别: - ConvS2S 是 1D 卷积,kernel 只是在时间维度上平移,且 stride 的固定 size 为1,这是因为语言不具备图像的可伸缩性,图像在均匀的进行降采样后不改变图像的特征,而一个句子间隔着取词,意思就会改变很多了。
- 在图像中一个卷积层往往有多个 filter,以获取图像不同的 pattern,但是在 ConvS2S 中,每一层只有一个 filter。一个句子进入 filter 的数据形式是 [1, n, d]. 其中 n 为句子长度, filter 对数据进行 n 方向上卷积,而 d 是词的向量维度,可以理解为 channel,与彩色图片中的 rgb 三个 channel 类似。 > Facebook 在设计时,并没有像图像中常做的那样,每一层只设置一个 filter。这样做的原因,一是为了简化模型,加速模型收敛,二是他们认为一个句子的 pattern 要较图像简单很多,通过每层设置一个 filter,逐层堆叠后便能抓到所有的 pattern. 更有可能的原因是前者。因为在 transorfmer 中,multi-head attention 多头聚焦取得了很好的效果,说明一个句子的 pattern 是有多个的.
这段话是有问题的吧? filter 的个数难道不是 2d吗? 只不过这里说的 transorfmer 的多头聚焦是值得聚焦到一个词向量中的部分维度。记得在 cs224d 中 manning 曾经讲过一个例子,经过训练或词与词之间的交互后,词向量中的部分维度发生了变化。

在 paper 中,卷积核的尺寸大小是 \(W\in R^{2d\times kd}\).

For encoder networks we ensure that the output of the convolutional layers matches the input length by padding the input at each layer. However, for decoder networks we have to take care that no future information is available to the decoder (Oord et al., 2016a). Specifically, we pad the input by k − 1 elements on both the left and right side by zero vectors, and then remove k elements from the end of the convolution output.

在 encoder 和 decoder 网络中,padding 的方式是不一样的。因为在 decoder 的时候不能考虑未来信息.
在 encoder 时,将 (k-1) pad 到左右两边,保证卷积层的长度不变。
在 decoder 中,将 (k-1) pad 到句子的左边。因此生成的词依旧是 one by one.

Multi-step Attention

\[d_i^l=W_d^lh_i^l+b_d^l+g_i\] \[a_{ij}^l=\dfrac{exp(d_i^l\cdot z_j^u)}{\sum_{t=1}^mexp(d_i^l\cdot z_j^u)}\] \[c_i^l=\sum_{j=1}^ma_{ij}^l(z_j^u+e_j)\]

上式中,l 表示 decoder 中卷积层的层数,i 表示时间步。
实际上跟 rnn 的 decoder 还是比较接近的。
- 在训练阶段是 teacher forcing, 卷积核 \(W_d^l\) 在 target sentence \(h^l\) 上移动做卷积得到 \((W_d^lh_i^l + b_d^l)\),类似与 rnn-decoder 中的隐藏状态。然后加上上一个词的 embedding \(g_i\),得到 \(d_i^l\).
- 与 encdoer 得到的 source sentence 做交互,通过 softmax 得到 attention weights \(a_{ij}^l\).
- 得到 attention vector 跟 rnn-decoder 有所不同,这里加上了 input element embedding \(e_j\).

至于这里为什么要加 \(e_j\)?
> We found adding e_j to be beneficial and it resembles key-value memory networks where the keys are the z_j^u and the values are the z^u_j + e_j (Miller et al., 2016). Encoder outputs z_j^u represent potentially large input contexts and e_j provides point information about a specific input element that is useful when making a prediction. Once c^l_i has been computed, it is simply added to the output of the corresponding decoder layer h^l_i.

\(z_j^u\) 表示更丰富的信息,而 \(e_j\) 能够能具体的指出输入中对预测有用的信息。还是谁用谁知道吧。。

关于 multi-hop attention:
> This can be seen as attention with multiple ’hops’ (Sukhbaatar et al., 2015) compared to single step attention (Bahdanau et al., 2014; Luong et al., 2015; Zhou et al., 2016; Wu et al., 2016). In particular, the attention of the first layer determines a useful source context which is then fed to the second layer that takes this information into account when computing attention etc. The decoder also has immediate access to the attention history of the k − 1 previous time steps because the conditional inputs \(c^{l-1}_{i−k}, . . . , c^{l-1}_i\) are part of \(h^{l-1}_{i-k}, . . . , h^{l-1}_i\) which are input to \(h^l_i\). This makes it easier for the model to take into account which previous inputs have been attended to already compared to recurrent nets where this information is in the recurrent state and needs to survive several non-linearities. Overall, our attention mechanism considers which words we previously attended to (Yang et al., 2016) and performs multiple attention ’hops’ per time step. In Appendix §C, we plot attention scores for a deep decoder and show that at different layers, different portions of the source are attended to.

这个跟 memory networks 中的 multi-hop 是有点类似。

FAST READING COMPREHENSION WITH CONVNETS

Gated Linear Dilated Residual Network (GLDR):
a combination of residual networks (He et al., 2016), dilated convolutions (Yu & Koltun, 2016) and gated linear units (Dauphin et al., 2017).

text understanding with dilated convolution

kernel:\(k=[k_{-l},k_{-l+1},...,k_l]\), size=\(2l+1\)
input: \(x=[x_1,x_2,...,x_n]\)
dilation: d

卷积可以表示为: \[(k*x)_ t=\sum_{i=-l}^lk_i\cdot x_{t+d\cdot i}\]

为什么要使用膨胀卷积呢? Why Dilated convolution?

Repeated dilated convolution (Yu & Koltun, 2016) increases the receptive region of ConvNet outputs exponentially with respect to the network depth, which results in drastically shortened computation paths.
能够显著缩短两个词之间的计算路径。

作者将 GLDR 和 self-attention,以及 RNN 进行了对比,input sequence length n, network width w, kernel size k, and network depth D.

model Architecture

作者与 BiDAF 和 DrQA 进行了对比,将 BiDAF 和 DrQA 中的 BiLSTM 部分替换成 GLDR Convolution.

The receptive field of this convolutional network grows exponentially with depth and soon encompasses a long sequence, essentially enabling it to capture similar long-term dependencies as an actual sequential model.
感受野的尺寸大小指数增加,能够迅速压缩 long sentence,并 capture 长期依赖。

Convolutional BiDAF. In our convolutional version of BiDAF, we replaced all bidirectional LSTMs with GLDRs . We have two 5-layer GLDRs in the contextual layer whose weights are un-tied. In the modeling layer, a 17-layer GLDR with dilation 1, 2, 4, 8, 16 in the first 5 residual blocks is used, which results in a reception region of 65 words. A 3-layer GLDR replaces the bidirectional LSTM in the output layer. For simplicity, we use same-padding and kernel size 3 for all convolutions unless specified. The hidden size of all GLDRs is 100 which is the same as the LSTMs in BiDAF.
具体网络结构,实际参数可以看 paper 实验部分。