课程0基础Agent开发课 / LLM基础 / 从N-gram到Transformer-语言模型的进化史
— 11 min read

从N-gram到Transformer-语言模型的进化史

> **本文适合谁**

从 N-gram 到 Transformer:语言模型的进化史

本文适合谁

想搞清楚"Transformer 为什么比 RNN 更好"、"为什么 LLM 能处理长距离依赖"的开发者。不需要数学背景,用类比和直觉理解每一步演进的必要性。


手机输入法预测下一个字,只能猜到"你好"后面跟"啊"或"吗"。但 GPT 能读完写了一半的需求文档,然后补全另一半,语气、上下文、领域术语都对。

同样是"预测下一个词",差距为何如此之大?

这不是算力的差距,是方法论的差距。语言模型这几十年走了一条清晰的演进路线,每一步都在解决前一步遗留的问题。理清这条线,就能理解为什么 LLM 能做到以前做不到的事。


1.1 N-gram:最朴素的概率模型

1.1.1 马尔可夫假设是什么,为什么它不够用

最早的语言模型基于一个简单假设:一个词出现的概率,只取决于它前面的 N-1 个词。这叫马尔可夫假设(即"未来只取决于当前状态,与更早的历史无关")。

统计时代1980sN-gram统计模型<br/>基于词频共现,马尔可夫假设神经网络时代2003神经网络语言模型NNLM<br/>首次用神经网络建模语言概率2013Word2Vec<br/>分布式词向量表示深度学习时代2014RNN /LSTM<br/>处理序列长程依赖2017Transformer<br/>自注意力机制革命大模型时代2018+GPT /BERT<br/>预训练 +微调范式语言模型进化时间线

图 6.2:语言模型进化时间线——从 N-gram 统计模型到现代大语言模型的六次关键演进

这个假设在工程上非常方便——你只需要统计词组共现频率,就能建立一个语言模型。但它有一个根本性的问题:语言中的依赖关系不是局部的。"那个在会议室里长篇大论了整整两个小时的演讲者,最后他没有说完自己的想法"——要理解最后这个"他"指的是谁,需要回头读十几个词之前的内容。马尔可夫假设说"只看前 N-1 个词",这种长程依赖天然无法处理。

Bigram(N=2)的意思是:每个词只看前一个词。"machine learning" 这个序列里,"learning" 出现的概率就是:

python
from collections import defaultdict

# 训练语料
corpus = [
    "machine learning is powerful",
    "machine learning can solve problems",
    "machine intelligence is advancing",
    "learning can be difficult",
]

# 统计 bigram 频次
bigram_count = defaultdict(int)
unigram_count = defaultdict(int)

for sentence in corpus:
    words = sentence.split()
    for i, word in enumerate(words):
        unigram_count[word] += 1
        if i > 0:
            bigram = (words[i-1], word)
            bigram_count[bigram] += 1

# 计算条件概率 P(learning | machine)
def bigram_prob(word, prev_word):
    return bigram_count[(prev_word, word)] / unigram_count[prev_word]

prob = bigram_prob("learning", "machine")
print(f"P(learning | machine) = {prob:.2f}")  # 2/3 ≈ 0.67

# 预测 "machine" 之后最可能的词
candidates = [(w, bigram_prob(w, "machine")) for (p, w) in bigram_count if p == "machine"]
candidates.sort(key=lambda x: -x[1])
print("machine 之后最可能的词:", candidates)

上面的代码验证了 N-gram 模型的基本工作原理:通过统计词组共现频率,计算条件概率。逻辑清晰,代码简单。但 N-gram 有两个致命缺陷。

数据稀疏。 语言的组合是指数级的。用 Trigram(看前两个词)时,绝大多数三词组合在训练集里根本没出现过,概率直接是 0,模型就废了。这就是数据稀疏问题——词表越大、N越大,未出现过的组合占比越高。加大 N,问题更严重。

无法泛化。 "我喜欢苹果"和"我爱苹果"在 N-gram 看来是完全不同的两个模式,它不知道"喜欢"和"爱"在语义上是近亲。每个词都是独立的符号,模型不理解词与词之间的关系。


1.2 词嵌入:给词一个坐标

