背景

语言模型也经常会在NLP中提出。在深度学习大行其道的今天基于神经网络的语言模型与传统定义的又有什么区别呢?语言模型在NLP中有什么意义呢?不妨沉下心,了解一下。

语言模型是一个单纯的、统一的、抽象的形式系统,语言客观事实经过语言模型的描述,比较适合于电子计算机进行自动处理,因而语言模型对于自然语言的信息处理具有重大的意义。换一句话说,语言模型其实就是看一句话是不是正常人说出来的正常的话。语言模型在信息检索、机器翻译、语音识别中担任着重要的任务。比如机器翻译、语音识别得到若干候选之后,可以利用语言模型挑一个尽量靠谱的结果。

传统的语言模型是基于统计的,在深度学习领域那么自然而然也就有了对应的语言模型变体。

语言模型的形式化表达

基于统计的语言模型自然少不了其对应的数学表达,用概率论的专业术语描述模型就是:为长度为m的字符串圈定其概率分布大语言模型 代码理解 51 语言模型有什么用_自然语言处理,其中大语言模型 代码理解 51 语言模型有什么用_深度学习_02大语言模型 代码理解 51 语言模型有什么用_语言模型_03依次表示文本中的各个词语。一般采用链式发着计算其概率值,如下式:

大语言模型 代码理解 51 语言模型有什么用_自然语言处理_04

由上式可知,当文本过长时,公式右部从第三项开始的每一项的计算难度都很大。为解决这个问题,有人提出大语言模型 代码理解 51 语言模型有什么用_自然语言处理_05元模型(n-gram model)降低该计算难度。所谓大语言模型 代码理解 51 语言模型有什么用_自然语言处理_05元模型就是在估算条件概率时,忽略距离大于大语言模型 代码理解 51 语言模型有什么用_自然语言处理_05的上文词的影响,因此大语言模型 代码理解 51 语言模型有什么用_大语言模型 代码理解 51_08的计算可以化简为:

大语言模型 代码理解 51 语言模型有什么用_大语言模型 代码理解 51_09

大语言模型 代码理解 51 语言模型有什么用_大语言模型 代码理解 51_10时称为一元模型(unigram model),此时整个句子的概率可表示为:大语言模型 代码理解 51 语言模型有什么用_深度学习_11
观察可知,在一元语言模型中,整个句子出现的概率等于各个词语出现概率的乘积。言下之意就是各个词之间都是相互独立的,这无疑完全损失了语序信息。所以一元模型的效果并不理想。
大语言模型 代码理解 51 语言模型有什么用_大语言模型 代码理解 51_12时称为二元模型(bigram model),那么一个语句出现的概率变为:
大语言模型 代码理解 51 语言模型有什么用_神经网络_13
以此类推,当大语言模型 代码理解 51 语言模型有什么用_语言模型_14的时候成为三元模型(trigram model),整个句子出现的概率变为:
大语言模型 代码理解 51 语言模型有什么用_自然语言处理_15
很显然当大语言模型 代码理解 51 语言模型有什么用_语言模型_16时,该模型时可以保留一定的次序信息的,而且大语言模型 代码理解 51 语言模型有什么用_自然语言处理_05越大,保留词序信息就越丰富,但计算成本也呈指数级增长。

一般使用频率计数的比例来计算大语言模型 代码理解 51 语言模型有什么用_自然语言处理_05元条件概率,如下式:

大语言模型 代码理解 51 语言模型有什么用_自然语言处理_19

式中大语言模型 代码理解 51 语言模型有什么用_大语言模型 代码理解 51_20表示词语大语言模型 代码理解 51 语言模型有什么用_语言模型_21在语料库中出现的总次数。

由此可见,当大语言模型 代码理解 51 语言模型有什么用_自然语言处理_05越大时,模型包含的次序信息越丰富,同时计算量随之增大。与此同时,长度越长的文本序列出现的次数也会越少,不过依照这种估计大语言模型 代码理解 51 语言模型有什么用_自然语言处理_05元条件概率时,就会出现分字分母为零的情况。因此,一般在大语言模型 代码理解 51 语言模型有什么用_自然语言处理_05元模型中需要配合相应的平滑算法解决该问题,例如拉普拉斯平滑算法。

NNLM

用神经网络训练语言模型的思想最早由徐伟在《Can Artificial Neural Networks Learn Language Models?》中提出。论文中提出一种用神经网络构建二元语言模型即:大语言模型 代码理解 51 语言模型有什么用_语言模型_25

