原文地址
该文章主要关于RNN来实现槽填充,比较基础的读物,这里只做粗略的翻译,一些细节还请看原文。
原作者提供了Keras实现,近期自己打算用Pytorch重写一个版本。
按照原文重写的Pytorch版本,代码写的并不好,主要是当做练习来写的,实验结果基本和原文的一致。
Problem and the Dataset
我们要解决的问题是自然语言理解(NLU)。NLU的目标是提取语句的含义,然而这仍是个未解决的难题。
因此,我们把这个问题简化为一个可解决的实际问题——理解说话者的一部分内容。
具体来说,说话者要了解航班信息,那么我们期望去识别出这个意图。
我们将使用Airline Travel Information System(ATIS)数据集,该数据集由DARPA在上世纪90年代收集的。
ATIS数据集包含了航班相关的咨询语句。
例如”I want to go from Boston to Atlanta on Monday.”
理解这句话,将其简化为可识别的参数,比如目的地和出发日,这个任务被成为槽填充(slot-filling)。
下面是来自数据集的一个句子样例和对应的标签:
ATIS官方数据分为4978条训练集和893条测试集,平均一句话长度为15个词,一共有128个类别(slots)标签。
我们的方法将使用到如下技术:
- Word embeddings
- Recurrent Neural Networks
下面几节将介绍这些信息。
Word Embeddings
word embeddings 将一个词映射到高维空间。
理想情况下,embedding可以学习到语义信息,近义词的向量夹角会比较小,而无关词的向量夹角会比较大。
embedding可以通过大量文本语料或放置于特定问题中学习,本文将采用第二种方法。
Word Embeddings 中比较流行的是word2vecter和 glove,不过这里用的是与模型一起训练,这在神经网络模型中也很常见
Recurrent Neural Networks
卷积层可以很好的汇聚局部信息,但是他们无法捕获数据的顺序信息。循环神经网络可以帮助我们捕获序列信息,比如自然语言中的词序。
如果我们要预测当前词所属的类别,我们最好去记住它之前的词。RNN单元中有包含了内部记忆单元,能够存储之前的序列信息。因此我们可以使用RNN来出来这类槽填充问题。
对于这类问题,我们将使用词的embedding作为RNN的输入。
Putting it all together
Loading Data
我们使用data.load.atisfull()来加载数据。第一次运行时会自动下载数据。
将词和标签用词汇表的索引来代替,词表分别存储于w2idx和lables2idx。
Keras Model
下面来定义模型,Keras有内置的Embedding层可用于word embeddings。
training
下面开始训练模型,每批只使用一个句子。
由于每个句子的长度不同,这里不能使用model.fit(),我们使用model.train_on_batch()。
Evaluation
为了估量模型的准确率,我们使用model.predict_on_batch()和metrics.accuracy.conlleval()。
该模型可以得到92.36的F1。
Improvements
该模型的不足在于,预测时没有利用后续的词。
可以想象,当前词的属性和下一个词也可能会有关联。
为了捕获后续词的信息,可以在RNN和Embedding层之间加入卷基层。
使用该方法可以达到94.90的F1得分。
References
- Grégoire Mesnil, Xiaodong He, Li Deng and Yoshua Bengio. Investigation of Recurrent-Neural-Network Architectures and Learning Methods for Spoken Language Understanding. Interspeech, 2013. pdf
- Recurrent Neural Networks with Word Embeddings, theano tutorial