语言模型(Language Model, LM)是自然语言处理的核心组件之一。其任务是为一个词序列分配一个概率值,反映这段文本在自然语言中的“合理性”或“常见性”。在本章节中,我们将从基本定义出发,深入讲解语言模型的建模方法(包括 n-gram 模型、链式法则分解、Markov 假设等)、概率计算技巧、数值稳定性对策,以及各类方法的优缺点对比。
语言模型的目标是对一个词序列 w 1 , w 2 , … w_1, w_2, \ldots w1,w2,…计算其联合概率:
P ( w 1 , w 2 , . . . , w N ) P(w_1, w_2, ..., w_N) P(w1,w2,...,wN)
例如:
输入:“We are people.”
输出:一个表示这句话合理性的概率值。
这个概率值可以用于下游多个任务,包括:下一个词预测、拼写纠错、语音识别、机器翻译、文本生成等。
构建一个大表,存储所有可能词序列的概率值,例如 7 个词的组合:
P ( w 1 , w 2 , . . . , w 7 ) P(w_1, w_2, ..., w_7) P(w1,w2,...,w7)
问题:
如果词汇表大小为 ∣ V ∣ = 1 0 4 |V| = 10^4 ∣V∣=104,则可能组合数量为:
∣ V ∣ 7 = 1 0 28 |V|^7 = 10^{28} ∣V∣7=1028
这意味着我们既无法存储这些组合,也无法从语料中统计出全部概率。
根据概率论的链式法则,我们可以将联合概率分解为条件概率的乘积:
P ( w 1 , . . . , w 7 ) = P ( w 1 ) ⋅ P ( w 2 ∣ w 1 ) ⋅ P ( w 3 ∣ w 1 , w 2 ) ⋯ P ( w 7 ∣ w 1 , . . . , w 6 ) P(w_1, ..., w_7) = P(w_1) \cdot P(w_2|w_1) \cdot P(w_3|w_1,w_2) \cdots P(w_7|w_1,...,w_6) P(w1,...,w7)=P(w1)⋅P(w2∣w1)⋅P(w3∣w1,w2)⋯P(w7∣w1,...,w6)
这种做法更合理,因为我们不再建表,而是用模型估计每个词在上下文条件下的概率。
问题:
尽管避免了存储问题,但长距离上下文仍然很难准确估计,如:
P ( w 7 ∣ w 1 , w 2 , . . . , w 6 ) P(w_7 | w_1, w_2, ..., w_6) P(w7∣w1,w2,...,w6)
计算量仍然很大,并存在数据稀疏性问题。
为进一步简化,我们假设:每个词只依赖前面的 n−1 个词(即马尔可夫假设):
Bigram(n=2)模型:
P ( w 1 , . . . , w 7 ) ≈ P ( w 1 ) ⋅ P ( w 2 ∣ w 1 ) ⋅ P ( w 3 ∣ w 2 ) ⋯ P ( w 7 ∣ w 6 ) P(w_1, ..., w_7) \approx P(w_1) \cdot P(w_2|w_1) \cdot P(w_3|w_2) \cdots P(w_7|w_6) P(w1,...,w7)≈P(w1)⋅P(w2∣w1)⋅P(w3∣w2)⋯P(w7∣w6)
Trigram(n=3)模型:
P ( w 1 , . . . , w 7 ) ≈ P ( w 1 ) ⋅ P ( w 2 ∣ w 1 ) ⋅ P ( w 3 ∣ w 1 , w 2 ) ⋯ P ( w 7 ∣ w 5 , w 6 ) P(w_1, ..., w_7) \approx P(w_1) \cdot P(w_2|w_1) \cdot P(w_3|w_1,w_2) \cdots P(w_7|w_5,w_6) P(w1,...,w7)≈P(w1)⋅P(w2∣w1)⋅P(w3∣w1,w2)⋯P(w7∣w5,w6)
马尔可夫假设(Markov Assumption):未来只依赖于当前,不依赖于更久远的过去。
以 bigram 为例:
P ( w n ∣ w 1 , . . . , w n − 1 ) ≈ P ( w n ∣ w n − 1 ) P(w_n | w_1, ..., w_{n-1}) \approx P(w_n | w_{n-1}) P(wn∣w1,...,wn−1)≈P(wn∣wn−1)
✅ 优点:
❌ 缺点:
n-gram 模型中的条件概率通常使用频数估计:
P ( w i ∣ w i − 1 ) = Count ( w i − 1 , w i ) Count ( w i − 1 ) P(w_i | w_{i-1}) = \frac{\text{Count}(w_{i-1}, w_i)}{\text{Count}(w_{i-1})} P(wi∣wi−1)=Count(wi−1)Count(wi−1,wi)
问题:
解决办法:
连续乘积如:
P ( w 1 , . . . , w 100 ) = ( 1 0 − 6 ) 100 = 1 0 − 600 P(w_1, ..., w_{100}) = (10^{-6})^{100} = 10^{-600} P(w1,...,w100)=(10−6)100=10−600
⚠️ 计算机无法表示如此小的数值
✅ 解决方案:使用对数概率(log probability)替代乘积运算:
log P ( w 1 , . . . , w n ) = ∑ i = 1 n log P ( w i ∣ w i − n + 1 , . . . , w i − 1 ) \log P(w_1, ..., w_n) = \sum_{i=1}^{n} \log P(w_i | w_{i-n+1}, ..., w_{i-1}) logP(w1,...,wn)=i=1∑nlogP(wi∣wi−n+1,...,wi−1)
这种做法可避免下溢问题,并将概率乘法转化为更稳定的加法操作。
语言模型需要特殊处理:
和
符号来界定边界方法 | 原理 | 优点 | 缺点 |
---|---|---|---|
查找表法 | 直接存储所有可能的组合概率 | 理论上精确 | 存储需求极高,不现实 |
链式法则 | 分解为条件概率乘积 | 理论上正确 | 上下文过长、稀疏问题 |
n-gram 模型 | 只依赖前 n-1 个词,Markov 假设 | 简单、可训练、可实现 | 忽略长距离依赖、稀疏性 |