训练语言模型的最经典之作要数 Bengio 等人在 2001 年发表在 NIPS 上的文章《A Neural Probabilistic Language Model》。网上也有人说,现在看的话,要看他在 2003 年投到 JMLR 上的同名论文了。

了解了这个其实也有助于理解word2vector那篇文章。那么我们先来看看这个论文中的内容。

1 A Neural Probabilistic Language Model

Bengio 用了一个三层的神经网络来构建语言模型,同样也是 n-gram 模型。如下图:

大语言模型 代码理解 51 语言模型有什么用_大语言模型 代码理解 51_26


模型的输入:大语言模型 代码理解 51 语言模型有什么用_深度学习_27就是前大语言模型 代码理解 51 语言模型有什么用_神经网络_28个词。现在需要根据这已知的大语言模型 代码理解 51 语言模型有什么用_神经网络_28个词预测下一个词大语言模型 代码理解 51 语言模型有什么用_语言模型_30大语言模型 代码理解 51 语言模型有什么用_语言模型_31表示大语言模型 代码理解 51 语言模型有什么用_深度学习_32所对应的词向量。整个模型中使用的是一套唯一的词向量,存在一个大小为大语言模型 代码理解 51 语言模型有什么用_大语言模型 代码理解 51_33的矩阵大语言模型 代码理解 51 语言模型有什么用_自然语言处理_34中,大语言模型 代码理解 51 语言模型有什么用_深度学习_35表示语料中的总词数,大语言模型 代码理解 51 语言模型有什么用_语言模型_36表示词向量的维度。大语言模型 代码理解 51 语言模型有什么用_深度学习_32大语言模型 代码理解 51 语言模型有什么用_自然语言处理_38的转化就是从矩阵中取出一行。

网络的第一层(输入层)是将大语言模型 代码理解 51 语言模型有什么用_神经网络_39大语言模型 代码理解 51 语言模型有什么用_神经网络_28个向量首尾拼接起来形成一个大语言模型 代码理解 51 语言模型有什么用_自然语言处理_41大小的向量,记作大语言模型 代码理解 51 语言模型有什么用_深度学习_42,

网络的第二层(隐藏层)就如同普通的神经网络,直接使用一个全连接层:大语言模型 代码理解 51 语言模型有什么用_神经网络_43计算得到,其中大语言模型 代码理解 51 语言模型有什么用_深度学习_44表示偏置,大语言模型 代码理解 51 语言模型有什么用_自然语言处理_45则是对应向量的权重。通过全连接层后再使用大语言模型 代码理解 51 语言模型有什么用_深度学习_46这个激活函数进行处理。

网络的第三层(输出层)一共有大语言模型 代码理解 51 语言模型有什么用_深度学习_35个节点,本质上这个输出层也是一个全连接层。每个输出节点大语言模型 代码理解 51 语言模型有什么用_神经网络_48表示下一个词语为大语言模型 代码理解 51 语言模型有什么用_语言模型_49(词表中的索引)的未归一化大语言模型 代码理解 51 语言模型有什么用_神经网络_50 概率。最后使用 大语言模型 代码理解 51 语言模型有什么用_自然语言处理_51 激活函数将输出值大语言模型 代码理解 51 语言模型有什么用_语言模型_52进行归一化。那么这个大语言模型 代码理解 51 语言模型有什么用_语言模型_52在整个模型中的计算如下:
大语言模型 代码理解 51 语言模型有什么用_大语言模型 代码理解 51_54
式中的大语言模型 代码理解 51 语言模型有什么用_大语言模型 代码理解 51_55是一个大语言模型 代码理解 51 语言模型有什么用_深度学习_56的矩阵,是隐藏层到输出层的参数,整个模型的多数计算集中在大语言模型 代码理解 51 语言模型有什么用_大语言模型 代码理解 51_55和隐藏层的矩阵乘法中。后文的提到的 3 个工作,都有对这一环节的简化,提升计算的速度。上式中还有一个大小为大语言模型 代码理解 51 语言模型有什么用_大语言模型 代码理解 51_58矩阵大语言模型 代码理解 51 语言模型有什么用_深度学习_59,主要是将输入层的数据结果也放到输出层进行计算的线性变换,称为直连边。如果不需要直连边的话,将大语言模型 代码理解 51 语言模型有什么用_深度学习_59置为 0 就可以了。在最后的实验中,Bengio 发现直连边虽然不能提升模型效果,但是可以少一半的迭代次数。同时他也猜想如果没有直连边,可能可以生成更好的词向量。

