利用双向注意流进行机器理解
本文基于Bi-Directional Attention Flow For Machine Comprehension一文
1. 概述
Machine Comprehension也就是机器理解, 简记为MC, 针对给定的一个上下文, 回答一个问题, 这需要我们对复杂的交互过程进行建模, 近来, 注意力机制(Attention Mechanisms)成功对MC作出了扩展, 特别是使用注意力机制来关注上下文并且最后生成一个固定大小的向量。 在该篇文章中, 介绍了BIDAF(双向注意流)网络, 一个多阶段层次化的过程, 可以将上下文表现于不同的粒度之上, 使用双向注意流来获取一个问题-察觉(query-aware)的上下文的表示方法, 而不是过早的对上下文进行概要
2. 介绍
近年来, MC和QA(问题回答)的关注程度逐渐增强, 特别是NLP(自然语言处理)和计算机视觉, 端到端训练的系统在对于文本和图像的多种任务中表现出色, 其中一个重要的因素就是使用了注意力机制, 该种技术可以使得系统关注于一个目标区域于上下文段落中, 或者是一张图片中(特别是视觉问答领域), 这里我们给出注意力机制的一些特性:
- 计算好的注意力权重通常被用来从上下文向量中抽取最为相关的信息, 上下文向量是通过某种归纳映射得到的固定大小的向量。
- 文本领域中, 整个注意力机制是暂时性的, 动态化的, 当前时间步的注意力权值是之前时间步注意力的一个映射结果
- 整个机制通常是单向的
这篇文章中主要介绍了双向注意流网络(BIDAF network), 一种层次化的多阶段的结构, 在不同粒度等级上对上下文进行建模, BIDAF主要包括对字符粒度等级(Character Level)和词粒度水平(Word Level), 并且使用双向注意流来获取问题-察觉的上下文的表示方法。
提出来的新的注意力机制对于之前热门的注意力机制有以下几点提升:
- 我们的注意力层并不用于将上下文映射到一个固定大小的向量, 反而是, 注意力在每一个时间步都会计算, 以及每一个时间步的伴随向量(Attend Vector)连同着先前层的表示, 都被允许流向后来的模型层, 这样的方法就减少了过早将上下文映射成固定大小的向量所带来的误差。
- 使用少内存(Memory-less)的注意力机制, 即, 我们每一次迭代计算的时候, 每一个时间步的注意力仅是当前问题和上下文的一个函数得出的结果, 并不直接依赖于先前时间步的注意力, 我们猜想这种简化可以减轻注意力层(attention layer)到模型层(model layer)的计算负载, 使得注意力层关注于学习问题和上下文之间的注意力, 这同时使得模型层可以从问题-察觉的上下文表达(实质上是注意力层的输出)中学习到某种复杂的交互逻辑。
- 使用双向注意力机制, 能够产生更为完整的信息。
3. 关于模型
整个机器理解模型是一个层次化多阶段的过程, 包括以下六个层次:
- 字符嵌入层(Character embedding layer)
其主要作用是将词映射到一个固定大小的向量, 这里我们使用字符水平的卷积神经网络(Character level CNN), 该网络由Kim在2014年提出, 我们后续会对部分细节进行补充。 - 词嵌入层(Word embedding layer)
这里是使用预先训练的词嵌入模型, 将每一个词映射到固定大小的向量。 - 上下文嵌入层(Contextual embedding layer)
主要作用是给每一个词加一个上下文的线索(cue), 前三层都是对问题和上下文进行应用 - 注意流层(Attention flow layer)
这里是组合问题和上下文的向量, 生成一个问题-察觉的特征向量集合。 - 模型层(Modeling layer)
本文是使用循环神经网络(RNN)来对上下文进行扫描 - 输出层(Output layer)
该层提供对问题的回答
这里我们给出相应的层次结构图
[图片上传失败...(image-68105-1553264153682)]
我们来继续讨论其中每一层更多的细节
3.1 字符嵌入层
字符嵌入层的作用主要在于将一个词映射到高维的向量空间之中,我们令 和 代表上下文的词集合和问题的词集合, 这两者都是有序的, 利用Kim的字符水平的CNN方法, 我们可以获得对应的字符水平的嵌入向量, 多个字符被嵌入成一个向量, 理解成CNN的一维输入, 大小和CNN输入的大小一致, CNN的输出被max-pool, 最终得到一个固定长度的向量。
我们有必要对Kim这个方法进行介绍
3.1.1 关于字符水平的CNN方法
我们首先给出Kim论文中的整套网络结构图, Kim是使用这套结构做文本分类的
[图片上传失败...(image-678fe1-1553264153682)]
输入一共有n个词, 每一个词都是k维的词向量, 这里我们记, 其中是向量的连接操作, CNN的卷积操作就是利用一个过滤器 , 实际上就是利用一个h大小的窗口来进行移动, 如上图所示, 红色窗口就是h=2的一个窗口, 从上到下对所有的词进行扫描, 这里我们给出计算方法:
向量c对应着上图的第二部分的一个长条, , 函数是一个非线性函数, 类似于双曲正切瀚函数tanh。
接下去我们就可以根据多个窗口大小来构造一系列的特征向量, 如上图所示, 接着就是经过Max-over-time pooling, 生成一个一维向量, 向量的大小等于不同窗口的个数。
关于Max-over-time pooling
该方法是Collobert在2011年提出来的, 原理十分简单, 就是取特征向量的最大值
目的就是获取最大的特征值于特征向量之中
整个pooling的做法目的其实有一部分是为了将变长的输入变成定长, 我规定有几个窗口, 最后就会得到几维的向量。
最后将最大池化后的向量结构全连接到一个层上, 加上dropout, 然后softmax输出, 最后得到文本所属不同类别的概率。
回到这篇文章中来, 我们使用kim的方法就可以将变长文本输入, 转变为一个定长的向量了!
3.2 词嵌入层
词嵌入层和字符嵌入层一样, 都是将词映射到一个高维的特征向量的空间, 这里我们使用预先训练好的词向量(采用GloVe), 来获得定长的词嵌入向量(和字符嵌入层的作用基本相同, 将变长的文本转换成定长的向量),这里最为关键的点就是Pennington在2014年提出来的GloVe, 一种词向量的表示方法。
3.2.1 关于GloVe
GloVe全称为Global Vector For Word Representation, 该方法结合了全局矩阵分解方法(global matrix factorization)以及局部上下文窗口方法(local context window)的优点, 我们来仔细说明一下该方法
首先我们需要定义一些符号:
- 词到词的协出现矩阵
其中对于每一个元素, 表示词在词的上下文中出现的次数 - 单个词的元素
我们定义, 表示所有词在词的上下文中出现的次数 - 概率
我们定义概率, 代表词出现在词的上下文的概率
举一个例子吧, 我们现在对句子进行分词, 得到了ice(冰)和steam(蒸汽)两个词, 然后我们计算一下概率, 比如在这两个词的上下文中, 某个词k = solid(固体)等出现的概率, 使用大量的数据来进行计算, 我们得到
[图片上传失败...(image-faa887-1553264153682)]
可以看出来, 如果的值远大于1, 则趋于ice的上下文, 远小于1则是更趋向于steam的上下文, 可以看到gas更趋向于steam, 而solid更趋于在ice的上下文中出现。
通过这个方法, 我们利用gas和solid比起利用water和fashion更加可以区分开ice和steam了, 进而我们可以构造出一个更具有区别性的词向量。
给出一个更加一般的模型:
其中是一个d维的词向量, 而是一个d维的分离上下文词向量(separate context word vector), 等式的右端是通过语料库进行抽取的, F可能依赖于某种未确定的参数, 但是F这样的概率值太多了, 我们这里给出一种选择方案:
- 我们希望F能够表达P的概率比值于词向量空间, 由于词向量是线性结构, 故考虑向量的差, 记
- F可能使用复杂的函数作为参数, 比如神经网络, 这样会使整个线性结构变得复杂, 我们作出以下修改
- 进一步修改
其中 - 令F是指数函数, 得
- 加上偏置, 由于实际和k无关, 在偏置的吸收下, 得到
- 给出代价函数, 使用加权最小二乘回归模型解决
这里需要对作出部分限定
a.
b. 是非递减的函数
c. 对于较大的x, 应该呈现较小的函数值
给出函数定义:
3.2.2 向量拼接输入
通过两个过程我们可以的得到, 字符水平的嵌入以及词水平的嵌入。利用Sirivastava在2015年的时候提出来的双层高速网络, 得到d维度的向量, 相当于得到两个矩阵, , 我们之前得到T维和J维的词序列的每一个词都被转换成d维的向量。
3.3 上下文嵌入层
利用1997年Sepp Hochreiter 和 Jurgen Schmidhuber提出来的长短时记忆单元(LSTM)网络, 我们将LSTM双向放置, 并将输出连接起来, 有两个矩阵, 之所以是2d是因为LSTM是双向的, 对应位置是有两个输出的
3.4 注意流层
注意流层的作用在于在问题和上下文之间连接和熔断, 和先前其他的注意力机制不一样, 并不是直接利用上下文和问题直接组成特征向量, 反而是, 每一个时间步的注意力向量, 以及先前层的嵌入向量, 被允许流向模型层, 降低了过早组合成特征向量所造成的误差。
该层的输出也就是关于上下文的问题-察觉向量表示, 以及先前层的上下文嵌入向量。
在这一层, 引入共享的相似度矩阵S,S的大小是T乘以J,其中, 代表上下文的第t个词和问题的第j个词的相似度, 是一个可训练的函数, 计算出H的t列和U的j列之间的相似度。
定义, 其中w是一个6d维度的可训练的权值向量, 就是对应元素乘积
我们通过两个方向进行计算注意力向量以及伴随向量:
3.4.1 从上下文到问题
上下文到问题的注意力, 对于每一个上下文词特别相关, 我们定义一个J维度的向量来表示, 上下文的第t个词对问题的注意力权值, 注意到, 其中有, 由此我们可以定义伴随向量
很容易理解, 也就是拿对应context的相似度向量(也就是S的第t行)做softmax操作, 是一个2d乘T的矩阵
3.4.2 从问题到上下文
从问题到上下文的注意力, 也就是当上下文的词和问题的某个词相似度最高, 那么就有可能是问题回答的关键。
定义, 可得到2d大小的伴随上下文向量
也利用上下文中最为关键的词产生伴随上下文向量, 进行T次运算可得到相应的
3.4.3 上下文嵌入向量的生成
我们将上下文嵌入和注意力向量合并到了G之中, G的每一列就是对上下文的每一个词的问题-察觉表达, 给出G的计算方法:
其中就是第t列向量, 其中可以是一个可训练的函数, 可以是一个神经网络, 这里给出定义:
这里是输出为8d维度
3.5 模型层
模型层很简单, 就是一个简单的双向LSTM, 用于抽取特征, 注意到LSTM的输入输出对应关系可以是n对m, 也就是对于每一个单元的输入是8d, 输出可以选取前d个, 这里的输出定义为d大小
由于是双向的, 我们便可以得到一个2d乘T的一个矩阵, 直接输入到输出层进行答案的判断。
3.6 输出层
3.6.1 关于训练
对于QA问题而言, 我们需要一段文本之中找到可能的回答, 也即是去推测出来回答的开始和结束的位置。
对于开始位置的概率分布:
是一个10d维度的可训练的权值向量
我们将M传到另一个LSTM之中获得另一个矩阵, 记, 同样是2d乘T的矩阵
对于结束位置的概率分布:
最后定义误差函数:
其中和是正确的开始和结束的索引
3.6.1 关于测试
测试的话只需要利用动态规划在线性时间内计算出概率最大的(k, l)对, 对应概率也就是
4. 参考文献
[1] Seo M, Kembhavi A, Farhadi A, et al. Bidirectional attention flow for machine comprehension[J]. arXiv preprint arXiv:1611.01603, 2016.
[2] Pennington, Jeffrey, Richard Socher, and Christopher Manning. "Glove: Global vectors for word representation." Proceedings of the 2014 conference on empirical methods in natural language processing (EMNLP). 2014.
[3] Kim, Yoon. "Convolutional neural networks for sentence classification." arXiv preprint arXiv:1408.5882 (2014).