Skip to article frontmatterSkip to article content
Site not loading correctly?

This may be due to an incorrect BASE_URL configuration. See the MyST Documentation for reference.

3.6 平滑、插值与回退

使用最大似然概率估计存在一个问题:任何有限训练语料库都会漏掉一些完全合理的英语词序列。也就是说,某个 n 元语法可能从未出现在训练数据中,却出现在测试集中。例如,训练语料库可能同时包含 ruby 和 slippers,却恰好没有短语 ruby slippers。

这些未见序列(unseen sequence)或零计数(zero),即训练集中没有、测试集中却出现的序列,会造成两个问题。第一,它们意味着我们低估了实际可能出现的词序列概率,从而损害任何使用这些数据之应用的性能。第二,只要测试集中的一个词概率为 0,整个测试集的概率就是 0。困惑度依据测试集概率的倒数定义;如果某些上下文中的词概率为零,就会发生除以零,根本无法计算困惑度。

处理理论上应当具有非零概率的“零概率 n 元语法”,标准方法称为平滑(smoothing)或折扣(discounting)。平滑算法从一些较频繁事件中削减少量概率质量,再把它分给未见事件。这里介绍几种简单的平滑算法:Laplace(加一)平滑、加 kk 平滑、n 元插值和笨拙回退。

3.6.1 Laplace 平滑

最简单的平滑方法是在把 n 元计数归一化为概率之前,先为所有计数加一。原本为 0 的计数变成 1,原本为 1 的变成 2,依此类推。这种算法称为 Laplace 平滑(Laplace smoothing)。Laplace 平滑的表现不足以用于现代 n 元模型,但它能有效引出其他平滑算法中的许多概念,提供一个实用基线,而且在文本分类(附录 B)等其他任务中仍是一种实用平滑算法。

先把 Laplace 平滑应用于一元概率。回想一下,词 wiw_i 的未平滑最大似然一元概率估计,是其计数 cic_i 除以词元总数 NN

P(wi)=ciNP (w _ {i}) = \frac {c _ {i}}{N}

Laplace 平滑只是为每个计数加一,因此也称加一平滑(add-one smoothing)。由于词表中有 VV 个词,每个词的计数都增加了 1,所以分母也必须加入额外的 VV 次观测。(如果不增大分母,概率值会怎样?)

PLaplace(wi)=ci+1N+V(3.24)P _ {\mathrm{Laplace}} (w _ {i}) = \frac {c _ {i} + 1}{N + V}\tag{3.24}

理解一元情形后,下面对 Berkeley Restaurant Project 的二元语法进行平滑。图 3.6 给出图 3.1 中各二元语法经过加一平滑后的计数。

iwanttoeatchinesefoodlunchspend
i68281101113
want3160927762
to315687317212
eat1131173431
chinese211118321
food1611612511
lunch31111211
spend21211111

图 3.6 Berkeley Restaurant Project 的 9,332 句语料库中,词表 V=1446V=1446 的八个词之二元计数经过加一平滑后的结果。原本为零的计数以灰色表示。

图 3.7 给出图 3.2 中各二元语法经过加一平滑后的概率,使用下文式 3.26 计算。普通二元概率是用所在行的一元计数归一化各项计数:

PMLE(wnwn1)=C(wn1wn)C(wn1)(3.25)P _ {\mathrm{MLE}} (w _ {n} | w _ {n - 1}) = \frac {C (w _ {n - 1} w _ {n})}{C (w _ {n - 1})}\tag{3.25}

对加一平滑后的二元计数,需要在分母的一元计数中加入词表的词类型总数 VV。下面的公式说明了原因:分母的一元计数其实是以 wn1w_{n-1} 开头的所有二元计数之和;由于其中每一项都加一,而这样的项共有 VV 个,所以分母总共增加 VV

P Laplace (wnwn1)=C(wn1wn)+1w(C(wn1w)+1)=C(wn1wn)+1C(wn1)+V(3.26)P _ {\text { Laplace }} \left(w _ {n} \mid w _ {n - 1}\right) = \frac {C \left(w _ {n - 1} w _ {n}\right) + 1}{\sum_ {w} \left(C \left(w _ {n - 1} w\right) + 1\right)} = \frac {C \left(w _ {n - 1} w _ {n}\right) + 1}{C \left(w _ {n - 1}\right) + V}\tag{3.26}

因此,前文给出的每个一元计数都要增加 V=1446V=1446。使用式 3.26 得到图 3.7 中经过平滑的二元概率。