现在万事俱备,用随机梯度下降法把这个模型优化出来就可以了。需要注意的是,一般神经网络的输入层只是一个输入值,而在这里,输入层大语言模型 代码理解 51 语言模型有什么用_深度学习_42也是参数存在与大语言模型 代码理解 51 语言模型有什么用_自然语言处理_34中,,也是需要优化的。优化结束之后,词向量有了,语言模型也有了。

这样得到的语言模型自带平滑,无需传统 n-gram 模型中那些复杂的平滑算法。Bengio 在 APNews 数据集上做的对比实验也表明他的模型效果比精心设计平滑算法的普通 n-gram 算法要好 10% 到 20%。

那么这篇文章到这就告一段落了。可以从上面的介绍可以看出可以利用这种语言模型去训练词向量,也可以预测一个语句中下一个词是什么等等。

Bengio 还在论文中随口(不是在 Future Work 中写的)提到:可以使用一些方法降低参数个数,比如用循环神经网络。后来 Mikolov 就顺着这个方向发表了一大堆论文,直到博士毕业。下面我们就看看Mikolv提出的RNNLM(循环神经网络模型)。

2.Mikolov 的 RNNLM

Mikolov 一直在RNNLM 上做各种改进,有速度上的,也有准确率上的。现在想了解 RNNLM,看他的博士论文《Statistical Language Models based on Neural Networks》肯定是最好的选择。

循环神经网络在之前的文章中已经介绍过了。下面的模型就比较好理解了。RNNLM结构如下:

大语言模型 代码理解 51 语言模型有什么用_神经网络_63


每个时间步的输入为大语言模型 代码理解 51 语言模型有什么用_神经网络_64,是句子中第 大语言模型 代码理解 51 语言模型有什么用_语言模型_65个词的 One-hot representation 的向量,也就是说大语言模型 代码理解 51 语言模型有什么用_神经网络_64是一个非常长的向量,里面只有一个元素是 1。RNNLM训练过程

大语言模型 代码理解 51 语言模型有什么用_自然语言处理_67


RNNLM反向传播过程

大语言模型 代码理解 51 语言模型有什么用_语言模型_68


语言模型评估迷惑度/困惑度/混乱度(perplexity),其基本思想是给测试集的句子赋予较高概率值的语言模型较好。当语言模型训练完之后,测试集中的句子都是正常的句子,那么训练好的模型就是在测试集上的概率越高越好。迷惑度越小,句子概率越大,语言模型越好。

大语言模型 代码理解 51 语言模型有什么用_大语言模型 代码理解 51_69


循环神经网络的最大优势在于,可以真正充分地利用所有上文信息来预测下一个词,而不像前面的其它工作那样,只能开一个 大语言模型 代码理解 51 语言模型有什么用_自然语言处理_05 个词的窗口,只用前大语言模型 代码理解 51 语言模型有什么用_自然语言处理_05个词来预测下一个词。从形式上看,这是一个非常“终极”的模型,毕竟语言模型里能用到的信息,他全用上了。可惜的是,循环神经网络形式上非常好看,使用起来却非常难优化,如果优化的不好,长距离的信息就会丢失,甚至还无法达到开窗口看前若干个词的效果。Mikolov 在 RNNLM 里面只使用了最朴素的 BPTT 优化算法,就已经比 n-gram 中的 state of the art 方法有更好的效果,这非常令人欣慰。如果用上了更强的优化算法,最后效果肯定还能提升很多。

当然RNNLM更侧重的是语言模型,而不是词向量。后期谷歌发表的word2vector则是针对词向量做出的优化。

总结

神经网络语言模型在NLP任务中起到了一定作用。现如今的使用的词向量基本上都是源于这个思想。也为自然语言生成提供了很好的思路。现如今NLP技术发展训练基于Bert的技术可谓是大行其道,当然如若没有以往语言模型的提出,现在的发展也是让人难以琢磨。虽然现在的Bert效果很好,了解一下以往发展的技术,也能够清晰地了解现在技术发展的前前后后。

Reference

  1. Deep Learning in NLP (一)词向量和语言模型
  2. 《Can Artificial Neural Networks Learn Language Models?》
  3. Yoshua Bengio, Rejean Ducharme, Pascal Vincent, and Christian Jauvin. A neural probabilistic language model. Journal of Machine Learning Research (JMLR), 3:1137–1155, 2003. PDF
  4. NLP自然语言处理:神经网络语言模型(NNLM)
  5. Mikolov Tomáš. Statistical Language Models based on Neural Networks. PhD thesis, Brno University of Technology. 2012. PDF