语言模型的定义#
语言模型(Language Model, LM)对语言符号 序列 的概率分布进行建模。给定一个词序列 w1,w2,…,wN,语言模型要估计它的联合概率:
P(w1,w2,…,wN)利用概率链式法则,联合概率可以写成条件概率的乘积:
P(w1,…,wN)=i=1∏NP(wi∣w1,…,wi−1)因此,语言建模的核心是估计“在给定全部历史的情况下,下一个词出现的概率”。这个概率既可以用于计算一个句子的合理性,也可以用于生成文本:每一步从条件分布中采样或取概率最大的词。
n-gram 模型#
直接估计 P(wi∣w1,…,wi−1) 需要枚举任意长的历史,参数空间无法承受。n-gram 模型引入 马尔可夫假设:一个词出现的概率只取决于它前面最近的 n−1 个词。
P(wi∣w1,…,wi−1)≈P(wi∣wi−n+1,…,wi−1)于是整个序列的概率近似为:
P(w1,…,wN)≈i=1∏NP(wi∣wi−n+1,…,wi−1)
- n=1:unigram,词与词独立,只看词频。
- n=2:bigram,当前词只看前一个词。
- n=3:trigram,当前词看前两个词。
n 越大,模型能利用的上下文越长,但参数数量和数据稀疏问题也随之加剧。n-gram 的参数通常用极大似然估计(MLE)得到:
P(wi∣wi−n+1,…,wi−1)=count(wi−n+1,…,wi−1)count(wi−n+1,…,wi)一个 bigram 的例子#
取一个很小的语料:
总词数为 9。unigram 与 bigram 的频数如下:
| unigram | 频数 | 概率 | bigram | 频数 |
|---|
| 我 | 2 | 2/9 | 我 喜欢 | 2 |
| 喜欢 | 3 | 3/9 | 喜欢 苹果 | 2 |
| 苹果 | 2 | 2/9 | 喜欢 香蕉 | 1 |
| 香蕉 | 1 | 1/9 | 他 喜欢 | 1 |
| 他 | 1 | 1/9 | | |
由 bigram 频数可以算出条件概率:
P(喜欢|我) = count(我 喜欢) / count(我) = 2/2 = 1
P(苹果|喜欢) = count(喜欢 苹果) / count(喜欢) = 2/3
P(香蕉|喜欢) = count(喜欢 香蕉) / count(喜欢) = 1/3
P(喜欢|他) = count(他 喜欢) / count(他) = 1/1
对于测试句“我喜欢苹果”:
P_uni(我 喜欢 苹果) = 2/9 × 3/9 × 2/9 = 12/729
P_bi(我 喜欢 苹果) = 2/9 × 1 × 2/3 = 4/27
bigram 给了一个高得多的概率,因为它利用了词序信息。
用困惑度评价语言模型#
语言模型的常用内在评价指标是 困惑度(Perplexity, PPL)。给定长度为 N 的测试序列:
PPL(W)=P(w1,…,wN)−1/N=exp(−N1i=1∑NlogP(wi∣w<i))困惑度可以理解为模型在每一步“平均要在多少个候选词中犹豫”。困惑度越低,模型对测试数据的预测越好。它本质上是测试集上平均负对数似然(交叉熵)的指数,详细推导见 困惑度。
要注意,困惑度只在相同的词表和分词方式下可比;不同 tokenizer 的困惑度不能直接比较。
数据稀疏与零概率#
n-gram 的 MLE 有一个致命问题:训练集中没有出现过的 n-gram,其概率为 0。只要测试句包含一个未见过的 bigram,整句概率就会变成 0,困惑度变成无穷大。
此外,多个概率连乘容易造成数值下溢,实际计算时通常在对数空间求和。
解决零概率问题的技术统称为 数据平滑(Smoothing):从高频事件中“借”一部分概率质量,分配给未观察到的事件。
加一与加 k 平滑#
最简单的平滑是加一平滑(Laplace smoothing):假设每个 n-gram 至少额外出现一次。
Padd-1(wi∣wi−1)=count(wi−1)+Vcount(wi−1,wi)+1其中 V 是词表大小。分母加 V 是为了保证所有条件概率之和为 1。
加一平滑对高频词影响不大,但对低频词和未登录词会“过度分配”概率,反而伤害模型。把 1 换成更小的 k 得到加 k 平滑:
Padd-k(wi∣wi−1)=count(wi−1)+kVcount(wi−1,wi)+kk 通常取 0<k<1。加 k 平滑简单,但在大词表上仍然不够精细。
插值与回退#
插值(Interpolation)把不同阶的 n-gram 概率加权组合,让高阶模型在数据充足时发挥作用,低阶模型在数据稀疏时兜底。以 trigram 为例:
P(wi∣wi−2,wi−1)=λ3P(wi∣wi−2,wi−1)+λ2P(wi∣wi−1)+λ1P(wi)其中 λ1+λ2+λ3=1。权重可以固定,也可以根据语料用 EM 算法学习。
回退(Backoff)则不混合,而是按阶数从高到低尝试:高阶 n-gram 计数为 0 时,退到低阶;如果低阶也为 0,再继续退。Katz 回退会给低阶概率乘一个折扣因子,保证整体概率归一化:
PKatz(wi∣wi−1)=⎩⎨⎧d⋅count(wi−1)count(wi−1,wi),α(wi−1)⋅PKatz(wi),count(wi−1,wi)>0count(wi−1,wi)=0
Good-Turing 平滑#
Good-Turing 的核心思想是:用“出现 r+1 次的 n-gram 数量”来估计“出现 r 次的 n-gram 应该分配多少概率”。令 Nr 表示恰好出现 r 次的 n-gram 种类数,则调整后的计数为:
r∗=(r+1)NrNr+1概率估计为 PGT=r∗/N,其中:
- r∗:调整后的计数;
- N:总的 n-gram 出现次数。
所有未出现的 n-gram 共享的总概率质量约为 N1/N。
Good-Turing 的直觉很优雅,但当 Nr 很小或为 0 时 r∗ 不稳定,实际系统通常会做平滑拟合(如 Simple Good-Turing)。它更多是后续折扣方法的理论基础。
Kneser-Ney 平滑#
Kneser-Ney(KN)是目前最经典的 n-gram 平滑方法之一。它观察到:一个词在低阶模型中出现的次数,不应该按原始词频计算,而应该按它出现在多少个不同的上下文中计算。这个量称为 接续计数(continuation count):
N1+(∙wi)=∣{wi−1:count(wi−1,wi)>0}∣以 bigram 为例,绝对折扣插值的 KN 形式为:
PKN(wi∣wi−1)=count(wi−1)max(count(wi−1,wi)−D, 0)+λ(wi−1)⋅PKN(wi)其中 D 是折扣常数(通常取 0.5 到 0.75 左右),低阶概率用接续计数估计:
PKN(wi)=∑wN1+(∙w)N1+(∙wi)插值权重为:
λ(wi−1)=count(wi−1)D⋅N1+(wi−1∙)其中 N1+(wi−1∙) 表示紧跟在 wi−1 后面、出现过的不同词的数量。
KN 的关键改进在于低阶分布:像 “Francisco” 这样的词,原始词频可能不高,但它几乎只出现在 “San” 后面,接续计数会正确地反映这种上下文专一性。trigram 版本需要递归地对低阶使用接续计数,称为 Modified Kneser-Ney。
平滑方法怎么选#
| 方法 | 核心思想 | 优点 | 局限 |
|---|
| 加一 / 加 k | 给所有事件加一个常数 | 简单、必有正概率 | 大词表上过度平滑 |
| 插值 | 各阶概率加权混合 | 灵活,可学习权重 | 需要调参 |
| 回退 | 高阶为零时退到低阶 | 保留高阶信息 | 需要折扣保证归一化 |
| Good-Turing | 用 Nr+1/Nr 调整计数 | 理论优雅 | 稀疏时 Nr 不稳定 |
| Kneser-Ney | 绝对折扣 + 接续计数 | 实践中效果最好 | 实现较复杂 |
n-gram 平滑只能缓解稀疏,无法从根本上解决“未见过的上下文”问题。神经网络语言模型通过分布式表示和参数共享,把相似的上下文映射到相近的表示,从而获得泛化能力,见 NNLM 与 RNNLM。