CS224N(2.7)Question Answering

这节课的内容比较简单,是问答系统(Question Answering, QA)的入门介绍。 QA简介 首先,为什么需要QA?目前各大搜索引擎对于一个查询,给出的都是一个结果列表。但是很多查询是一个问题,答案也往往比较确定,比如“现任美国总统是谁?”,此时,返回一堆结果列表就显得太过啰嗦了,尤其是在手机等移动设备上搜索时,简单的给出回答也许会更好一些。另一方面,智能手机上的助手如Siri、Google Now之类的,用户期望的也是简洁的答案,而不是一堆网页列表。 QA系统的组成主要有两个部分,一部分是根据问题检索到相关的文档,这部分是传统的信息检索的内容;另一部分是对检索到的文档进行阅读理解,抽取出能回答问题的答案,这部分就是本文要介绍的QA系统。 QA的历史可追溯到上世纪七十年代,但真正取得突破性进展也就是最近几年。2015/2016年,几个大规模QA标注数据集的发表,极大的推动了这个领域的发展。这其中比较有名的数据集是斯坦福大学发布的Stanford Question Answering Dataset (SQuAD)。 SQuAD数据集的每一个样例包含一段描述P,一个问题Q,以及对Q的人工标注答案A。为了使数据集更加鲁棒,对于每个问题,都给出了三个人工标注答案。每个答案都是描述P中的一小段文字,称为一个span。所以,问题相对来说比较简单,答案可以直接从描述中提取sub-sequence得到。 QA系统的评价指标有两个,一个是确定性匹配Exact match,即对于每个问题,模型给出的回答如果和3个答案中的任意一个完全匹配,则加1分,否则不加分。另一个是F1指标,使用词袋模型(不考虑词的顺序),对于每个问题,模型给出的回答和3个答案中的每一个计算F1,这个问题的F1是3个F1的最大值,最终得分是所有问题的F1打分的均值。Exact match和F1都不考虑标点符号和冠词。相对来说,F1比Exact match更可靠和鲁棒一些。 经过两年的两三年的刷榜,SQuAD数据集的最好性能已经超越了人类的性能,为了增加数据集的难度,斯坦福后续推出升级版本SQuAD 2.0。 由于1.1版本的问题都有答案,所以QA系统变成了一个排序系统,只需要把Answer列表中排名第一的结果输出就好了。2.0在1.1的基础上,增加了没有答案的问题,可以理解为假问题,对系统造成干扰。此时就要求系统判断这个问题能否从描述P中获得答案,如果没有答案的话,就不输出任何回答<No Answer>。对于没有答案的问题,如果系统没有输出答案,得1分,否则输出任何答案都得0分。 SQuAD数据集的局限性: 回答都是span-based类型的,没有yes/no、计数、why等的问答。 由于构造问题q的时候,已知了描述P,那么q和P的描述会很像,无论是用词还是语法。而搜索引擎面临的真实情况往往是,q根本不知道P是什么,有可能q和P的描述在行文及用词上有很大差别。 描述P比较简单,因为答案是一个span,所以模型把q和P匹配,找到可能的答案位置就行。实际的复杂场景有可能要综合好几个句子的信息,还要理解不同的指代关系等才能得出最终答案。 虽然SQuAD数据集还有不少局限性,但由于其是一个well-targeted、well-structured、clean dataset,在QA发展初期,还是为促进QA发展立下了汗马功劳。 Stanford Attentive Reader 下面介绍一下Chris Manning组针对SQuAD数据集开发的QA系统——Stanford Attentive Reader。该系统目前虽然不是最好性能,但它包含QA的基本模块,可以作为QA的一个baseline模型。 首先模型对问题q进行表征的方法如下,输入是q中每个词的词向量,然后使用一个Bi-LSTM提取句子特征,由于是双向的LSTM,所以模型把正向和反向的LSTM的最后一个隐状态拼接起来,作为对整个句子的表征。 由于SQuAD数据集的回答都是描述P中的一个span,那么,模型只需要预测出这个span在P中的起始位置和终止位置即可,具体方法如下图所示。其实也很简单,上一步我们得到的句子的表征向量q,下一步,我们对描述P也使用Bi-LSTM,得到描述P中每个词的表征向量\(\tilde p_i\)。然后,使用两次Attention,用q查询集合\(P=[\tilde p_1,…,\tilde p_n]\),得到答案span的起始位置\(\alpha_i\)和终止位置\(\alpha’_i\)。另外,由于\(q\)和\(\tilde p_i\)的维度可能不一样,又或者为了提升模型性能,在计算Attention score的时候,不是简单的向量点积,而是采用了线性变换的方法,增加了参数\(W\)。 后来,Chris Manning组又推出了升级版本Stanford Attentive Reader++,主要包括两个方面。首先,对表征问题的网络进行了改进,\(q\)不仅包含Bi-LSTM的两个尾结点的隐状态,而是包含整个问题所有隐状态的加权平均,而且网络层数增加到了3层。其次,对描述P的表征方面,原来的输入只包含词向量,现在还包含语言特征(如POS、NER的标签)、词频、以及近义词的相似度等。改进版模型性能提升了不少。 另一个比较流行的QA系统是BiDAF,如下图所示,这里不再详细介绍。它的特点一方面输入不仅包含词向量,还包含字符级别的特征。另一大创新是在Attention Flow Layer,相对于Stanford Attentive Reader,BiDAF的Attention是双向的,不但包含q对P的Attention,还包含P对q的Attention。

