数学基础:线性代数、概率论与信息论
数学基础:线性代数、概率论与信息论
引言:数学作为大语言模型的基石
当我们审视现代大语言模型的内部运作机制时,会发现支撑这些复杂系统的底层逻辑其实源自几个经典而优雅的数学分支。线性代数提供了描述和处理高维数据的语言,概率论赋予我们处理不确定性和进行推断的能力,而信息论则揭示了信息编码与传输的本质规律。这些数学工具并非孤立存在,它们在大语言模型的每一个关键环节中交织融合:从词嵌入的向量表示,到注意力机制的张量运算,再到语言建模的损失函数设计,无一不是数学思想的具象化应用。
本章将系统梳理这些数学基础,建立理解后续章节所需的数学素养。我们将从线性代数出发,深入探讨向量空间与矩阵运算的深层含义,特别关注特征值分解与奇异值分解在降维与表示学习中的核心作用。随后转向概率论,阐述条件概率与贝叶斯定理如何为语言建模提供理论基础。最后,本章将重点介绍信息论的核心概念——熵、交叉熵与KL散度,它们构成了现代语言模型损失函数的数学基础。通过这些内容的铺垫,读者将能够更深入地理解注意力机制和Transformer架构的数学本质。
1 线性代数:描述语言的空间语言
1.1 从标量到张量:数据表示的层级演进
在深入探讨线性代数之前,我们有必要先厘清数据表示的基本层级。大语言模型处理的核心数据对象经历了从标量到向量,再到矩阵,最终到高阶张量的层级演进过程。标量作为零阶张量,代表单个数值,如词表中的一个索引;向量作为一阶张量,是一组有序的数值序列,构成了词嵌入的基本单元;矩阵作为二阶张量,可视为向量的集合,常用于表示词与词之间的关联或词与上下文的关系;而张量则是矩阵在更高维度的推广,在现代深度学习框架中,所有的神经网络数据都以张量形式存储和运算。
这种层级演进并非仅仅是形式上的扩展,而是反映了语言数据本质属性的不同侧面。当我们说“语义空间”时,并非只是一种隐喻——词嵌入技术确实将离散的语言符号映射到了连续可计算的向量空间,使得语义相似性可以用向量距离来度量。GPT系列模型中,隐藏状态的维度通常在数千量级,这意味着模型在处理每个token时,实际上是在一个数千维的向量空间中游走。理解这一点,对于把握Transformer架构的工作原理至关重要。
```python import numpy as np
简化的词嵌入示例
vocab_size = 10000 embedding_dim = 768 # GPT-2的嵌入维度
随机初始化词嵌入矩阵
word_embeddings = np.random.randn(vocab_size, embedding_dim)
查看单个词向量
word_id = 42 word_vector = word_embeddings[word_id] print(f"词向量的形状: {word_vector.shape}") print(f"词向量的前10维: {word_vector[:10]}") ```
1.2 向量空间与内积空间:语义运算的几何基础
向量空间(也称为线性空间)是线性代数的研究对象,它由向量构成并满足加法和数乘的封闭性。更重要的是,当我们为向量空间引入内积运算时,就得到了内积空间,这个结构使得我们能够定义向量长度、夹角和距离等几何概念。在语言处理中,内积空间的结构性质被充分利用:两个词向量的内积(点积)越大,其语义相似性通常越高;通过向量减法,我们可以进行语义类比推理,例如“king - man + woman ≈ queen”。
这一几何直觉在BERT等双向编码器模型中得到了充分体现。掩码语言建模(Masked Language Modeling)的训练目标要求模型能够基于上下文预测被掩盖的词,这本质上要求模型学习一种能够保持语义一致性的向量空间结构。双向注意力机制使得每个词的表示能够同时汇聚来自左右两侧的信息,而这种信息汇聚正是通过向量空间中的线性运算实现的。
```python
语义类比示例:king - man + woman ≈ queen
def cosine_similarity(v1, v2): """计算两个向量的余弦相似度""" return np.dot(v1, v2) / (np.linalg.norm(v1) * np.linalg.norm(v2))
假设已有预训练词向量(这里使用随机向量做演示)
np.random.seed(42) dim = 300 king = np.random.randn(dim) man = np.random.randn(dim) woman = np.random.randn(dim) queen = np.random.randn(dim)
语义类比运算
result = king - man + woman
计算与queen的相似度
similarity = cosine_similarity(result, queen) print(f"语义类比相似度: {similarity:.4f}") ```
1.3 矩阵运算:语言模型的核心计算单元
矩阵作为线性代数的核心对象,在大语言模型中扮演着多重角色。首先,词嵌入本身就是以矩阵形式存储的,每个词对应矩阵的一行。其次,神经网络的每一层变换都可以表示为矩阵乘法。设输入向量为 $\mathbf{x} \in \mathbb{R}^n$,权重矩阵为 $\mathbf{W} \in \mathbb{R}^{m \times n}$,偏置向量为 $\mathbf{b} \in \mathbb{R}^m$,则线性变换可表示为:
$$\mathbf{y} = \mathbf{W}\mathbf{x} + \mathbf{b}$$
这个看似简单的表达式实际上是Transformer架构中最基础也最频繁的计算单元。在多头注意力机制中,查询(Query)、键(Key)、值(Value)三个矩阵均通过独立的权重矩阵从输入变换得到:
$$\mathbf{Q} = \mathbf{W}_Q \mathbf{X}, \quad \mathbf{K} = \mathbf{W}_K \mathbf{X}, \quad \mathbf{V} = \mathbf{W}_V \mathbf{X}$$
其中 $\mathbf{X}$ 是输入序列的向量矩阵,每一列对应一个位置或一个词的表示。
矩阵乘法具有一些重要的代数性质,理解这些性质有助于把握神经网络的计算特性。矩阵乘法满足结合律但不满足交换律,这一特性确保了多层网络能够堆叠出复杂的非线性变换,同时使得计算图能够被清晰地定义和反向传播。特别值得注意的是,GPU和TPU等专用硬件在矩阵乘法方面具有极高的计算效率,这也是现代大语言模型得以高效训练的重要硬件基础。
```python
模拟Transformer中的QKV计算
def compute_qkv(X, W_q, W_k, W_v): """ 计算Query, Key, Value矩阵 X: (batch_size, seq_len, hidden_dim) W_q, W_k, W_v: (hidden_dim, head_dim) """ Q = np.einsum('bsh,hc->bsc', X, W_q) K = np.einsum('bsh,hc->bsc', X, W_k) V = np.einsum('bsh,hc->bsc', X, W_v) return Q, K, V
使用numpy演示
batch_size, seq_len, hidden_dim = 4, 16, 64 head_dim = 16
X = np.random.randn(batch_size, seq_len, hidden_dim) W_q = np.random.randn(hidden_dim, head_dim) W_k = np.random.randn(hidden_dim, head_dim) W_v = np.random.randn(hidden_dim, head_dim)
Q, K, V = compute_qkv(X, W_q, W_k, W_v) print(f"Q矩阵形状: {Q.shape}") # (batch_size, seq_len, head_dim) ```
1.4 特征值分解:矩阵的谱分析
特征值分解是线性代数中最重要的矩阵分解方法之一。给定一个 $n \times n$ 的方阵 $\mathbf{A}$,其特征值分解将矩阵表示为:
$$\mathbf{A} = \mathbf{Q}\boldsymbol{\Lambda}\mathbf{Q}^{-1}$$
其中 $\mathbf{Q}$ 的列是 $\mathbf{A}$ 的特征向量,$\boldsymbol{\Lambda}$ 是对角矩阵,其对角元素是相应的特征值。特征值揭示了矩阵的核心性质:它们描述了矩阵作为线性变换时的伸缩因子。在物理和工程系统中,特征值往往对应系统的固有频率或稳定性边界,这种解释同样适用于神经网络分析。
在语言模型的语境下,特征值分解有着独特的应用。词共现矩阵的特征值分解是早期词嵌入方法(如LSA,Latent Semantic Analysis)的理论基础。通过分析词共现矩阵的特征值分布,我们可以了解语言数据中潜在的结构层次。较大的特征值对应于数据中的主要变异方向,这些方向往往捕捉了最显著的语义主题。Transformer中的层归一化操作,其参数学习也隐含着对特征值分布的调整。
然而,特征值分解有其局限性:它只适用于方阵,且要求矩阵能够完全对角化。在实际应用中,我们更常使用的是奇异值分解,它对任意矩阵都适用,并且与特征值分解有着深刻的联系。
1.5 奇异值分解:降维与表示学习的利器
奇异值分解(Singular Value Decomposition, SVD)是矩阵分解的另一种重要形式,它将任意 $m \times n$ 矩阵 $\mathbf{A}$ 表示为三个特殊矩阵的乘积:
$$\mathbf{A} = \mathbf{U}\boldsymbol{\Sigma}\mathbf{V}^T$$
其中 $\mathbf{U}$ 是 $m \times m$ 的正交矩阵(其列称为左奇异向量),$\mathbf{V}$ 是 $n \times n$ 的正交矩阵(其列称为右奇异向量),$\boldsymbol{\Sigma}$ 是 $m \times n$ 的对角矩阵,其对角元素是奇异值(按降序排列)。与特征值分解不同,SVD对矩阵的形状没有限制,这使其具有更广泛的应用场景。
奇异值在数据压缩和降维中具有核心地位。设 $\mathbf{A}$ 的奇异值为 $\sigma_1 \geq \sigma_2 \geq \cdots \geq \sigma_r > 0$,其中 $r = \text{rank}(\mathbf{A})$。如果我们只保留前 $k$ 个最大的奇异值及其对应的奇异向量,则得到矩阵 $\mathbf{A}$ 的最优 $k$ 秩近似:
$$\mathbf{A}_k = \mathbf{U}_k \boldsymbol{\Sigma}_k \mathbf{V}_k^T$$
这个近似在Frobenius范数意义下是最佳的,这意味着如果我们用 $\mathbf{A}_k$ 代替 $\mathbf{A}$,所丢失的信息量最小。奇异值的这种“能量集中”特性,使得截断SVD成为降维的标准方法之一。
在大语言模型中,SVD的思想体现在多个层面。在表示学习层面,模型通过训练学习到的词嵌入矩阵本质上是在寻找一种能够保留语义信息的低维表示。在分析层面,研究者常使用SVD来可视化词嵌入空间的语义结构,通过观察奇异值分布来诊断模型的学习状态。在工程层面,SVD也被用于模型压缩和知识蒸馏,通过低秩近似减少参数量的同时尽量保持模型性能。
```python
使用SVD进行降维演示
from sklearn.decomposition import TruncatedSVD import numpy as np
模拟词共现矩阵
np.random.seed(42) vocab_size = 1000 seq_len = 5000
生成具有低秩结构的模拟数据
true_rank = 50 U_true = np.random.randn(vocab_size, true_rank) S_true = np.diag(np.random.rand(true_rank) * 100) # 奇异值 V_true = np.random.randn(seq_len, true_rank) co_occurrence_matrix = U_true @ S_true @ V_true.T + np.random.randn(vocab_size, seq_len) * 0.1
使用截断SVD进行降维
k = 20 # 降到20维 svd = TruncatedSVD(n_components=k, random_state=42) reduced_matrix = svd.fit_transform(co_occurrence_matrix)
print(f"原始矩阵形状: {co_occurrence_matrix.shape}") print(f"降维后矩阵形状: {reduced_matrix.shape}") print(f"前10个奇异值: {svd.singular_values_[:10]}") print(f"解释方差比例: {svd.explained_variance_ratio_.sum():.4f}") ```
2 概率论:不确定性下的语言建模
2.1 随机变量与概率分布:语言的不确定性量化
语言本身具有固有的不确定性——同一个意思可以用多种方式表达,同一个词在不同上下文中可能有不同的含义。这种不确定性不仅是语言的自然属性,更是语言模型需要处理的核心问题。概率论为此提供了系统化的数学框架,它允许我们对不确定性进行量化和推断。
随机变量是概率论的基本概念,它将随机实验的结果映射为数值。在语言建模中,词表中的每个词都可以对应一个离散随机变量,其取值范围是词的索引。对于一个长度为 $T$ 的文本序列 $w_1, w_2, \ldots, w_T$,我们关心的是该序列的联合概率 $P(w_1, w_2, \ldots, w_T)$。这个联合概率描述了语言中词语组合的统计规律性,是语言模型的核心建模对象。
概率分布函数描述了随机变量的取值规律。对于离散随机变量,我们使用概率质量函数(PMF)$P(X = x)$;对于连续随机变量,则使用概率密度函数(PDF)$p(x)$。在大语言模型中,最常用的是分类分布(Categorical Distribution),它描述了在给定上下文条件下,下一个词取各个可能值的概率。当我们说模型输出一个概率分布时,实际上是指模型对词表中每个词给出了作为下一个词的条件概率估计。
```python import numpy as np from scipy.stats import entropy
模拟语言模型的输出概率分布
def softmax(logits): """将logits转换为概率分布""" exp_logits = np.exp(logits - np.max(logits)) # 数值稳定性处理 return exp_logits / np.sum(exp_logits)
假设模型输出的logits
logits = np.array([2.5, 0.8, -1.2, 3.1, 0.5, -0.3]) probs = softmax(logits)
print("词表概率分布:") for i, p in enumerate(probs): print(f" 词 {i}: {p:.4f}")
计算分布的熵
h = entropy(probs, base=2) print(f"\n概率分布的熵: {h:.4f} bits")
采样生成下一个词
def sample_from_distribution(probs): """从概率分布中采样""" return np.random.choice(len(probs), p=probs)
sampled_word = sample_from_distribution(probs) print(f"采样的词: {sampled_word}") ```
2.2 条件概率与贝叶斯定理:上下文化的语言理解
条件概率 $P(A|B)$ 表示在事件 $B$ 已发生的条件下,事件 $A$ 发生的概率。对于语言建模,核心任务就是计算条件概率 $P(w_t | w_1, w_2, \ldots, w_{t-1})$,即给定前文词语序列的条件下,下一个词的概率分布。这正是语言模型名称中“语言”一词的含义——模型学习的是语言的概率分布。
贝叶斯定理是条件概率的直接推论,它建立了先验概率与后验概率之间的联系:
$$P(\theta | \mathcal{D}) = \frac{P(\mathcal{D} | \theta) P(\theta)}{P(\mathcal{D})}$$
其中 $P(\theta)$ 是先验概率(Prior),$P(\mathcal{D} | \theta)$ 是似然(Likelihood),$P(\theta | \mathcal{D})$ 是后验概率(Posterior),$P(\mathcal{D})$ 是证据(Evidence)。在语言模型的语境下,这个公式有着深刻的解释意义:如果我们将 $\theta$ 视为模型参数,$\mathcal{D}$ 视为训练数据,那么贝叶斯定理描述了如何根据观察到的数据来更新我们对模型参数的信念。
这种贝叶斯视角在多个层面影响着现代大语言模型的设计。在训练层面,GPT等模型使用的最大似然估计本质上是在寻找能够最大化观察训练数据概率的参数。在推断层面,当模型生成文本时,它实际上是在进行贝叶斯推断——综合考虑训练阶段学到的语言规律(先验)和当前上下文(似然),来预测最可能的下一个词(后验)。在模型选择层面,贝叶斯因子(Bayes Factor)提供了一种理论框架来比较不同模型的性能。
2.3 链式法则与语言建模的概率基础
联合概率可以通过链式法则分解为一系列条件概率的乘积:
$$P(w_1, w_2, \ldots, w_T) = P(w_1) \cdot P(w_2|w_1) \cdot P(w_3|w_1,w_2) \cdots P(w_T|