# 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：待之后对神经语言模型有系统的了解后，考虑将本文融合进综述的文章中）

## 1. 算法介绍

### 1.1 RNN

这篇文章中使用了最简单的RNN版本，而现在市场上普遍选择LSTM，GRU甚至NAS等具有捕捉更长时间长期依赖的节点。在RNN中，第$$t$$个时间片$$x(t)$$读取的是$$t-1$$时刻的状态$$s(t-1)$$和$$t$$时刻的数据$$w(t)$$。$$w(t)$$是$$t$$时刻单词的one-hot编码，单词量在3万-20万之间；$$s(t-1)$$是$$t-1$$时刻的隐藏层状态，实验中隐层节点数一般是30-500个，$$t=0$$时使用0.1进行初始化。上面过程表示为：

$$
x(t) = w(t) + s(t-1)
$$

$$t$$时刻的隐藏层状态是$$x(t)$$经过sigmoid激活函数$$f$$得到的值，其中$$u\_{ji}$$是权值矩阵：

$$
s\_j(t) = f(\sum\_i x\_i(t)u\_{ji})
$$

有的时候我们需要在每个时间片有一个输出，只需要在隐层节点$$s\_j(t)$$处添加一个softmax激活函数即可：

$$
y\_k(t)= g(\sum\_j s\_j(t)v\_{kj})
$$

### 1.2 训练数据

训练语言模型的数据是不需要人工标注的，我们要做的就是寻找大量的单语言数据即可。在制作训练数据和训练标签时，我们通过取第$$0$$到$$t-1$$时刻的单词作为网络输入，第$$t$$时刻的单词作为标签值。

由于输出使用了softmax激活函数，所以损失函数的计算使用的是交叉熵，输出层的误差向量为：

$$
\text{error}(t) = \text{desired}(t) - y(t)
$$

上式中$$\text{desired}(t)$$是one-hot编码的模型预测值，$$y(t)$$是标签值。不知道上式的得来的同学自行搜索交叉熵的更新的推导公式，此处不再赘述。更新过程使用标准的SGD即可。

### 1.3 训练细节

**初始化**：使用的是均值为0，方差为0.1的高斯分布进行初始化。

**学习率**：初始值为0.1，当模型在验证集上的精度不再提升时将学习率减半，一般10-20个Epoch之后模型就收敛了。

**正则**：即使采用过大的隐藏层，网络也不会过度训练，并且实验结果表明添加正则项不会很有帮助。

**动态模型**：常见的机器/深度学习在测试的时候测试数据并不会用来更新模型。在这篇文章中作者认为测试数据也应该参与到模型的更新中，例如在测试数据中反复出现的一个人名等这种类似的情况，作者将这种情况叫做动态模型。实验结果表明动态模型可以大大降低困惑度。

**稀有（rare）类**：为了提高模型的能力，作者将低于阈值的词合并到rare类中，词概率的计算方式如下：

$$
P(w\_i(t+1)|w(t), s(t-1))=
\left{
\begin{array}{}
\frac{y\_{rare}(t)}{C\_{rare}} & \text{if } w\_i(t+1)\text{ is rare}\\
y\_i(t) & \text{otherwise}
\end{array}
\right.
$$

其中$$C\_{rare}$$是词表中词频低于阈值的单词的个数，所有的低频次都被平等对待，即它们的概率分布是均等的。

## 2. 总结

2019年的侧重点将会转移到NLP方向，首先拿一篇经典的RNN语言模型进行一下预热。毕竟发表在2010年，这篇文章的算法非常简单，RNN的效果必定不如LSTM或者GRU等，顺序语言模型也不如掩码语言模型能捕捉更多的上下文信息。这里只算抛砖引玉，在之后的文章中我们将介绍更多效果更好的语言模型。
