N-gram语言模型 & Perplexity & 平滑

版权声明:本文为博主原创文章,欢迎交流分享,未经博主允许不得转载。 https://blog.csdn.net/qjf42/article/details/79761786

一、N-gram语言模型

  • 语言模型(Language Model,LM)的一个常见任务,是已知一句话的前面几个词,预测下一个是什么,即对 P ( w i | w 1 i 1 ) 建模
  • N-gram语言模型,是基于Markov假设,假设文本中的每个词只与前面的n-1个词有关,即

    P ( w i | w 1 i 1 ) P ( w i | w i n + 1 i 1 ) = P ( w i | w i 1 , , w i n + 1 )

    这可以通过对训练语料做极大似然估计,
    P ( w i | w i n + 1 i 1 ) = C o u n t ( w i , w i 1 , , w i n + 1 ) C o u n t ( w i 1 , , w i n + 1 )

  • 由此我们可以求一段文本(句子) s 的概率

    • 首先在句子的首尾增加两个特殊标记 <s>, </s>
    • 再通过链式法则,以bigram(n=2)为例,

      P ( s ) = P ( <s> , w 1 , , w N , </s> ) = P ( <s> ) P ( w 1 | <s> ) P ( w 2 | w 1 , <s> ) P ( w N | w 1 N 1 , <s> ) P ( </s> | w 1 N , <s> ) = P ( w 1 | <s> ) P ( w 2 | w 1 ) P ( w N | w N 1 ) P ( </s> | w N )

      • 这里忽略 P ( <s> ) ,因为始终等于1
      • 这里一共是 N + 1 (与很多地方说的都不一样)
        • 不能没有 </s>
          • 可以证明,对于一个固定长度 N ,所有可能句子 { S N } 的概率之和,即
            s { S N } P ( <s> , w 1 , , w N ) = 1
          • 那么对于不同长度的句子集合,即“所有可能的句子”,其概率之和 > 1
    • 通常,为了防止概率(<1)连乘 导致浮点underflow,对其取对数,这样乘法就变成了加法
      log P ( s ) = log P ( w 1 | <s> ) + log P ( w 2 | w 1 ) + + log P ( </s> | w N )

二、Perplexity(困惑度)

刚才我们通过训练集得到了语言模型,而perplexity是一种评价语言模型在测试集上表现的方法

  • 对一句句子来说,
    P e r p l e x i t y ( s ) = P ( s ) 1 N + 1 = 2 1 N + 1 log P ( s )
  • 对于bigram LM来说,就是

    1 P ( w 1 | <s> ) P ( w 2 | w 1 ) P ( w N | w N 1 ) P ( </s> | w N ) N + 1

  • 对于整个测试集,我们再对所有句子的perplexity,求几何平均,得到整体的结果
    这里用 N 表示所有测试集中句子长度之和,即 N = ( N k + 1 )

    P e r p l e x i t y = P ( S ) 1 N = 2 1 N log P ( S ) = 2 log P ( s k ) ( N k + 1 )

  • 解释

    • 注意上面的指数表达形式,其中 1 N log p ( S ) 可以理解为(对词平均的)交叉熵(cross-entropy),也就是 H ( q , p ) = q ( w ) log p ( w )
    • 这里 q ( w ) 是经验分布,即 n N n = C o u n t ( w ) log p ( w ) 表示其信息量(编码长度,惊讶程度(?))
    • 所以,perplexity就是在某种编码方式(语言模型)下评估测试集的平均编码长度(平均惊讶程度(?)),也就是交叉熵的含义
    • LM拟合得越好,即模型越贴近真实分布 q ,perplexity(交叉熵)越小,KL散度越小,越接近真实分布的熵
      H ( q , p ) = E q [ log p ] = H ( q ) + D K L ( q p ) H ( q )
  • 注意
    • 不同LM比较时,需要有相同的词表,否则比较结果可能会不可靠
      • 举个极端的例子:某个模型中词表中只包含两个词:“的” 和 <unk> (下面提到的OOV的一种处理方式,可以看做一个特殊词),因为两者出现的次数都足够多,那么其LM必然是很准的

三、平滑方法

PS:以下对”ngram”和”词”不做区分

问题

  • 假如我们词表的大小是50万,则要覆盖所有的bigram情况,需要至少2500亿个词的语料,参数必然也是这个数量级;对于trigram(n=3)以及更大的n,还会更大,显然这是不现实的
  • 很多的词不会相邻出现,即大部分 P ( w i | w i n + 1 i 1 ) = 0 (稀疏),另外,还有很多训练语料中不存在(OOV, Out-of-vocabulary) 的词
  • 所以,如果训练语料数量不够大,或者词表不够全,得到的语言模型容易出现过拟合

