Recurrent Neural Network based Language Model
最后更新于
最后更新于
tags: NLP, Language Model
在深度学习兴起之前,NLP领域一直是统计模型的天下,例如词对齐算法GIZA++,统计机器翻译开源框架MOSES等等。在语言模型方向,n-gram是当时最为流行的语言模型方法。一个最为常用的n-gram方法是回退(backoff) n-gram,因为n值较大时容易产生特别稀疏的数据,这时候回退n-gram会使用(n-1)-gram的值代替n-gram。
n-gram的问题是其捕捉句子中长期依赖的能力非常有限,解决这个问题的策略有cache模型和class-based模型,但是提升有限。另外n-gram算法过于简单,其是否有能力取得令人信服的效果的确要打一个大的问号。
一个更早的使用神经网络进行语言模型学习的策略是Bengio团队的使用前馈神经网络进行学习。他们要求输入的数据由固定的长度,从另一个角度看它就是一个使用神经网络编码的n-gram模型,也无法解决长期依赖问题。基于这个问题,这篇文章使用了RNN作为语言模型的学习框架。
这篇文章介绍了如何使用RNN构建语言模型,至此揭开了循环神经语言模型的篇章。由于算法比较简单,这里多介绍一些实验中使用的一些trick,例如动态测试过程等,希望能对你以后的实验设计有所帮助。(TODO:待之后对神经语言模型有系统的了解后,考虑将本文融合进综述的文章中)
这篇文章中使用了最简单的RNN版本,而现在市场上普遍选择LSTM,GRU甚至NAS等具有捕捉更长时间长期依赖的节点。在RNN中,第个时间片读取的是时刻的状态和时刻的数据。是时刻单词的one-hot编码,单词量在3万-20万之间;是时刻的隐藏层状态,实验中隐层节点数一般是30-500个,时使用0.1进行初始化。上面过程表示为:
时刻的隐藏层状态是经过sigmoid激活函数得到的值,其中是权值矩阵:
由于输出使用了softmax激活函数,所以损失函数的计算使用的是交叉熵,输出层的误差向量为:
初始化:使用的是均值为0,方差为0.1的高斯分布进行初始化。
学习率:初始值为0.1,当模型在验证集上的精度不再提升时将学习率减半,一般10-20个Epoch之后模型就收敛了。
正则:即使采用过大的隐藏层,网络也不会过度训练,并且实验结果表明添加正则项不会很有帮助。
动态模型:常见的机器/深度学习在测试的时候测试数据并不会用来更新模型。在这篇文章中作者认为测试数据也应该参与到模型的更新中,例如在测试数据中反复出现的一个人名等这种类似的情况,作者将这种情况叫做动态模型。实验结果表明动态模型可以大大降低困惑度。
稀有(rare)类:为了提高模型的能力,作者将低于阈值的词合并到rare类中,词概率的计算方式如下:
2019年的侧重点将会转移到NLP方向,首先拿一篇经典的RNN语言模型进行一下预热。毕竟发表在2010年,这篇文章的算法非常简单,RNN的效果必定不如LSTM或者GRU等,顺序语言模型也不如掩码语言模型能捕捉更多的上下文信息。这里只算抛砖引玉,在之后的文章中我们将介绍更多效果更好的语言模型。
有的时候我们需要在每个时间片有一个输出,只需要在隐层节点处添加一个softmax激活函数即可:
训练语言模型的数据是不需要人工标注的,我们要做的就是寻找大量的单语言数据即可。在制作训练数据和训练标签时,我们通过取第到时刻的单词作为网络输入,第时刻的单词作为标签值。
上式中是one-hot编码的模型预测值,是标签值。不知道上式的得来的同学自行搜索交叉熵的更新的推导公式,此处不再赘述。更新过程使用标准的SGD即可。
其中是词表中词频低于阈值的单词的个数,所有的低频次都被平等对待,即它们的概率分布是均等的。