1.2.1 为什么需要连续向量空间来表示词义

N-gram 把每个词当作一个独立的符号,"苹果"和"梨"之间的距离,和"苹果"和"汽车"之间的距离完全相同——都是"不同的符号",没有任何近远之分。这导致模型完全无法泛化:学到了"我喜欢苹果",对"我爱梨子"的预测没有任何帮助。

真正的解决方案是改变词的表示方式:不用独立符号,而是用连续向量空间中的点来表示每个词。如果两个词在语义上相近,它们的向量就应该在空间中距离接近。这样,学到了"喜欢"的向量,就可以借助向量空间的几何关系,对"爱"做出合理的预测。

解决"无法泛化"的关键一步是词嵌入(Word Embedding,词向量化)。

把每个词映射到一个高维向量空间里(比如用512个数字来表示一个词,语义由这些数字的组合来表达)。语义相近的词,向量距离近;语义无关的词,向量距离远。

python
import numpy as np

# 假设已经训练好的词向量(简化示意)
word_vectors = {
    "king":   np.array([0.9, 0.1, 0.8, 0.2]),
    "queen":  np.array([0.9, 0.9, 0.8, 0.2]),
    "man":    np.array([0.1, 0.1, 0.8, 0.2]),
    "woman":  np.array([0.1, 0.9, 0.8, 0.2]),
}

def cosine_similarity(a, b):
    return np.dot(a, b) / (np.linalg.norm(a) * np.linalg.norm(b))

# 经典类比:king - man + woman ≈ queen
result = word_vectors["king"] - word_vectors["man"] + word_vectors["woman"]

# 找最近的词
for word, vec in word_vectors.items():
    sim = cosine_similarity(result, vec)
    print(f"{word}: {sim:.4f}")

上面的代码验证了词向量的语义算术性质:将"king"的向量减去"man"再加上"woman",得到的向量最接近"queen"。

Word2Vec(一种将词语映射为向量的训练方法,2013年由Google提出)等方法训练出来的词向量有一个神奇的性质:"king" - "man" + "woman" ≈ "queen"。这意味着向量空间里存在"性别方向"这样的语义轴。模型学到了词与词之间的关系,而不只是把词当作符号。

词嵌入解决了泛化问题。但顺序问题还没解决,语言是有顺序的。


1.3 RNN/LSTM:引入记忆

1.3.1 顺序处理的代价:梯度消失的根本原因

词嵌入让模型能理解词义,但"我爱你"和"你爱我"——同样的词,不同的顺序,意思完全不同。词嵌入本身不感知顺序,我们需要另一套机制来处理序列的时序关系。

循环神经网络(RNN,Recurrent Neural Network)的思路是:维护一个"隐藏状态"(hidden state),把读过的所有词的信息压缩进这个向量。每读一个新词,就把新词和当前隐藏状态一起处理,更新隐藏状态。

code
h_t = f(W_h * h_{t-1} + W_x * x_t)

处理每个词时,既看当前词,也看上一步的隐藏状态。隐藏状态里理论上包含了之前所有词的信息。

RNN 的问题在哪里?梯度消失的根本原因是链式法则的乘法累积。训练神经网络时,需要把误差从输出层反向传播到输入层(反向传播算法)。梯度在每一个时间步都要乘以一个矩阵,如果这个矩阵的特征值小于 1,经过 50 步之后,梯度就变成了一个极小的数——接近于零。靠近输入端的参数因为收不到任何梯度信号,就学不到任何东西。

LSTM(Long Short-Term Memory,长短期记忆网络)用门控机制(类似"记忆开关",决定哪些信息保留、哪些遗忘)缓解了这个问题,但没有根本解决。一个段落里,第一句话的主语影响第十句话的代词指向,这种依赖对 RNN/LSTM 来说还是困难。

还有一个问题:RNN 必须按顺序处理,处理第 t 个词时必须先处理完前 t-1 个词。这导致训练很慢,没法并行。在 GPU 时代,无法并行意味着大量算力被浪费。


1.4 Transformer 革命:任意两词直接交互

1.4.1 自注意力的本质:把"接力传递"变成"直接对话"

