语言模型的进化之路:从统计方法到深度学习
语言模型的进化之路:从统计方法到深度学习
当我们与智能助手对话、让机器翻译一段文字、或使用搜索引擎寻找答案时,很少有人会停下来思考这些技术背后经历了怎样的技术演进。事实上,语言模型作为这些应用的核心支撑,其发展历程本身就是一部波澜壮阔的技术革命史。从20世纪50年代诞生之初的简单统计方法,到如今能够理解和生成人类语言的大语言模型,这个领域经历了数次重大范式转换。每一次转换不仅带来了技术的进步,更重要的是改变了我们对于“机器如何理解语言”这一根本问题的认识。
理解语言模型的发展历史,对于深入掌握当代大语言模型技术具有不可替代的价值。这不是因为历史本身重要,而是因为当代技术的每一个设计决策都深深植根于前人的探索之中。当我们理解了在统计语言模型时代研究者们如何艰难地处理维度灾难问题,我们就能更深刻地领会词向量表示为何如此重要;当我们明白循环神经网络如何努力尝试捕捉序列中的时序依赖关系,我们就能更清晰地认识到注意力机制为何能够带来革命性的突破。本章将带领读者沿着技术演进的脉络,系统梳理语言模型从统计方法到深度学习的发展历程,为后续章节的深入讨论奠定坚实的知识基础。
统计语言模型时代:基于频率的语言理解
N-gram模型的基本原理
统计语言模型的核心思想可以追溯到香农(Claude Shannon)在1948年发表的信息论奠基性论文。在那篇论文中,香农提出了使用概率来描述语言的思想,并设想通过马尔可夫过程来模拟文本生成过程。这一思想后来被明确化为N-gram语言模型,成为20世纪后半叶自然语言处理领域的主导方法。
N-gram模型的核心假设非常简单:语言中的每个词都可以根据其前N-1个词来预测。用数学语言来表达,给定一个词序列$w_1, w_2, ..., w_m$,模型计算该序列的概率为:
$$P(w_1, w_2, ..., w_m) = \prod_{i=1}^{m} P(w_i | w_1, ..., w_{i-1})$$
为了简化计算,N-gram模型引入了一个关键假设:第$i$个词的概率仅依赖于其前N-1个词,即:
$$P(w_i | w_1, ..., w_{i-1}) \approx P(w_i | w_{i-N+1}, ..., w_{i-1})$$
当N=1时,模型退化为单词的概率分布,即每个词的出现概率与其在语料库中的频率成正比,这被称为一元模型(Unigram Model)。当N=2时,模型根据前一个词来预测当前词,这就是著名的二元模型(Bigram Model),也称为马尔可夫模型。当N=3时,模型使用前两个词作为上下文,这就是三元模型(Trigram Model)。实践中,N的取值通常不超过5,因为随着N的增大,模型面临的数据稀疏问题会急剧恶化。
让我们通过一个具体的例子来理解N-gram模型的工作原理。考虑句子"The cat sat on the mat"(猫坐在垫子上),使用二元模型,其概率计算过程为:
$$P(\text{"The cat sat on the mat"}) = P(\text{The}|\langle s\rangle) \times P(\text{cat}|\text{The}) \times P(\text{sat}|\text{cat}) \times P(\text{on}|\text{sat}) \times P(\text{the}|\text{on}) \times P(\text{mat}|\text{the}) \times P(\langle/s\rangle|\text{mat})$$
其中$\langle s\rangle$和$\/s\rangle$分别表示句子的开始和结束标记。这些条件概率可以从大规模语料库中通过最大似然估计(Maximum Likelihood Estimation, MLE)计算得到:
$$P(w_i | w_{i-1}) = \frac{\text{count}(w_{i-1}, w_i)}{\text{count}(w_{i-1})}$$
这里的$\text{count}(\cdot)$表示在语料库中观察到的词对或单词的频次。
N-gram模型在机器翻译、语音识别、拼写检查等任务中取得了巨大成功。在机器翻译中,模型可以评估候选译文的流畅度;在语音识别中,它可以区分发音相似但语义不同的句子;在拼写检查中,它能够根据上下文推荐正确的单词。这些应用的共同特点是:不需要深入理解语言的深层语义,只需要利用表层的统计规律就能获得有价值的结果。
平滑技术:对抗数据稀疏
N-gram模型的致命弱点在于数据稀疏问题。语言的组合空间是巨大的——即使是英语中常用的数万词汇,二元组合的可能性也达到数十亿级别,三元组合更是天文数字。对于任何一个中等规模的语料库来说,绝大部分可能的N-gram组合根本不会出现,相应的概率会被估计为0。然而,零概率并不意味着这些组合永远不会出现;它们只是在我们有限的训练数据中没有被观察到而已。
为了解决这个问题,研究者们发展出了一系列平滑技术(Smoothing Techniques)。平滑的基本思想是将观察到的频率分配给未见事件一些概率质量,从而避免将全部概率质量集中于已经见过的有限模式。
最简单的平滑方法是拉普拉斯平滑(Laplace Smoothing),也称为加一平滑(Add-One Smoothing)。其核心思想是在每个计数上加1,确保所有事件都有非零概率:
$$P_{\text{Laplace}}(w_i | w_{i-1}) = \frac{\text{count}(w_{i-1}, w_i) + 1}{\text{count}(w_{i-1}) + V}$$
其中$V$是词汇表的大小。拉普拉斯平滑简单有效,但它的假设过于强烈——认为所有未见事件的概率相等,且等于每个可见事件增加的概率份额。对于稀疏数据来说,这往往会导致过度惩罚常见模式。
更好的选择是折扣平滑(Discounting Smoothing),其核心思想是从观察到的计数中"折扣"一部分概率,然后将这些概率重新分配给未见事件。Kneser-Ney平滑是这类方法中最著名的代表,它由Rey Neser和Kenneth Church在1995年提出,至今仍被广泛使用。
Kneser-Ney平滑的核心创新在于它对未见事件的概率估计方式。它不是简单地平均分配折扣概率,而是根据上下文的多样性来分配。具体来说,未见二元组的概率与该词作为不同上下文的"延续词"的能力相关:
$$P_{\text{KN}}(w_i | w_{i-1}) = \frac{\max(\text{count}(w_{i-1}, w_i) - d, 0)}{\text{count}(w_{i-1})} + \lambda(w_{i-1}) \cdot P_{\text{continuation}}(w_i)$$
其中$d$是折扣参数(通常在0.5到0.75之间),$\lambda(w_{i-1})$是归一化常数,$P_{\text{continuation}}(w_i)$表示词$w_i$作为各种上下文延续词的能力。
除了这些经典方法,研究者们还发展了许多其他平滑技术,包括绝对折扣、线性折扣、古德-图灵估计(Good-Turing Estimation)等。每种方法都在计算复杂度和估计准确性之间做出了不同的权衡。
然而,无论平滑技术多么精巧,N-gram模型的本质局限都无法通过技术改进来克服。模型只能捕捉非常局部的表层模式,无法理解词与词之间的语义关系,无法处理长距离的依赖,无法捕捉语言的层次结构。这些根本性的局限驱使研究者们寻找新的方法。
统计方法的局限与反思
让我们更深入地分析统计语言模型的局限性。首先是上下文表示的问题。在N-gram模型中,上下文被简单地表示为词的序列,没有任何抽象和压缩。当N=3时,模型记住了"the cat sat"和"a dog sat"是两个不同的上下文,但无法意识到"cat"和"dog"都属于"动物"这一概念。这意味着模型必须为每一个可能的词汇组合学习一个独立的概率估计,导致学习效率极低。
其次是长距离依赖的问题。在自然语言中,重要的语法和语义关系往往跨越很长的距离。例如,在"The children who the teachers like are happy"这句话中,"children"和"are"之间需要建立主谓一致关系,但它们之间相隔了7个词。对于N-gram模型来说,这种长距离关系完全超出了其捕捉能力。即使我们使用很大的N值(比如N=10),仍然无法可靠地处理这类问题,因为真正的依赖关系可能跨越任意长的距离。
第三是无法处理未见组合问题。即使是最复杂的平滑技术,也无法真正理解为什么"the cat sat on the mat"是合理的,而"the mat sat on the cat"虽然每个三元组都可能被观察到,但整体语义是荒谬的。统计方法只能捕捉表面模式,无法深入到语义层面进行推理。
第四是缺乏泛化能力。N-gram模型无法将从一个语境中学到的知识迁移到另一个类似但不同的语境。例如,如果模型在训练数据中见过"我 吃了 苹果",它应该能够处理"我 吃了 香蕉",但这种泛化能力在N-gram框架下是有限的,因为"吃了 香蕉"可能从未被观察过。
这些局限性在20世纪80年代末到90年代初变得更加明显。当时的研究者开始意识到,如果不能在语言表示层面实现某种形式的"抽象化",统计方法将很快触及天花板。这种认识直接催生了下一波技术浪潮——基于神经网络的语言模型。
词向量表示的革命:从离散符号到连续空间
词嵌入的核心思想
2003年,Bengio等人发表了开创性论文"A Neural Probabilistic Language Model",首次将神经网络引入语言建模。这篇论文的核心贡献不是神经网络本身——神经网络在其他领域早已被使用——而是词向量表示(Word Embedding)的概念。
词向量表示的基本思想是:将每个词映射到一个低维稠密的实数向量空间中。在这个空间里,语义相近的词被映射到相近的位置,从而使得模型能够"理解"词与词之间的语义关系。
形式化地说,假设我们有一个大小为$V$的词汇表,传统方法将每个词表示为一个长度为$V$的one-hot向量,其中只有一个位置为1,其余为0。对于包含10,000个词的词汇表,每个词向量有10,000个维度,而且任意两个不同的词向量之间的点积都为0——这意味着模型无法表达任何词与词之间的相似性或关系。
词嵌入则将每个词映射到一个$d$维的实数向量,其中$d$远小于$V$(通常在50到300之间)。映射函数可以表示为:
$$f: \{w_1, w_2, ..., w_V\} \rightarrow \mathbb{R}^d$$
映射后的向量被称为词向量或词嵌入(Word Embedding)。关键在于,这些向量不是随机分配的,而是通过学习得到的,使得语义相似的词在向量空间中彼此靠近。
这种表示方式带来了革命性的优势。首先是泛化能力的提升:如果"猫"和"狗"的词向量相近,那么模型在"猫"上学到的知识可以自然地迁移到"狗"。其次是维度效率的提升:从$V$维稀疏向量压缩到$d$维稠密向量,大大降低了计算复杂度。第三是能够捕捉词语之间的各种语义关系:通过向量运算可以发现诸如"国王 - 男人 + 女人 ≈ 女王"这样的语义关系。
Word2Vec:简化词向量学习
2013年,Mikolov等人发表了Word2Vec论文,提出了两种简单而高效的学习词向量的方法:Skip-gram和CBOW(Continuous Bag-of-Words)。这两种方法的核心创新在于:通过巧妙的简化,将词向量学习问题转化为一个可计算的任务,使得在数十亿级别的语料上训练成为可能。
Skip-gram模型的核心思想与N-gram模型相反:给定中心词,预测周围的上下文词。对于句子"The quick brown fox jumps",以"brown"为中心词,窗口大小为2时,模型需要预测"quick"、"fox"、"jumps"等上下文词。
Skip-gram模型的结构非常简洁。输入是中心词的one-hot表示,通过一个嵌入矩阵$E \in \mathbb{R}^{V \times d}$投影到$d$维词向量,然后通过另一个投影矩阵$E'$得到每个上下文词的得分,通过softmax函数转换为概率:
$$P(context | center) = \text{softmax}(E' \cdot (E \cdot w_c))$$
模型的参数就是两个投影矩阵$E$和$E'$,它们都包含词向量。训练的目标是最大化真实上下文词的概率。
然而,直接计算softmax需要对所有$V$个词求和,当词汇表很大时这是不可接受的。Word2Vec引入了两种近似方法来加速训练:层次softmax(Hierarchical Softmax)和负采样(Negative Sampling)。
层次softmax使用一棵二叉霍夫曼树来表示词汇表,每个词对应树中的一个叶节点。从根节点到叶节点的路径长度大约与$\log V$成正比,因此计算概率的时间复杂度从$O(V)$降低到$O(\log V)$。更重要的是,霍夫曼树根据词频构建,高频词距离根节点更近,进一步加速了训练。
负采样的核心思想更加巧妙:对于每个训练样本,不是更新所有词的概率,而是采样一小部分"负例"来更新。具体来说,给定一个正样本(中心词-上下文词对),我们采样$k$个负样本(中心词-非上下文词对),然后使用逻辑回归来区分正负样本。目标函数为:
$$J = \log \sigma(v_w'^\top v_c) + \sum_{i=1}^{k} \mathbb{E}_{w_i \sim P_n(w)}[\log \sigma(-v_{w_i}'^\top v_c)]$$
其中$\sigma$是sigmoid函数,$v_c$是中心词的向量,$v_w'$是上下文词(或负样本)的向量,$P_n(w)$是负采样分布(通常使用unigram分布的3/4次幂)。
CBOW模型与Skip-gram相反:给定上下文词,预测中心词。它将上下文中所有词的词向量求和,然后用这个和来预测中心词。CBOW对于高频词训练更快,但在捕捉词与词之间的细粒度关系方面通常不如Skip-gram。
Word2Vec的另一个重要贡献是发现了词向量空间中蕴含的语义结构。Mikolov等人通过类比推理任务验证了词向量的语义属性:
$$\text{vec}("king") - \text{vec}("man") + \text{vec}("woman") \approx \text{vec}("queen")$$
这种"语义算术"现象表明,词向量空间不仅仅是一个便于计算的数据结构,它实际上捕捉了语言中的语义关系结构。类似的例子包括:国家-首都关系(Paris - France + Italy ≈ Rome)、语法时态关系(run - running ≈ walk - walking)等。
GloVe与其他词向量方法
在Word2Vec提出的同时,Pennington等人提出了另一种词向量学习方法——GloVe(Global Vectors for Word Representation)。GloVe的核心思想是结合全局矩阵分解方法和局部上下文方法的优点。
GloVe的创新在于它利用了词共现矩阵的全局统计信息。给定语料库,我们可以统计词$i$出现在词$j$上下文的次数,得到共现矩阵$X$。共现矩阵捕捉了语料库的全局统计特性——它告诉我们哪些词经常一起出现,而这些共现模式本身就编码了丰富的语义信息。
GloVe的目标是学习词向量,使得向量的点积能够近似表示词的共现概率的对数:
$$\text{vec}(w_i)^\top \text{vec}(\tilde{w}_j) + b_i + \tilde{b}_j = \log X_{ij}$$
对应的损失函数为:
$$J = \sum_{i,j=1}^{V} f(X_{ij})(\text{vec}(w_i)^\top \text{vec}(\tilde{w}_j) + b_i + \tilde{b}_j - \log X_{ij})^2$$
其中$f$是一个加权函数,用于降低高频共现词的权重,同时确保未见共现对的损失为零:
$$f(x) = \begin{cases} (x/x_{\max})^\alpha & \text{if } x < x_{\max} \\ 1 & \text{otherwise} \end{cases}$$
GloVe与Word2Vec代表了两种不同的词向量学习范式。Word2Vec通过预测局部上下文来学习词向量,隐式地利用了局部窗口内的词共现信息。GloVe则显式地利用了全局共现统计信息。在实践中,两种方法产生的词向量在下游任务上的表现相近,但各有优势:GloVe在类比推理任务上略胜一筹,而Word2Vec在某些语料上训练更快。
除了这些主流方法,研究者们还提出了许多其他词向量学习技术。传统的矩阵分解方法如LSA(Latent Semantic Analysis)通过对词-文档共现矩阵进行奇异值分解来学习词表示。神经语言模型(如Bengio的原始模型)通过联合学习语言模型参数来得到词向量。这些方法虽然不如Word2Vec和GloVe流行,但在某些场景下仍然有价值。
值得注意的是,词向量表示虽然革命性地提升了语言模型的性能,但它仍然存在明显的局限。最根本的问题是"一词多义"问题:同一个词在不同的上下文中可能具有不同的含义,但传统的词向量将每个词映射为固定的向量,无法区分这些不同的语义。例如,"bank"可以指银行(金融机构)或河岸(地理特征),但词向量方法无法区分这两种用法。这一问题直到后来上下文词向量(如ELMo和BERT)的出现才得到有效解决。
循环神经网络时代:序列建模的兴起
RNN的基本原理与训练
循环神经网络(Recurrent Neural Network, RNN)的引入标志着语言模型从"查表"向"动态计算"的转变。RNN的核心思想是引入隐藏状态(Hidden State)的概念,使得网络能够保持对过去信息的记忆,从而处理任意长度的序列。
RNN的基本结构可以用以下方程描述:
$$h_t = \sigma(W_{xh} \cdot x_t + W_{hh} \cdot h_{t-1} + b_h)$$
$$y_t = W_{hy} \cdot h_t + b_y$$
其中$x_t$是时刻$t$的输入,$h_t$是时刻$t$的隐藏状态,$y_t$是输出,$W$和$b$是网络参数,$\sigma$是激活函数(通常为tanh或ReLU)。关键在于$h_{t-1}$的引入——这使得当前隐藏状态不仅取决于当前输入,还取决于之前的隐藏状