1. 语言模型

  在这一部分中,我们讨论的语言模型主要是统计语言模型,除此之外,我们在今后的文章中还会对神经网络语言模型进行介绍。
  所谓语言模型,就是利用数学的方法描述语言规律。而统计语言模型,就是用句子SSS出现的概率P(S)P(S)P(S)来刻画句子的合理性(而不进行语言学分析处理),这是统计自然语言处理的基础模型。
  假设句子S=w1,w2,...,wnS=w_1,w_2,...,w_nS=w1,w2,...,wn,其中,wiw_iwi可以暂时看作句子中的第iii个词(在后面会进行具体介绍)。由于自然语言是上下文相关的信息传递方式,可以很自然地讲句子SSS出现的概率定义如下:
P(S)=P(w1)P(w2∣w1)...P(wn∣w1,w2,...wn−1)P(S) = P(w_1)P(w_2|w_1)...P(w_n|w_1,w_2,...w_n-1)P(S)=P(w1)P(w2w1)...P(wnw1,w2,...wn1)

  特别地,当i=1i=1i=1时,P(w1∣w0)=P(w1)P(w_1|w_0) = P(w_1)P(w1w0)=P(w1),概率定义与条件概率相同。
  在统计语言模型中,输入是句子SSS,输出是句子SSS的概率P(S)P(S)P(S),模型参数是各个PPP,即P(wi∣w1,w2,...,wi−1)P(w_i|w_1,w_2,...,w_{i-1})P(wiw1,w2,...,wi1)

  wiw_iwi被称为统计基元,可以是字、词、短语、词类等等,通常以“词”代替;

  wiw_iwiw1,w2,...wi−1w_1,w_2,...w_{i-1}w1,w2,...wi1决定,由特定一组w1,w2,...wi−1w_1,w_2,...w_{i-1}w1,w2,...wi1构成的一个序列称为wiw_iwi的历史。
  说到这里,相信大家已经发现了一个很现实却很重要的问题:在这个模型中,参数的数量也太多了!

  假设我们的统计基元个数为LLL(在这里可以将其理解为词汇表),那么一句话中的第iii个基元就有L(i−1)L(i-1)L(i1)种不同的历史情况。我们必须考虑到这所有不同的历史情况下产生第iii个基元的概率,于是,对于长度为mmm的句子,模型中有LmL^mLm个自由参数P(wm∣w1…wm−1)P(w_m|w_1…w_{m-1})P(wmw1wm1)

  这样算来,这会是一个很可怕的参数数量,假设L=5000L = 5000L=5000(词汇表中的词数有5000不过分吧),m=3m = 3m=3,模型中的自由参数就达到了1250亿!这还仅仅是对应着一个三个词的句子,而汉语中平均每句话中有22个词,这将是一个天文数字。

  要解决这个问题,就要减少历史基元的个数,也就是减少决定wiw_iwi的历史词的数目。

  等等!看到这里,是不是有点熟悉,这不就是大名鼎鼎的马尔可夫链嘛!(不熟悉马尔可夫链的朋友们可以自行百度一下~)

  没错,我们称其为马尔可夫方法:假设任意一个词wiw_iwi出现的概率只与它前面的wi−1w_{i-1}wi1有关,将原模型简化为二元模型:

P(S)=P(w1)P(w2∣w1)...P(wi∣wi−1)...P(wn∣wn−1)P(S) = P(w_1)P(w_2|w_1)...P(w_i|w_{i-1})...P(w_n|w_{n-1})P(S)=P(w1)P(w2w1)...P(wiwi1)...P(wnwn1)

  在此基础上,提出nnn元文法(n-gram):一个词由它前面的n−1n-1n1个词决定(注意,是n−1n-1n1哦,不是nnn)。

  • 一元文法(1-gram):n=1,P(wi∣w1,w2,...,wi−1)=P(wi)n=1,P(w_i|w_1,w_2,...,w_{i-1}) = P(w_i)n=1P(wiw1,w2,...,wi1)=P(wi),出现在每一位上的基元wiw_iwi独立于历史;

  • 二元文法(2-gram):n=2,P(wi∣w1,w2,...,wi−1)=P(wi∣wi−1)n=2,P(w_i|w_1,w_2,...,w_i-1) = P(w_i|w_{i-1})n=2P(wiw1,w2,...,wi1)=P(wiwi1),1阶马尔可夫链;

  • 三元文法(3-gram):n=3,P(wi∣w1,w2,...,wi−1)=P(wi∣wi−2,wi−1)n=3,P(w_i|w_1,w_2,...,w_{i-1}) = P(w_i|w_{i-2},w_{i-1})n=3P(wiw1,w2,...,wi1)=P(wiwi2,wi1),2阶马尔可夫链;

  ……

  以此类推。

  理论上讲,nnn元文法中的n越大越好(越能保留句子词之间的相关性),但是正如上文所说,nnn越大也就意味着需要估计的参数越多。一般来讲,n=3n=3n=3用得相对较多,n=4n=4n=4的时候参数就已经太多了。

  值得注意的是,即使采用n较大的高阶模型,也无法覆盖全部的语言现象(因为现阶段,对于人类来讲,语言依然是一个谜)。

  了解了语言模型之后,问题来了:如何估计语言模型的参数呢?(用于计算P(S)P(S)P(S)的各个P(wi∣wi−n+1,...,wi−1)P(w_i|w_{i-n+1},...,w_{i-1})P(wiwin+1,...,wi1)

  利用极大似然估计(Maximum Likelihood Evaluation,MLE)。

  从个人理解的角度出发,我认为利用极大似然估计在语料中统计语言模型参数的过程,可以形象化地概括为两个字:数(三声)数(四声)。

  极大似然估计的过程大致如下:

  假设我们的语料库中只有三句话(语料库的概念将在后面进行介绍):

  1. John read Moby Dick
  2. Mary read a different book
  3. She read a book by Cher

  现在,我们想要估计2-gram模型中,‘John read a book’ 这句话出现的概率。

P(‘John read a book’)=P(John∣<BOS>)P(read∣John)P(a∣read)P(book∣a)P(<EOS>∣book)P(‘John\ read\ a\ book’ ) = P(John|<BOS>)P(read|John)P(a|read)P(book|a)P(<EOS>| book)P(John read a book)=P(John<BOS>)P(readJohn)P(aread)P(booka)P(<EOS>book),其中<BOS><BOS><BOS><EOS><EOS><EOS>分别表示句子的开始符和结束符。

  我们可以从语料中(1,2,3一共三句话)统计得到:

  P(John∣<BOS>)=1/3P(John|<BOS>) = 1/3P(John<BOS>)=1/3,因为<BOS><BOS><BOS>出现了三次(每个句子的开始),后面接John的有一次——即,John出现在句首;

  P(read∣John)=1/1P(read|John) = 1/1P(readJohn)=1/1,因为John出现了一次,后面接read的有一次;

  P(a∣read)=2/3P(a|read) = 2/3P(aread)=2/3,因为read出现了3词,后面接a的有一次;

  P(book|a) = 1/2,因为a出现了2次,后面接book的有一次;

  P(<EOS>∣book)=1/2P(<EOS>| book) = 1/2P(<EOS>book)=1/2,因为book出现了2次,book出现在句子结尾(后面接<EOS><EOS><EOS>)的有1次。

  因此,P(S)=1/18P(S) = 1/18P(S)=1/18

  通过这个小小的例子,我们可以发现,语言模型可以预测句子的下一个词(已知前面的词),也可以计算一句话出现的概率,决定哪一个词序列出现的概率大。

  下面,我们再举一个例子:

  还是上面的语料库,还是使用2-gram,我们想要求‘Cher read a book’的概率。

  看起来没什么问题啊,按着上面的套路做就可以了啊,但是在实际计算的时候我们发现:P(Cher∣<BOS>)=0P(Cher|<BOS>) = 0P(Cher<BOS>)=0,Cher这个词根本就没有出现在句首过!

  这也就意味着,无论后面几个概率值是多少,我们计算出来的整个句子出现的概率都是0。

  这个问题被称为零概率问题,是由数据稀疏(匮乏)造成的。

  那么遇到了这个问题,该如何解决呢?

  进行数据平滑。

  数据平滑的方法有很多种,在这里不一一进行赘述,有兴趣的朋友可以自行百度了解。

  总之,数据平滑之后,不会出现上面例子中出现的零概率问题,我们就可以安安心心地用语言模型计算一句话出现的概率啦~

  到这里,对语言模型的介绍就基本结束了,我们还剩下一些边边角角的问题需要解决:比如,如何评价语言模型。

  目前,语言模型的评价一般有两种方法:

  1. 实用方法:通过查看该模型在实际应用(如机器翻译)中的表现来评价,优点是直观、实用,缺点是缺乏针对性、不够客观。

  2. 理论方法:为了评价语言模型,提出了一个“困惑度”的概念,方法如下:

  平滑过后的n-gram模型句子的概率为(与语言模型中的描述相同):P(S)=P(w1)...P(wi∣wi−n+1,...,wi−1)...P(S) = P(w_1)...P(w_i|w_{i-n+1},...,w_{i-1})...P(S)=P(w1)...P(wiwin+1,...,wi1)...

  假设测试语料TTTkkk个句子t1,t2,...,tkt_1,t_2,...,t_kt1,t2,...,tk构成,那么整个测试集TTT的概率为:p(T)=P(t1)P(t2)...P(tk)p(T) = P(t_1)P(t_2)...P(t_k)p(T)=P(t1)P(t2)...P(tk)

  定义模型对于测试预料的交叉熵为:

Hp(T)=−1Wtlog2p(T)H_p(T) = \frac{- 1}{W_t}log_2p(T)Hp(T)=Wt1log2p(T)

  其中,分母项为测试语料TTT中的词数(可以理解为测试文本集的单词表)。

  定义模型的困惑度为:
PPp(T)=2Hp(T)PP_p(T)=2^{H_p(T)}PPp(T)=2Hp(T)

  困惑度越低,模型评价越高。

  在这里,多说几句题外话:

  对于一个模型而言,最重要的部分有四个:输入、输出、参数、对应关系(函数)。

  对于任何一个模型而言,把握住这四个基本要素,相信会帮助大家理解得更加透彻(特别是今后我们会提到的神经网络)。

2. 语料库(corpus)

  语料库是什么?
  语料库就是,存放在计算机里的原始语料文本 或 经过加工后带有语言学信息标注的语料文本。为了方便理解,我们可以将其看作一个数据库,我们从中提取语言数据,以便对其进行分析、处理。
语料库有三点特征:

  1. 语料库中存放的是在实际使用中真是出现过的语言材料。
  2. 语料库是以计算机为载体承载语言知识的基础资源,但并不等于语言知识。
  3. 真实语料需要经过分析、处理和加工,才能成为有用的资源。(这一点尤为重要,在NLP知识的学习中,需要对语言原材料进行一系列的处理才能够使用)

  在这里,不对语料库进行系统的介绍,仅需要了解“我们可以从中提取语言数据来用”就可以啦~
  如果有朋友对语料库的分类和现阶段一些著名的语料库感兴趣,可以自行百度了解~

3. 参考文献

[1] https://blog.csdn.net/echoKangYL/article/details/86626714

Logo

CSDN联合极客时间,共同打造面向开发者的精品内容学习社区,助力成长!

更多推荐