语言模型简介

语言模型
语言模型可以对一段文本的概率进行估计,对信息检索,机器翻译,语音识别等任务有着重要的作用。语言模型分为统计语言模型神经网络语言模型。下面一次介绍着两类语言模型。
统计语言模型
要判断一段文字是不是一句自然语言,可以通过确定这段文字的概率分布来表示其存在的可能性。 语言模型中的词是有顺序的,给定m个词看这句话是不是一句合理的自然语言,关键是看这些词的排列顺序是不是正确的。所以统计语言模型的基本思想是计算条件概率。比如一段文字有 w1,w2,w3...,wm w 1 , w 2 , w 3 . . . , w m 这m个词组成,看看是不是一句话,就可以用下面的公式计算其联合概率:
P(w1,w2,w3...,wm)=P(w2|w1)P(w3|w1,w2)...P(wm|w1,w2,...wm1) P ( w 1 , w 2 , w 3 . . . , w m ) = P ( w 2 | w 1 ) P ( w 3 | w 1 , w 2 ) . . . P ( w m | w 1 , w 2 , . . . w m − 1 )
在实际操作中,如果文本较长, P(wi|w1,w2,...wi1) P ( w i | w 1 , w 2 , . . . w i − 1 ) 的估计会非常困难,所以就出现了一个简化模型N-gram语言模型:当前词只和它前面的n个词有关,与更前面的词无关,上面的式子就可以写成:
P(wi|w1,w2,...wi1)=P(wi|wi(n1),...,wi1) P ( w i | w 1 , w 2 , . . . w i − 1 ) = P ( w i | w i − ( n − 1 ) , . . . , w i − 1 )
经典的统计语言模型就是N-gram语言模型。
为什么说文本较长故居会非常困难?
语言模型的任务是根据语料训练模型参数,根据词典中存在的词自动生成一句自然语言,需要保证生成的这句话是一段通顺的话,如果N-gram中的N选取的比较大,比如说5,那每个当前词的估计都和前面的5个词有关,比如我要生成‘中华人民共和国’,在生成第六个词‘和’时,要计算P(和|w1,w2,w3,w4,w5),要知道在生成第六个词的时候前面的5个词并不是确定的,需要将所有的可能性都列出来一个一个比较,选择概率最大的那个,而每个词的可能性都是词典大小的可能性,如果词典里有1万个词,那w1,w2,w3,w4,w5每个词都有1万中选择,这5个词组成的序列有10000^5个序列,这是一个非常大的数,每一种序列都回去训练语料中寻找该种序列出现的次数,也就是序列频率,这只是计算出了条件概率的分母,还有分子,分子是6个词所有可能性每一种可能性出现的次数,会得到10000^6个序列,用一个公式表示:

P(w6|w1,w2,w3,w4,w5)=count(w1,w2,w3,w4,w5,w6)count(w1,w2,w3,w4,w5) P ( w 6 | w 1 , w 2 , w 3 , w 4 , w 5 ) = c o u n t ( w 1 , w 2 , w 3 , w 4 , w 5 , w 6 ) c o u n t ( w 1 , w 2 , w 3 , w 4 , w 5 )

根据上面的分析每个词的预测我们都会得到10000^6个这样的概率,试想一下,如果不约束文本的长度,那后面的条件概率几乎是无法计算的,因为数量太多了,不仅有这个问题,还有如果 w1,w2,w3,w4,w5,w6 w 1 , w 2 , w 3 , w 4 , w 5 , w 6 组成的序列不是一个常用的序列,在预料中找不到这样的词序组合,那对应序列算出来的概率会很小很小,但是你也不能不计算他,所以就会面临你要计算非常多的概率,但是计算出来的大部分值非常小,甚至接近于0,而这些接近于0的概率还不能舍弃,必须存在,这样就会造成数据稀疏的问题。

n-gram语言模型解决了用普通的条件概率计算句子概率参数太多难以训练的问题,理论上来说n取得越大保留的词序信息就越多,生成的句子越合理,但如果n取得比较大,同样会面临数据稀疏的问题,n-gram 模型解决了参数太多难以训练的问题,但没有解决数据稀疏的问题。

之所以存在数据稀疏的问题,是因为我们想把n取得大一点来更多的保留词序信息,但n太大会导致 w1,w2,w3,...wn w 1 , w 2 , w 3 , . . . w n 这个序列在语料中很少出现或者根本不出现,(根据经验也知道太长的一句话在语料中出现的次数不是那么多,要远远小于2,3个词出现的次数)造成计算出的条件概率接近于0,那算出的句子的概率也是接近于0,这个语言模型就没法用了,这是数据稀疏导致的训练出的语言模型无法用的原因。