RNN 的信息传递模式像一个接力跑:第 1 个词的信息先传给第 2 个词,再传给第 3 个词……每次传递都有信息损耗,到了第 100 个词的时候,第 1 个词的信息已经所剩无几。

Transformer 的自注意力机制彻底打破了这个模式。它说:为什么一定要接力?为什么不能让每个词直接和序列里所有其他词对话?

2017 年,"Attention is All You Need" 这篇论文提出了 Transformer 架构,用自注意力机制替代了循环。

核心思想是:处理每个词时,直接计算它和句子里所有其他词的关联程度,加权融合。不用一步步传递,任意两个词之间直接交互。

这解决了 RNN 的两个问题:长距离依赖和并行计算。"it" 在 "The animal didn't cross the street because it was too tired" 里指哪个词,自注意力可以直接把 "it" 和 "animal"、"street" 同时比较,不需要信息跋山涉水地传递。

位置信息怎么处理?RNN 天然知道顺序(按顺序处理的),但 Transformer 是并行的,需要额外给每个词加上位置编码(Positional Encoding),告诉模型"你是第几个词"。

N-gram
只看前N-1个词
数据稀疏、无法泛化

RNN/LSTM
引入记忆/隐藏状态
梯度消失、难以并行

Transformer
自注意力机制
任意词直接交互、并行计算

GPT/LLM
Decoder-Only架构
自回归生成、涌现能力


1.5 Decoder-Only 架构:GPT 的核心

1.5.1 为什么"只向前看"的设计能产生涌现能力

Transformer 原始论文里有 Encoder 和 Decoder 两部分,用于机器翻译。Encoder 读入源语言,理解整句话的意思;Decoder 根据 Encoder 的输出,逐词生成目标语言。

但 GPT 只用了 Decoder 部分,只做一件事:预测下一个 token。

这个简化看起来是削减了能力,但背后有深刻的设计逻辑。Decoder-Only 的关键设计是掩码自注意力(Masked Self-Attention)。训练时,模型在预测第 t 个词时,只能看到前 t-1 个词,看不到后面的词——用掩码遮住。这样模型学到的是"根据已有内容预测下一个",而不是"看完全文抄答案"。

生成时是自回归的:预测出第一个词,把它拼到输入里,再预测第二个,如此循环。每次都基于之前生成的所有内容继续往后生成。

这个简单的设计,配合足够大的模型和足够多的数据,产生了涌现能力(Emergent Ability,指模型在规模达到某个临界点后突然展现出的、训练时未被明确教过的能力)——规模到一定程度之后,模型突然会做它没被明确训练过的事:推理、写代码、做数学题。

涌现能力是一个令人困惑但至关重要的现象。没有人设计了一个专门用来推理的模块,没有人写了让它会做数学的规则,但通过大量的"预测下一个词"训练,模型学会了这些能力。其背后的机制还没有被完全理解,但这个现象本身已经改变了整个 AI 行业的走向。


1.6 这条演进路线说明了什么

从 N-gram 到 Transformer,每一步都在解决上一步的核心瓶颈:

  • N-gram 解决了最基础的统计建模,但受限于马尔可夫假设——只能看到极短的历史窗口,无法捕捉长程依赖。
  • 词嵌入解决了语义泛化,让相近含义的词在数学空间中也彼此接近,但没有处理顺序和上下文动态信息。
  • RNN 引入了上下文记忆,但梯度消失让它实际上只能记住近期的词,长距离依赖和并行化是硬伤。
  • Transformer 用自注意力同时解决了这两个问题:任意两词之间的注意力计算只有一步,且所有位置可以并行计算。

理解这条线,就能理解 LLM 的能力边界从哪里来。它不是魔法,是一步步工程迭代的结果。下一篇深入 LLM 处理语言的基本单位——Token,到底是什么。


1.7 小结

架构 核心机制 解决了什么 遗留了什么
N-gram 统计词频 最基础的语言概率建模 无法捕捉长程依赖;数据稀疏
词嵌入 向量空间表示词义 语义泛化,相近词距离近 没有处理上下文和顺序
RNN/LSTM 隐藏状态接力传递 引入上下文记忆 梯度消失;无法并行
Transformer 自注意力机制 任意两词直接交互;并行计算 计算量 O(n²),上下文窗口有限
本页目录