过去半年以来,自然语言处理领域进化出了一件神器。此神器乃是深度神经网络的一种新模式,该模式分为:embed、encode、attend、predict四部分。本文将对这四个部分娓娓道来,并且剖析它在两个实例中的用法。
人们在谈论机器学习带来的提升时,往往只想到了机器在效率和准确率方面带给人们的提升,然而最重要的一点却是机器学习算法的通用性。如果你想写一段程序来识别社交媒体平台上的侮辱性帖子,就把问题泛化为“需要输入一段文本,预测出文本的类别ID”。这种分类与识别侮辱性帖子或是标记电子邮件类别之类的具体任务无关。如果两个问题的输入和输出类型都一致,那我们就应复用同一套模型的代码,两者的区别应该在于送入的训练数据不同,就像我们使用同一个游戏引擎玩不同的游戏。
笔者用spaCy和Keras实现了自然语言推理的可分解注意力模型。代码已经上传到
假设你有一项强大的技术,可以预测实数稠密向量的类别标签。只要输入输出的格式相同,你就能用这项技术解决所有的问题。与此同时,你有另一项技术,可以用一个向量和一个矩阵预测出另一个向量。那么,现在你手里就握着三类问题的解决方案了,而不是两类。为什么是三类呢?因为如果第三类问题是通过矩阵和一个向量,得到一个类别标签,显然你可以组合利用前两种技术来解决。大多数NLP问题可以退化成输入一条或多条文本的机器学习问题。如果我们能将这些文本转化为向量,我们就可以复用现有的深度学习框架。接下来就是具体的做法。
嵌入式词语表示,也被称为“词向量”,是现在最广泛使用的自然语言处理技术之一。词向量表示是一种既能表示词本身又可以考虑语义距离的表示方法。然而,大多数NLP问题面对的不是单个词语,而是需要分析更长的文本内容。现在有一个简单而灵活的解决方案,它在许多任务上都表现出了卓越的性能,即RNN模型。将文本用一个向量的序列表示之后,使用双向RNN模型将向量编码为一个句子向量矩阵。这个矩阵的每一行可以理解为词向量——它们对句子的上下文敏感。最后一步被称为注意力机制。这可以将句子矩阵压缩成一个句子向量,用于预测。
词向量表将高维的稀疏二值向量映射成低维的稠密向量。举个例子,假设我们收到的文本是一串ASCII字符,共有256种可能值,于是我们把每一种可能值表示为一个256维的二值向量。字符’a’的向量只有在第97维的值等于1,其它维度的值都等于0。字符’b’的向量只有在第98维的值等于1,其它维度的值都等于0。这种表示方法称为’onehot’形式。不同字符的向量表示完全不一样。
假设得到了词向量的序列,编码这一步是将其转化为句子矩阵,矩阵的每一行表示每个词在上下文中所表达的意思。
#bidirectionalRNNdefencode(fwd_rnn,bwd_rnn,word_vectors):fwd_out=ndarray((len(word_vectors),fwd_rnn.nr_hidden,dtype='float32')bwd_out=ndarray((len(word_vecors),bwd_rnn.nr_hidden),dtype='float32')fwd_state=fwd_rnn.initial_state()bwd_state=bwd_rnn.initial_state()foriinrange(len(word_vectors)):fwd_state=fwd_rnn(word_vectors[i],fwd_state)bwd_state=bwd_rnn(word_vectors[-(i+1)],bwd_state)fwd_out[i]=fwd_statebwd_out[-(i+1)]=bwd_statereturnconcatenate([fwd_state,bwd_state])我个人认为双向RNN会是今后的主流。RNN的主要应用是读入文本内容,然后从中预测出一些信息。而我们是用它来计算一个中间表达状态。最重要的一点是得到的表达能够反映词语在文中的意义。理论上应该学到“pickup”与“pickon”这两个词语的意义有区别。这一直是NLP模型的巨大弱点。现在我们有了一个解决方案。
这一步是将上一步的矩阵表示压缩为一个向量表示,因此可以被送入标准的前馈神经网络进行预测。注意力机制对于其它压缩方法的优势在于它输入一个辅助的上下文向量:
Yang等人在2016年发表的提出了一种注意力机制,输入一个矩阵,输出一个向量。区别于从输入内容中提取一个上下文向量,该机制的上下文向量是被当做模型的参数学习得到。这使得注意机制变成一个纯粹的压缩操作,可以替换任何的池化步骤。
文本内容被压缩成一个向量之后,我们可以学习最终的目标表达——一种类别标签、一个实数值或是一个向量等等。我们也可以将网络模型看做是状态机的控制器,如一个基于转移的解析器,来做结构化预测。
有趣的是,大部分的NLP模型通常更青睐浅层的前馈网络。这意味着近期在机器视觉领域取得的重要技术至今为止并没有影响到NLP领域,比如residualconnections和batchnormalization。
自然语言推测是给一对句子预测类别标签的问题,类别标签则表示它们两者的逻辑关系。使用三种类别标签:
Bowman等人在中给出了几条例子:
这份语料库的目的之一是为我们提供一个新的、规模合适的语料库用于研发将句子编码为向量的模型。例如,Bowman在2016年发表的介绍了一种基于转移的模型,它依次读入句子,构建一种树形结构的内部表达。
Bowman他们的准确率达到了83.2%,比之前的工作成果提升了一大截。过了不到半年,Parikh的提出的模型取得了86.8%的准确率,而使用的模型参数数量只有Bowman模型的10%。不久之后,Chen等人发表的提出了一种效果更好的系统,准确率达到88.3%。当我第一次阅读Parikh的论文时,我无法理解他们的模型如何取得这么好的效果。原因在于他们的模型用独特的注意力机制融合了两个句子矩阵:
关键的优势是他们讲句子转为向量的压缩步骤合并完成,而Bowman他们则是分别将两个句子转为向量。请记住Vapnik的原则:
该模型接收一篇文档作为输入,文档由句子的序列组成,其中每个句子是一个词语的序列。每句话的每个词语分别编码,生成两个词向量序列,每个序列表示一个句子。这两个序列分别编码成两个句子矩阵。然后由注意力机制将句子矩阵压缩为句子向量,多个句子向量又组成文本矩阵。最后一步注意力操作将文本矩阵压缩为文本向量,然后送入最终的预测网络来预测类别标签。
将yang等人的模型与卷积神经网络做比较,可以得到有意思的结果。两个模型都能自动提取位置敏感特征。然而,CNN模型既不通用,效率也较低。而双向RNN模型只需要对每个句子读入两次——正向一次,反向一次。LSTM编码还能提取任意长度的特征,因为句子上下文的任何信息都有可能被揉入词语的向量表示。将句子矩阵压缩成向量的步骤简单并且有效的。要构建文档向量,只需要对句子向量再进行一次同样的操作。
提升模型准确率的主要因素是双向LSTM编码器,它创建了位置敏感的特点。作者通过将注意力机制替换为平均池化,证明了上述观点。使用平均池化的方法,该模型在所有测试数据上仍然优于以前的最好模型。然而,注意力机制进一步普遍地提高了性能。
我已经用我们自己的NLP库实现了第一个例子,我正在实现文本分类的系统。我们还计划开发一个SpaCy版的通用双向LSTM模型,能够方便地将预训练的词向量用于实际问题中。