一、N-gram语言模型
- 语言模型(
Language Model
,LM
)的一个常见任务,是已知一句话的前面几个词,预测下一个是什么,即对 建模 -
N-gram语言模型,是基于Markov假设,假设文本中的每个词只与前面的n-1个词有关,即
这可以通过对训练语料做极大似然估计,
-
由此我们可以求一段文本(句子) 的概率
- 首先在句子的首尾增加两个特殊标记
-
再通过链式法则,以bigram(n=2)为例,
- 这里忽略 ,因为始终等于1
- 这里一共是
项(与很多地方说的都不一样)
- 不能没有
- 可以证明,对于一个固定长度
,所有可能句子
的概率之和,即
- 那么对于不同长度的句子集合,即“所有可能的句子”,其概率之和 > 1
- 可以证明,对于一个固定长度
,所有可能句子
的概率之和,即
- 不能没有
- 通常,为了防止概率(<1)连乘 导致浮点underflow,对其取对数,这样乘法就变成了加法
二、Perplexity(困惑度)
刚才我们通过训练集得到了语言模型,而perplexity是一种评价语言模型在测试集上表现的方法
- 对一句句子来说,
-
对于bigram LM来说,就是
-
对于整个测试集,我们再对所有句子的perplexity,求几何平均,得到整体的结果
这里用 表示所有测试集中句子长度之和,即 , -
解释
- 注意上面的指数表达形式,其中 可以理解为(对词平均的)交叉熵(cross-entropy),也就是
- 这里 是经验分布,即 , , 表示其信息量(编码长度,惊讶程度(?))
- 所以,perplexity就是在某种编码方式(语言模型)下评估测试集的平均编码长度(平均惊讶程度(?)),也就是交叉熵的含义
- LM拟合得越好,即模型越贴近真实分布
,perplexity(交叉熵)越小,KL散度越小,越接近真实分布的熵
- 注意
- 不同LM比较时,需要有相同的词表,否则比较结果可能会不可靠
- 举个极端的例子:某个模型中词表中只包含两个词:“的” 和 (下面提到的OOV的一种处理方式,可以看做一个特殊词),因为两者出现的次数都足够多,那么其LM必然是很准的
- 不同LM比较时,需要有相同的词表,否则比较结果可能会不可靠
三、平滑方法
PS:以下对”ngram”和”词”不做区分
问题
- 假如我们词表的大小是50万,则要覆盖所有的bigram情况,需要至少2500亿个词的语料,参数必然也是这个数量级;对于trigram(n=3)以及更大的n,还会更大,显然这是不现实的
- 很多的词不会相邻出现,即大部分
(稀疏),另外,还有很多训练语料中不存在(
OOV
,Out-of-vocabulary
) 的词 - 所以,如果训练语料数量不够大,或者词表不够全,得到的语言模型容易出现过拟合
常用方法
Laplace平滑 (add-one, add-α)
其中
- 时,即为不做平滑的结果
- 时,即为常说的add-one
- 两类词
- 对于
词表内
的词, ,也就是说,在做了平滑之后,表内词概率和为1(也就是说算上OOV所有可能出现的词概率之和>1 !)- 可以理解为一个利用了 Dirichlet-Multinomial 共轭 的MAP(最大后验估计)
- 假设词表的先验分布 ,其中 是长度为 ,元素都是1的向量(不考虑OOV)(从期望上看,各个词是相等的)
- 语料中的词 服从多项分布
- 则词的后验分布为 ,期望为上面的
- 可以理解为一个利用了 Dirichlet-Multinomial 共轭 的MAP(最大后验估计)
- 对于
OOV
的词, , 的选择可以用cross-validation
- 对于
Good-Turing Smoothing
- 假设语料中出现了
次的词有
(出现
次的词的集合大小),语料大小为
,则
- 考虑unigram(n=1),出现 次的所有词,其概率为
- 当
较小时,极大似然估计可能不准确,同时我们也要考虑一下那些没有出现(
)的词,从而我们给所有
打一个“折扣”(discount),
容易证明, - 根据Zipf’s law, 越大, 越小,所以,一般情况下,
- 可以证明,
- 因为有未知的信息(unseen ngram),所以观测的统计量的方差较大(但仍是无偏的),所以设计一个条件概率来减小方差(?)
Backoff (Katz)
上面的两种处理方式,是对原先概率为0的情况作了一刀切地处理,但是有些ngram其实比另一些更有可能出现,所以这么做肯定不那么准确。由此,我们分两种情况:
- 对于见过的ngram,优先用训练语料来拟合
- 对于unseen-ngram,取折扣因子(discounting factor)为剩下的概率,再递归地去寻找 (n-1)-gram(回退补偿,backoff)
- 这里的 可以通过上面的Good-Turing Smoothing得到
- 因为没有加入 的情况,所以概率之和<1,剩下的部分就尽量匀给第二种情况,即
Interpolation(Jelinek-Mercer)
除了backoff之外,另一种利用多层context的方法是做插值,两者的不同在于
- backoff在“证据充分”的情况下,会尽量用ngram直接估计,不行才会求助于更短的上下文
- 而插值法每次都会综合多个层次,这对于数据量少时减少过拟合很有用
以trigram为例,
- 其中 也可以和上文(context)有关,即
Recursive Interpolation
递归地调用插值法
Absolute Discounting
上面的很多做法都需要对训练集中的ngram做discount,把剩下的概率匀给unseen ngram。
Church & Gale (1991) 做了一项实验,他们将语料库分成大小相同的两部分(训练集和验证集分别有2200万),观察那些在训练集中出现了
次的bigram 在验证集中平均出现的次数。
下面给出不同的
的结果,
可以看出,除了
的bigram之外,验证集中的平均出现次数,都约等于
。
和Good-Turing Smoothing不同的是,Absolute discounting 直接对
进行某种确定性的操作,不依赖于训练集的
。
照着这个思路,
- 其中, 可以根据 设置不同的值
- 注意右边的第二个插值项(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)数量
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)的可能性
- 然后,我们normalize一下
-
从而,我们有
- 这里,我们用 代替了unigram
- 如果用的 是一样的,那么
-
对于更高阶的ngram,我们可以用递归的方式
- 其中,
- 解释一下,因为采用了递归形式,原先的第二项 没有了;为了能用第一项的形式表达continuation,对于低阶的ngram,其count要用计算continuation时的方法
- 其中,
- 如果不限制 是固定的,而采用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处理
- 因为没有对seen ngram做discount,所以总的概率之和>1,这里用 而不是 来表示
- 论文中, 一刀切用了0.4
- 对大规模语料,ngram的抽取可以用map-reduce并行处理加快速度
小结
- backoff/interpolation很管用,能尽可能地利用低阶信息,减少过拟合
- 在训练集比较小时,插值法更好一些
- 在训练集比较大时,backoff 可以直接用高阶的信息,所以效果会更好
- 具体的参数选择,需要通过在验证集上的表现决定