August 4, 2019 · 1 min

CS224N(1.31)Translation, Seq2Seq, Attention

今天介绍另一个NLP任务——机器翻译,以及神经网络机器翻译模型seq2seq和一个改进技巧attention。 机器翻译最早可追溯至1950s,由于冷战的需要,美国开始研制由俄语到英语的翻译机器。当时的机器翻译很简单,就是自动从词典中把对应的词逐个翻译出来。 后来在1990s~2010s,统计机器翻译(Statistical Machine Translation, SMT)大行其道。假设源语言是法语\(x\),目标语言是英语\(y\),机器翻译的目标就是寻找\(y\),使得\(P(y|x)\)最大,也就是下图的公式。进一步,通过贝叶斯公式可拆分成两个概率的乘积:其中\(P(y)\)就是之前介绍过的语言模型,最简单的可以用n-gram的方法;\(P(x|y)\)是由目标语言到源语言的翻译模型。为什么要把\(P(y|x)\)的求解变成\(P(x|y)*P(y)\)?逐个击破的意思,\(P(x|y)\)专注于翻译模型,翻译好局部的短语或者单词;而\(P(y)\)就是之前学习的语言模型,用来学习整个句子\(y\)的概率,专注于翻译出来的句子从整体上看起来更加通顺、符合语法与逻辑。所以问题就转化为怎样求解\(P(x|y)\)。 SMT进一步把\(P(x|y)\)分解成\(P(x,a|y)\),其中\(a\)表示一个对齐alignment,可以认为是两种语言之间单词和单词或短语和短语的一个对齐关系。如下图所示是一个英语和法语的alignment。对齐本身就很复杂,存在1对1,1对多,多对1,多对多等情况,所以\(P(x,a|y)\)的求解在给定\(y\)的情况下,不但要考虑对齐方案\(a\)的情况\(P(a|y)\),还需要考虑对齐之后词与词的翻译情况\(P(x|a,y)\),可能的情况非常多。 那么,SMT怎样找到\(\arg max_y\)呢?穷举所有情况是不可能的,启发式搜索是可行的。形象描述就是在搜索过程中,对概率较低的路径进行剪枝,只保留概率较大的翻译情况。如下图的搜索树,对于概率较低的路径就不往下搜索了。 总之,统计机器翻译非常复杂,有很多的子模块,需要很多的人工干预和特征工程。 2014年,seq2seq模型横空出世,神经网络机器翻译(Neural Machine Translation, NMT)方兴未艾。seq2seq顾名思义,就是从序列到序列的模型,因为机器翻译的源语言和目标语言都是seq。 seq2seq的NMT如下图所示,它由两个RNN组成,左边的红色部分称为Encoder RNN,它负责对源语言进行编码(Encode);右边的绿色部分称为Decoder RNN,它负责对目标语言进行解码(Decode)。首先,Encoder RNN可以是任意一个RNN,比如朴素RNN、LSTM或者GRU。Encoder RNN负责对源语言进行编码,学习源语言的隐含特征。Encoder RNN的最后一个神经元的隐状态作为Decoder RNN的初始隐状态。Decoder RNN是一个条件语言模型,一方面它是一个语言模型,即用来生成目标语言的;另一方面,它的初始隐状态是基于Encoder RNN的输出,所以称Decoder RNN是条件语言模型。Decoder RNN在预测的时候,需要把上一个神经元的输出作为下一个神经元的输入,不断的预测下一个词,直到预测输出了结束标志符<END>,预测结束。Encoder RNN的输入是源语言的word embeding,Decoder RNN的输入是目标语言的word embeding。 seq2seq是一个很强大的模型,不但可以用来做机器翻译,还可以用来做很多NLP任务,比如自动摘要、对话系统等。 seq2seq作为一个条件语言模型,形式化来说,它直接对\(P(y|x)\)进行建模,在生成\(y\)的过程中,始终有\(x\)作为条件,正如下图的条件概率所示。 上面介绍了seq2seq的预测过程,seq2seq的训练过程如下图所示。训练的时候,我们同时需要源语言和翻译好的目标语言,分别作为Encoder RNN和Deocder RNN的输入。对于Encoder RNN没什么好说的。Decoder RNN在训练阶段,每一个时间步的输入是提供的正确翻译词,输出是预测的下一个时间步的词的概率分布,比如在\(t=4\),预测输出是\(\hat y_4\),而正确答案是“with”,根据交叉熵损失函数,\(J_4=-\log P(“with”)\)。总的损失函数就是所有时间步的损失均值。 seq2seq的训练过程是end2end的,即把Encoder RNN和Decoder RNN作为一个整体进行训练,不会像SMT一样有很多的子模块单独训练。当然seq2seq也可以单独对encoder和deconder进行训练优化,再组合,但是这个效果不一定会比整体优化encoder和deconder更好。 上上张图介绍的seq2seq的预测过程,实际上是一个贪心的预测过程,即在Decoder RNN的每一步都贪心选择\(\hat y_t\)概率最大的那个词。但是贪心只能保证每一步是最优的,无法保证预测出来的句子整体是最优的。特别是如果在\(t\)时刻贪心选择的词不是全局最优,会导致\(t\)时刻往后的所有预测词都是错误的,没有回头路了。但是如果每个时间步都穷举所有可能的情况的话,时间复杂度\(O(V^T)\)又太高了。 Beam search搜索策略是贪心策略和穷举策略的一个折中方案,它在预测的每一步,都保留Top-k高概率的词,作为下一个时间步的输入。k称为beam size,k越大,得到更好结果的可能性更大,但计算消耗也越大。请注意,这里的Top-k高概率不仅仅指当前时刻的\(\hat y_t\)的最高概率,而是截止目前这条路径上的累计概率之和,如下图的公式所示。 举例如下,假设\(k=2\),第一个时间步保留Top-2的词为”he”和”I”,他们分别作为下一个时间步的输入。”he”输入预测输出前两名是”hit”和”struck”,则”hit”这条路的累加概率是”he”的概率加上”hit”的概率=-1.7,类似的可以算出其他几个词对应路径的概率打分。最后在这4条路上保留\(k=2\)条路,所以”hit”和”was”对应路径保留,作为下一个时间步的输入;”struck”和”got”对应路径被剪枝。 最终的搜索树如下图所示,可以看到在每个时间步都只保留了\(k=2\)个节点往下继续搜索。最后”pie”对应的路径打分最高,通过回溯法得到概率最高的翻译句子。请注意,beam search作为一种剪枝策略,并不能保证得到全局最优解,但它能以较大的概率得到全局最优解,同时相比于穷举搜索极大的提高了搜索效率。 在beam search的过程中,不同路径预测输出结束标志符<END>的时间点可能不一样,有些路径可能提前结束了,称为完全路径,暂时把这些完全路径放一边,其他路径接着beam search。beam search的停止条件有很多种,可以设置一个最大的搜索时间步数,也可以设置收集到的最多的完全路径数。 当beam search结束时,需要从n条完全路径中选一个打分最高的路径作为最终结果。由于不同路径的长度不一样,而beam search打分是累加项,累加越多打分越低,所以需要用长度对打分进行归一化,如下图所示。那么,为什么不在beam search的过程中就直接用下面的归一化打分来比较呢?因为在树搜索的过程中,每一时刻比较的两条路径的长度是一样的,即分母是一样的,所以归一化打分和非归一化打分的大小关系是一样的,即在beam search的过程中就没必要对打分进行归一化了。 ...

August 2, 2019 · 1 min