重新理解n-gram：从统计到深度学习的桥梁

最近在梳理早期 NLP 技术时，重新归纳了 n-gram 模型。虽然现在更关注 Transformer 等架构，但回头看这些 "古老" 的方法，其实能学到很多东西。

n-gram 的基本思想

n-gram 的核心想法其实很直观：一个词出现的概率只取决于它前面的几个词（具体来说是前 n-1 个词）。这听起来像是对语言的简化，但人类说话时确实经常基于前面的词来选择后面的词。

几种常用的 n-gram 模型：

Unigram：每个词独立出现，不考虑上下文

Bigram：每个词只看前面 1 个词

Trigram：每个词看前面 2 个词

刚开始接触时会觉得这种假设太粗糙了，但实际上这种简化在很多场景下是有效的。

马尔可夫假设

n-gram 背后的理论基础是马尔可夫假设。数学表达为：

P(x i+1∣xi,x i−1,x i−2...)=P(x i+1∣xi)P(x_{i+1}|x_{i},x_{i-1},x_{i-2}...) = P(x_{i+1}|x_{i})P(xi+1​∣xi​,xi−1​,xi−2​...)=P(xi+1​∣xi​)

这个假设的关键是 "无记忆性"—— 下一个状态只依赖当前状态，不依赖历史路径。

举例计算 "I love deep learning" 的概率：

Bigram 计算：
P("Ilovedeeplearning")=P("I")×P("love"∣"I")×P("deep"∣"love")×P("learning"∣"deep")P("I love deep learning") = P("I") \times P("love"|"I") \times P("deep"|"love") \times P("learning"|"deep")P("Ilovedeeplearning")=P("I")×P("love"∣"I")×P("deep"∣"love")×P("learning"∣"deep")

Trigram 计算：
P("Ilovedeeplearning")=P("I")×P("love"∣"I")×P("deep"∣"Ilove")×P("learning"∣"lovedeep")P("I love deep learning") = P("I") \times P("love"|"I") \times P("deep"|"I love") \times P("learning"|"love deep")P("Ilovedeeplearning")=P("I")×P("love"∣"I")×P("deep"∣"Ilove")×P("learning"∣"lovedeep")

复杂的句子概率被分解成了简单的条件概率乘积，这种分解方式既优雅又实用。

数据稀疏性问题

n-gram 有个很现实的问题：数据稀疏性。如果某个词组合在训练数据中没出现过，它的概率就是 0，这会让整个句子概率变成 0。

为了解决这个问题，前人想出了几种平滑策略：

加一平滑

给所有词的计数都加 1，这样就不会有 0 概率了。

加 K 平滑

是加一平滑的推广版本，通过调整 K 值来控制平滑程度，效果上比加一平滑要好一些。

加一平滑是加 K 平滑的特例，使用加 K 平滑，K 的取值具体关注于训练数据，需要在验证集上进行调优。

当训练数据数量较小时，可能会出现一些极端的分布，这时 K 值一般取较大，以平衡每个词的出现概率。

当训练数据量较大时，使用较小的 K 值以保持原始的统计分布。

Kneser-Ney 平滑

更复杂但效果更好的方法，考虑了词在不同上下文中的分布。

这些平滑方法体现了早期 NLP 研究者的实用精神 —— 遇到问题就想办法解决，不纠结于理论的完美性。

n-gram 的特点

简单有效：虽然假设简单，但在很多任务上效果不错。现在的输入法、拼写检查还在用类似的技术。

计算友好：训练和推理都很快，这在计算资源有限的年代很重要。

局限明显：无法处理长距离依赖是个根本问题。比如 "昨天下雨... 今天很累"，这种跨越多个词的语义关系 n-gram 就捕捉不到。

从 n-gram 到现代模型

现在回头看，n-gram 其实为后来的模型奠定了重要基础：

概率建模思路：把语言看作概率分布，这个思想一直延续到现在

序列预测框架：基于历史预测未来的基本框架

统计学习方法：从数据中学习规律的方法论

即使是最新的大语言模型，本质上还是在做类似的事情 —— 基于前面的 token 预测下一个 token。只是现在的模型能够考虑更长的上下文，捕捉更复杂的依赖关系。

技术演进的思考

理解技术发展的历史脉络很重要。现在的很多 "创新" 其实都能在早期技术中找到影子。n-gram 虽然简单，但它体现的核心思想 —— 通过统计规律来理解和预测语言 —— 至今仍然有效。

就像学数学一样，掌握基础概念比追求最新最复杂的技术更重要。n-gram 不是最强的模型，但它提供了一个很好的思考框架，帮助理解语言建模的本质。

技术的进步是渐进的，每一代技术都在前一代的基础上改进。n-gram 教会我们如何用概率的眼光看待语言，这个视角在今天仍然很有价值。而且简单的方法往往能够揭示深层的规律，理解问题的本质比追求复杂的解决方案更加重要。

动手实现

参考 Github 仓库