iwanttoeatchinesefoodlunchspend
i0.00150.210.000250.00250.000250.000250.000250.00075
want0.00130.000420.260.000840.00290.00290.00250.00084
to0.000780.000260.00130.180.000780.000260.00180.055
eat0.000460.000460.00140.000460.00780.00140.020.00046
chinese0.00120.000620.000620.000620.000620.0520.00120.00062
food0.00630.000390.00630.000390.000790.0020.000390.00039
lunch0.00170.000560.000560.000560.000560.00110.000560.00056
spend0.00120.000580.00120.000580.000580.000580.000580.00058

图 3.7 使用式 3.26 计算的 BeRP 语料库二元概率之加一平滑结果。原本为零的概率以灰色表示。

一种有用的可视化方法是重建调整计数 CC^*,从而观察平滑算法对原始计数作了多大改变。CC^* 除以 C(wn1)C(w_{n-1}) 后应当得到平滑概率,因此它可以直接与 MLE 计数比较:

P Laplace (wnwn1)=C(wn1wn)+1C(wn1)+V=C(wn1wn)C(wn1)P _ {\text { Laplace }} (w _ {n} | w _ {n - 1}) = \frac {C (w _ {n - 1} w _ {n}) + 1}{C (w _ {n - 1}) + V} = \frac {C ^ {*} (w _ {n - 1} w _ {n})}{C (w _ {n - 1})}

整理各项,可以解出:

C(wn1wn)=[C(wn1wn)+1]×C(wn1)C(wn1)+V(3.27)C ^ {*} (w _ {n - 1} w _ {n}) = \frac {[ C (w _ {n - 1} w _ {n}) + 1 ] \times C (w _ {n - 1})}{C (w _ {n - 1}) + V}\tag{3.27}

图 3.8 给出使用式 3.27 计算的重建计数。

iwanttoeatchinesefoodlunchspend
i3.85270.646.40.640.640.641.9
want1.20.392380.782.72.72.30.78
to1.90.633.14301.90.634.4133
eat0.340.3410.345.81150.34
chinese0.20.0980.0980.0980.0988.20.20.098
food6.90.436.90.430.862.20.430.43
lunch0.570.190.190.190.190.380.190.19
spend0.320.160.320.160.160.160.160.16

图 3.8 使用式 3.27 计算的 BeRP 语料库八个词之加一重建计数。原本为零的计数以灰色表示。

加一平滑对计数作出了非常大的改变。比较图 3.8 与图 3.1 的原始计数可见,C(want to)C(want\ to) 从 608 变成 238;概率空间中,P(towant)P(to|want) 也从未平滑时的 0.66 降到平滑后的 0.26。把新旧计数之比定义为折扣 dd,就能看出每个前缀词的计数下降得多么明显:want to 的折扣为 0.39,Chinese food 的折扣仅为 0.10,缩小了 10 倍。发生这种剧烈变化,是因为过多概率质量被分给了所有零计数项。

3.6.2 加 kk 平滑

加一平滑的一种替代方法,是从已见事件向未见事件转移更少的概率质量。不为每个计数加 1,而是加一个分数计数 kk,例如 0.5 或 0.01。因此,这种算法称为kk 平滑(add-k smoothing)。

PAddk(wnwn1)=C(wn1wn)+kC(wn1)+kV(3.28)P _ {\mathrm{Add-k}} ^ {*} (w _ {n} | w _ {n - 1}) = \frac {C (w _ {n - 1} w _ {n}) + k}{C (w _ {n - 1}) + k V}\tag{3.28}

kk 平滑需要选择 kk 的方法,例如可以在开发集上进行优化。尽管加 kk 对文本分类等任务有用,它在语言建模中的表现仍然不佳,会产生方差不良的计数和往往不合适的折扣(Gale and Church, 1994)。

3.6.3 语言模型插值

要解决零频 n 元语法问题,还可以利用另一种知识来源。如果要计算 P(wnwn2wn1)P(w_n|w_{n-2}w_{n-1}),却没有三元语法 wn2wn1wnw_{n-2}w_{n-1}w_n 的任何实例,可以改用二元概率 P(wnwn1)P(w_n|w_{n-1}) 估计。如果也没有足够计数计算 P(wnwn1)P(w_n|w_{n-1}),则可以使用一元概率 P(wn)P(w_n)。换句话说,对于模型了解不多的上下文,减少上下文有时能够帮助模型更好地泛化。