常用方法

Laplace平滑 (add-one, add-α)

p = c + α n + α v

其中 0 α 1 ,   v = | V |

  • α = 0 时,即为不做平滑的结果
  • α = 1 时,即为常说的add-one
  • 两类词
    • 对于词表内的词, 1 v p = 1 ,也就是说,在做了平滑之后,表内词概率和为1(也就是说算上OOV所有可能出现的词概率之和>1 !)
      • 可以理解为一个利用了 Dirichlet-Multinomial 共轭 的MAP(最大后验估计)
        • 假设词表的先验分布 P p r i o r D i r ( α I v ) ,其中 I v 是长度为 v ,元素都是1的向量(不考虑OOV)(从期望上看,各个词是相等的)
        • 语料中的词 服从多项分布 P d a t a M u l t ( )
        • 则词的后验分布为 P p o s t D i r ( { c i + α } ) ,期望为上面的 p
    • 对于OOV的词, c = 0 p = α n + α v = 1 n / α + v α 的选择可以用cross-validation
Good-Turing Smoothing
  • 假设语料中出现了 r 次的词有 N r (出现 r 次的词的集合大小),语料大小为 N ,则 N = r = 1 r N r
    • 考虑unigram(n=1),出现 r 次的所有词,其概率为 r N
  • r 较小时,极大似然估计可能不准确,同时我们也要考虑一下那些没有出现( r = 0 )的词,从而我们给所有 r 打一个“折扣”(discount),
    d r = ( r + 1 ) N r + 1 N r

    容易证明, N = r = 0 d r N r
  • 根据Zipf’s law r 越大, N r 越小,所以,一般情况下, r < r
  • 可以证明, d r E ( r ) = E ( c ( w ) | c ( w ) = r )
    • 因为有未知的信息(unseen ngram),所以观测的统计量的方差较大(但仍是无偏的),所以设计一个条件概率来减小方差(?)
Backoff (Katz)

上面的两种处理方式,是对原先概率为0的情况作了一刀切地处理,但是有些ngram其实比另一些更有可能出现,所以这么做肯定不那么准确。由此,我们分两种情况:

  1. 对于见过的ngram,优先用训练语料来拟合
  2. 对于unseen-ngram,取折扣因子(discounting factor)为剩下的概率,再递归地去寻找 (n-1)-gram(回退补偿,backoff)