现在问题来了,我们既想把n取的大一点以保留更多的词序信息,又想避免数据稀疏的问题,事实上,确实有这样的模型,那就是神经网络语言模型。
神经网络语言模型
神经网络语言模型的提出解决了n-gram模型当n较大时会发生数据稀疏的问题。
与N-gram语言模型相同,神经网络语言模型(NNLM)也是对n元语言模型进行建模,估计 P(wi|win+1,win+2,...wi1) P ( w i | w i − n + 1 , w i − n + 2 , . . . w i − 1 ) 的概率,与统计语言模型不同的是,NNLM不通过计数的方法对n 元条件概率进行估计,而是直接通过一个神经网络对其建模求解。语言模型简介_第1张图片
NNLM的结构如图所示,分为三层,输入层,隐藏层,输出层,如果要生成‘中华人民共和国’这句话,已经生成了前面的四个词,要在前面的四个字为条件的情况下输出第五个词,输入层是将原始文字映射层向量,当然,这个向量是随机初始化得到的,也是我们要在训练过程中调整的参数(权重),在输入层将词向量拼接起来输入到隐藏层,隐藏层是一个非线性激活函数,输出层得到的是一个词典大小的向量,表示词典中的每个词作为语言模型生成的第五个词的可能性。
NNLM也是N元语言模型,比如假设我们训练的是一个7元语言模型,在训练预料中我们会按照每7个词做一样样本,其中前6个词是输入,第七个词是正确的输出,模型通过6个词的输入在输出层预测第七个词在字典上的概率分布。对整个语料来说,语言模型需要最大化:

wiDlogP(wi|win+1,...wi1) ∑ w i ∈ D l o g P ( w i | w i − n + 1 , . . . w i − 1 )

训练时使用随机梯度下降法(就是求导取极值)来优化上述目标函数。
为什么神经网络语言模型能够缓解数据稀疏的问题?
这是由于NNLM使用词序列的词向量对上文(预测词前面的词被称为上文)进行表示,而统计语言模型使用的上文是各词的one-hot 表示,词是直接在字典里拿出来的,词与词之间是相互独立的,每个位置都可以在词典中任意选择词,可以这样理解,作为条件的每个词都是一个维度为词典大小的one hot向量,这样构成的条件矩阵是一个非常稀疏的矩阵,而NNLM将词向量压缩在一个低维空间,利用这种低维的实数表示,可以用相似的上文预测出相似的目标词,而传统模型只能用相同的上文预测出相同的目标词(无法计算词与词之间的距离,只能去语料中匹配找词频,很机械)。
至此出现了两个数据稀疏,一个是说输入是one-hot的形式,输入词典大小的向量,但这个向量只有一个1,其余维度都是0,输入一个很大的矩阵但包含的信息太少,造成数据稀疏。另一个是说在输出层,由于n太大导致长度为n-1的序列在语料中出现的频次太少甚至不出现,导致计算出来的条件概率很多都是0或者接近于0,这样就会造成模型生成出来的句子概率基本都接近于0,无法分出那些是正常的句子,那些是不对的句子,使模型失效。NNLM对这两个数据稀疏问题都起到一定的缓解作用。
语言模型是考虑上文,用 上文预测下一个词,而后来出现的Word2vec中的CBOW用 上下文来预测中间词训练词向量。

即使使用了神经网络,本质上NNLM仍然是N元语言模型,就是你要预测的当前词只和他前面的N-1个词有关,与更前面的词无关,尽管这种方法一定程度上解决了数据稀疏的问题,但还是损失了一些信息。那有没有一种把要预测的当前词的前面所有的词都利用上的模型,显然是有的,这就要涉及到自然语言处理中的大杀器循环神经网络(RNN),我们都知道,循环神经网络的定义是当前的输出不仅和当前的输入有关,还和上一时刻的隐藏层的输出有关,这样讲神经网络展开后就会发现他把序列从开头到结尾全连起来了, 十分方便处理序列数据,而这个性质正是我们做语言模型所需要的:预测的当前词要和他前面的所有词有关,而不仅仅是他前面的N-1个词。

循环神经网络语言模型(RNNLM)
这个模型的结构图只需要把NNLM的隐藏层换成RNN神经元就可以了。输入不在限制长度,而是按照句子序列一个词一个词的迭代输入,比如将‘中华人民共和国’这句话作为训练样本,RNNLM先设隐藏层的初始状态为h(0),然后读入第一个词‘中’,预测下一个词‘华’(先不管预测的对不对),根据预测结果通过优化目标函数更新网络参数,然后在读入下一个词‘华’(读入的是样本中的词,与上一时刻输出什么无关,现在是在训练阶段),此时输入了‘中华’两个词,根据这两个词预测第三个词,再根据预测结果更新网络参数,在读入下一个词‘人’,此时根据读入的‘中华人’这三个词预测下一个词,在根据输出更新网络参数,依次类推,这就是RNNLM包含全部上文信息的原因,不管你预测第几个词,都会用到前面输入的所有词的信息(全部上文信息)。
语言模型简介_第2张图片

神经网络语言模型都会在输入层得到一个词向量矩阵,当语言模型训练好之后,顺便也得到了词向量,词向量时神经网络语言模型的副产物。
语言模型的隐藏层都是非线性函数,从输入到隐藏层的输出肯定要经过一个矩阵运算,即 tanh(Wx+b) t a n h ( W x + b ) ,有一个W,而在CBOW中,隐层是将输入直接相加,没有矩阵运算,所以CBOW相比NNLM要快很多,这也是隐藏层是线性比非线性更快的原因。

你可能感兴趣的:(语言模型简介)