使用这种 n 元层次最常见的方法称为插值(interpolation):对三元、二元和一元概率加权并组合,计算一个新概率。在简单的线性插值(linear interpolation)中,不同阶的 n 元语法以线性方式插值。三元概率 P(wnwn2wn1)P(w_n|w_{n-2}w_{n-1}) 的估计是分别由 λ\lambda 加权的一元、二元和三元概率之和:

P^(wnwn2wn1)=λ1P(wn)+λ2P(wnwn1)+λ3P(wnwn2wn1)(3.29)\begin{array}{r c l} \hat {P} (w _ {n} | w _ {n - 2} w _ {n - 1}) & = & \lambda_ {1} P (w _ {n}) \\ & & + \lambda_ {2} P (w _ {n} | w _ {n - 1}) \\ & & + \lambda_ {3} P (w _ {n} | w _ {n - 2} w _ {n - 1}) \end{array}\tag{3.29}

各个 λ\lambda 的总和必须为 1,因此式 3.29 等价于加权平均。稍复杂的线性插值会以当前上下文为条件计算每个 λ\lambda 权重。如果某个二元语法的计数特别准确,就可以假定以该二元语法为基础的三元计数更可信,从而为相应三元语法设置更高的 λ\lambda,在插值中赋予它更大权重。式 3.30 给出使用上下文条件化权重的插值公式,其中每个 λ\lambda 的参数都是前两个词构成的上下文:

P^(wnwn2wn1)=λ1(wn2:n1)P(wn)+λ2(wn2:n1)P(wnwn1)+λ3(wn2:n1)P(wnwn2wn1)(3.30)\begin{array}{r c l} \hat {P} (w _ {n} | w _ {n - 2} w _ {n - 1}) & = & \lambda_ {1} (w _ {n - 2: n - 1}) P (w _ {n}) \\ & & + \lambda_ {2} (w _ {n - 2: n - 1}) P (w _ {n} | w _ {n - 1}) \\ & & + \lambda_ {3} (w _ {n - 2: n - 1}) P (w _ {n} | w _ {n - 2} w _ {n - 1}) \end{array}\tag{3.30}

怎样设置这些 λ\lambda 值?无论简单插值还是条件插值,λ\lambda 都从留出语料库(held-out corpus)中学习。留出语料库是一份额外训练语料库;这个名称来自它被留在常规训练数据之外,专门用于设置 λ\lambda[3] 我们选择能够最大化留出语料库似然的 λ\lambda 值:固定 n 元概率,再搜索代入式 3.29 后能为留出集给出最高概率的一组 λ\lambda。求取最优 λ\lambda 的方法有许多,其中一种是 EM 算法;它是一种迭代学习算法,会收敛到局部最优的 λ\lambda(Jelinek and Mercer, 1980)。

3.6.4 笨拙回退

插值的另一种替代方案是回退(backoff)。在回退模型中,如果所需 n 元语法的计数为零,就回退到 (n1)(n-1) 元语法进行近似;继续回退,直到到达具有非零计数的历史。要让回退模型给出正确概率分布,必须对高阶 n 元语法进行折扣,为低阶 n 元语法保留一些概率质量。实践中经常不执行折扣,而使用一种简单得多的无折扣回退算法,称为笨拙回退(stupid backoff)(Brants et al., 2007)。

笨拙回退放弃让语言模型构成真正概率分布的目标,不对高阶概率进行折扣。如果高阶 n 元语法计数为零,就直接回退到低一阶 n 元语法,并乘以固定且不依赖上下文的权重。由于算法不产生概率分布,按照 Brants et al.(2007)的做法,把其分数记作 SS

S(wiwiN+1:i1)={count(wiN+1:i)count(wiN+1:i1)若 count(wiN+1:i)>0λS(wiwiN+2:i1)否则(3.31)S (w _ {i} | w _ {i - N + 1: i - 1}) = \left\{ \begin{array}{l l} \frac {\operatorname{count} (w _ {i - N + 1 : i})}{\operatorname{count} (w _ {i - N + 1 : i - 1})} & \text {若 } \operatorname{count} (w _ {i - N + 1: i}) > 0 \\ \lambda S (w _ {i} | w _ {i - N + 2: i - 1}) & \text {否则} \end{array} \right.\tag{3.31}

回退最终在一元语法处终止,其分数为 S(w)=count(w)/NS(w)=\operatorname{count}(w)/N。Brants et al.(2007)发现,λ=0.4\lambda=0.4 的效果良好。

Footnotes
  1. 留出语料库通常用于设置超参数(hyperparameter)。超参数是一类特殊参数,不同于从训练数据中学习的普通计数;我们将在第 6 章讨论超参数。