P B O ( w n | w n N + 1 n 1 ) = { P ( w n | w n N + 1 n 1 ) , i f   C o u n t ( w n N + 1 n ) > 0 α ( w n N + 1 n 1 ) P B O ( w n | w n N + 2 n 1 ) , e l s e

  • 这里的 P ( w n | w n N + 1 n 1 ) 可以通过上面的Good-Turing Smoothing得到
  • 因为没有加入 r = 0 的情况,所以概率之和<1,剩下的部分就尽量匀给第二种情况,即 α ( w n N + 1 n 1 ) = 1 w n P ( w n | w n N + 1 n 1 )
Interpolation(Jelinek-Mercer)

除了backoff之外,另一种利用多层context的方法是做插值,两者的不同在于

  • backoff在“证据充分”的情况下,会尽量用ngram直接估计,不行才会求助于更短的上下文
  • 而插值法每次都会综合多个层次,这对于数据量少时减少过拟合很有用

以trigram为例,

p I ( w n | w n 1 , w n 2 ) = λ 1 p ( w n ) + λ 2 p ( w n | w n 1 ) + λ 3 p ( w n | w n 1 , w n 2 ) s . t       λ 1 + λ 2 + λ 3 = 1

  • 其中 λ 也可以和上文(context)有关,即 λ 1 ( w n 2 n 1 ) , λ 2 ( w n 2 n 1 ) , λ 3 ( w n 2 n 1 )
Recursive Interpolation

递归地调用插值法

p n I ( w i | w i n + 1 i 1 ) = λ ( w i n + 1 i 1 )   p n ( w i | w i n + 1 i 1 ) + ( 1 λ ( w i n + 1 i 1 ) )   p n 1 I ( w i | w i n + 2 i 1 )

Absolute Discounting

上面的很多做法都需要对训练集中的ngram做discount,把剩下的概率匀给unseen ngram。

Church & Gale (1991) 做了一项实验,他们将语料库分成大小相同的两部分(训练集和验证集分别有2200万),观察那些在训练集中出现了 r 次的bigram 在验证集中平均出现的次数
下面给出不同的 r 的结果,
absoulute_discounting
可以看出,除了 r = 0 1 的bigram之外,验证集中的平均出现次数,都约等于 r 0.75
和Good-Turing Smoothing不同的是,Absolute discounting 直接对 r 进行某种确定性的操作,不依赖于训练集的 N r

照着这个思路,
P A D ( w i | w i 1 ) = ( C o u n t ( w i , w i 1 ) d ) / C o u n t ( w i 1 ) + λ ( w i 1 ) P ( w i )

  • 其中, d 可以根据 C o u n t ( w i , w i 1 ) = 0 , 1 2 设置不同的值
  • 注意右边的第二个插值项(Good-Turing 中没有加这个), λ 不是一刀切,和context有关(比如可以用下面的Witten-Bell Smoothing来选择)
Witten-Bell Smoothing

一种确定插值法中 λ 的思路

  • 某些context ngram的下文的选择较少(e.g spite后一般固定搭配跟of),说明一般这个ngram本身会有一些代表性(信息量),需要 λ 大一些
  • 反之,对于一些下文分布的可能性较多的context(e.g constant,常见的形容词),这个context的信息量就比较小,要缩小context看看(甚至不用context),所以反过来 λ 不能太大
  • 具体计算方式,其中考虑每个context的可能的下文(possible extension)数量
    witten_bell
Kneser-Ney discounting
  • 让我们来看一道完形填空: I can’t see without my reading (York/glasses).
    • 该选哪个呢?如果用unigram来选的话,York因为经常以New York的形式出现,且出现次数比glasses多,所以瞎猜的话,更倾向于选这个
    • 但是也正因为York前面能选的并不多,而glasses之前的可能性明显更多一点(the, my, buy, break等),所以从这个角度来说,猜glasses更可能对
  • 所以,与Witten-Bell的思路类似,但我们这里考虑可能的上文,或者说这个词本身作为下文(as continuation)的可能性
    • P c o n t i n u a t i o n ( w ) | { v : C ( v w ) > 0 } |
    • 然后,我们normalize一下
      P c o n t i n u a t i o n ( w ) = | { v : C ( v , w ) > 0 } | | { v , w : C ( v , w ) > 0 } | = C o u n t ( w ) C o u n t ( b i g r a m )
  • 从而,我们有

    P K N ( w i | w i 1 ) = m a x ( C o u n t ( w i , w i 1 ) d , 0 ) C o u n t ( w i 1 ) + λ ( w i 1 ) P c o n t i n u a t i o n ( w i )

    • 这里,我们用 P c o n t i n u a t i o n ( w i ) 代替了unigram P ( w i )
    • 如果用的 d 是一样的,那么 λ ( w i 1 ) = d C o u n t ( w i 1 ) | w : C o u n t ( w i 1 , w ) > 0 |
  • 对于更高阶的ngram,我们可以用递归的方式

    P K N ( w i | w i n + 1 i 1 ) = m a x ( C K N ( w i n + 1 i ) d , 0 ) C K N ( w i n + 1 i 1 ) + λ ( w i n + 1 i 1 ) P K N ( w i | w i n + 2 i 1 )

    • 其中,
      C K N ( ) = { C o u n t ( ) , for the highest order c o n t i n u a t i o n   c o u n t ( ) , for lower order
    • 解释一下,因为采用了递归形式,原先的第二项 P c o n t i n u a t i o n 没有了;为了能用第一项的形式表达continuation,对于低阶的ngram,其count要用计算continuation时的方法
  • 如果不限制 d 是固定的,而采用absolute discounting中区分count为0, 1, >1的方法,那就变成了Modified Kneser-Ney discounting,基本是目前效果最好的平滑方法之一了
Stupid Backoff

google提出的一种面向大型语料库的方法,在语料足够多的情况下,效果可以与Kneser-Ney媲美
(有兴趣可以玩一下google ngram

  • 语料足够时(文中最大1.8万亿tokens,3000亿ngram(n=1-5)),对于seen ngram,直接用极大似然的结果,也能保证方差不会太大
  • 而对于剩下的情况,用最简单的backoff处理
    S ( w n | w n N + 1 n 1 ) = { P ( w n | w n N + 1 n 1 ) , i f   C o u n t ( w n N + 1 n ) > 0 λ ( w n N + 1 n 1 ) S ( w n | w n N + 2 n 1 ) , e l s e
  • 因为没有对seen ngram做discount,所以总的概率之和>1,这里用 S 而不是 P 来表示
  • 论文中, λ 一刀切用了0.4
  • 对大规模语料,ngram的抽取可以用map-reduce并行处理加快速度

小结

  • backoff/interpolation很管用,能尽可能地利用低阶信息,减少过拟合
    • 在训练集比较小时,插值法更好一些
    • 在训练集比较大时,backoff 可以直接用高阶的信息,所以效果会更好
  • 具体的参数选择,需要通过在验证集上的表现决定

四、Reference

猜你喜欢

转载自blog.csdn.net/qjf42/article/details/79761786