概率与统计提供了处理不确定性的数学语言,这对于语言建模至为根本。本质上,语言模型为词语或符号序列分配概率。理解这些思想有助于解释模型预测,制定训练目标,并分析模型行为。本节回顾支撑大型语言模型的重要概率论观点。概率分布与语言语言模型关注预测序列中的下一个符号。给定一个包含所有可能符号的词汇表 $V$,模型对下一个符号的预测可以表示为在 $V$ 上的离散概率分布。这表示为词汇表中的每个符号 $t \in V$ 分配一个概率 $P(token=t)$,使得所有概率均为非负且总和为一:$\sum_{t \in V} P(token=t) = 1$。语言模型根据先前语境生成的下一个符号的分布,通常是多项分布。这种分布将二项分布推广到有多个可能结果(词汇表中的符号)的情况。模型输出一个概率向量,每个符号对应一个概率,表示该符号是序列中下一个符号的可能性。例如,如果我们的词汇表仅包含 {cat, dog, sat, mat} 且先前语境是 "the cat",模型可能会输出如下概率:$P(\text{sat | "the cat"}) = 0.7$$P(\text{mat | "the cat"}) = 0.2$$P(\text{dog | "the cat"}) = 0.05$$P(\text{cat | "the cat"}) = 0.05$这些概率总和必须为 1.0。链式法则与语言建模语言建模的一个主要目标是估计整个符号序列 $P(w_1, w_2, \dots, w_n)$ 的概率。概率的链式法则使得我们能将此联合概率分解为条件概率的乘积:$$ P(w_1, w_2, \dots, w_n) = P(w_1) P(w_2 | w_1) P(w_3 | w_1, w_2) \dots P(w_n | w_1, \dots, w_{n-1}) $$这可以更紧凑地写为:$$ P(w_1, \dots, w_n) = \prod_{i=1}^{n} P(w_i | w_1, \dots, w_{i-1}) $$其中 $P(w_1 | w_0)$ 通常简化为 $P(w_1)$。大型语言模型,特别是像 GPT 系列这样的自回归模型,被训练来近似这些条件概率 $P(w_i | w_1, \dots, w_{i-1})$。模型将前面的序列(语境)作为输入,并为下一个符号 $w_i$ 输出一个在词汇表上的概率分布。大多数基于 Transformer 的语言模型的最后一层是线性变换,接着是Softmax 函数。Softmax 函数将原始分数(logits)向量 $z = (z_1, z_2, \dots, z_{|V|})$ 转换为概率分布 $p = (p_1, p_2, \dots, p_{|V|})$:$$ p_j = \text{softmax}(z)j = \frac{e^{z_j}}{\sum{k=1}^{|V|} e^{z_k}} $$每个 $p_j$ 表示模型估计的词汇表中第 $j$ 个符号作为下一个符号的概率。import torch import torch.nn.functional as F # 模型为大小为 5 的词汇表输出的 logits 示例 logits = torch.tensor([1.0, -0.5, 3.0, 0.0, 1.5]) # 应用 softmax 获得概率 probabilities = F.softmax(logits, dim=0) print(f"Logits: {logits}") print(f"Probabilities: {probabilities}") print(f"Sum of probabilities: {probabilities.sum()}") # 输出: # Logits: tensor([ 1.0000, -0.5000, 3.0000, 0.0000, 1.5000]) # Probabilities: tensor([0.1083, 0.0242, 0.7985, 0.0398, 0.1291]) # Sum of probabilities: 1.0信息论:熵、交叉熵和 KL 散度信息论提供了量化信息和比较概率分布的工具,这些工具对于理解和训练语言模型很有用。熵熵,记为 $H(P)$,表示在一个集合 $\mathcal{X}$ 上的离散概率分布 $P$ 中,与结果相关的平均不确定性或“惊讶度”。其计算方式为:$$ H(P) = - \sum_{x \in \mathcal{X}} P(x) \log_2 P(x) $$当使用 $\log_2$ 时,单位通常是比特。高熵的分布更不确定(例如,均匀分布),而低熵的分布则更集中(可预测)。对于语言模型而言,下一个符号预测的熵值越低,表示置信度越高。交叉熵交叉熵,记为 $H(P, Q)$,衡量在使用为不同分布 $Q$ 设计的最优编码时,识别从分布 $P$ 中提取事件所需的平均比特数。$$ H(P, Q) = - \sum_{x \in \mathcal{X}} P(x) \log_2 Q(x) $$在机器学习中,交叉熵常被用作损失函数。$P$ 代表“真实”分布(通常是一个独热向量,其中正确符号的概率为 1,其他为 0),而 $Q$ 代表模型的预测概率分布。训练期间最小化交叉熵损失会使模型的预测分布 $Q$ 更接近真实分布 $P$。对于单个目标标签 $y$(表示为独热向量)和模型预测 $q$,交叉熵损失简化为 $-\log_2 q_y$,其中 $q_y$ 是模型分配给正确标签的概率。import torch import torch.nn as nn import torch.nn.functional as F # 示例:模型预测(logits)和真实目标标签 # 批处理大小 = 1,词汇表大小 = 5 logits = torch.tensor([[1.0, -0.5, 3.0, 0.0, 1.5]]) # 单个实例的 Logits target = torch.tensor([2]) # 真实标签索引为 2(logit 为 3.0 的符号) # PyTorch 的 CrossEntropyLoss 结合了 LogSoftmax 和 NLLLoss # 它期望原始 logits 作为输入,类别索引作为目标 criterion = nn.CrossEntropyLoss() loss = criterion(logits, target) print(f"Logits: {logits}") print(f"Target index: {target}") print(f"Cross-Entropy Loss: {loss.item()}") # 手动计算: probabilities = F.softmax(logits, dim=1) # 损失 = -log(正确类别的概率) manual_loss = -torch.log(probabilities[0, target.item()]) print(f"Manual Calculation: -log(P(target)) = {manual_loss.item()}") # 输出: # Logits: tensor([[ 1.0000, -0.5000, 3.0000, 0.0000, 1.5000]]) # Target index: tensor([2]) # Cross-Entropy Loss: 0.22514162957668304 # Manual Calculation: -log(P(target)) = 0.22514162957668304KL 散度Kullback-Leibler (KL) 散度,记为 $D_{KL}(P || Q)$,衡量两个概率分布 $P$ 和 $Q$ 之间的差异。它量化了用 $Q$ 近似 $P$ 时信息损失的量。$$ D_{KL}(P || Q) = \sum_{x \in \mathcal{X}} P(x) \log_2 \frac{P(x)}{Q(x)} = H(P, Q) - H(P) $$KL 散度始终非负 ($D_{KL}(P || Q) \ge 0$),且仅当 $P = Q$ 时为零。它不对称,通常意味着 $D_{KL}(P || Q) \neq D_{KL}(Q || P)$。当真实分布 $P$(及其熵 $H(P)$)固定时,最小化真实分布 $P$ 与模型预测 $Q$ 之间的 KL 散度等同于最小化交叉熵 $H(P, Q)$,这在监督学习中通常如此。从模型分布中采样一旦模型生成了词汇表上的概率分布,我们通常需要从该分布中采样,尤其是在文本生成等任务中。基本采样最简单的方法是根据预测的概率直接采样。概率较高的符号更有可能被选中。温度采样为了控制采样过程的随机性,通常在 Softmax 之前对 Logits $z$ 应用温度缩放:$$ p_j = \frac{e^{z_j / T}}{\sum_{k=1}^{|V|} e^{z_k / T}} $$这里,$T$ 是温度参数:如果 $T \to 0$,概率将集中在最有可能的符号上(接近贪婪解码)。如果 $T = 1$,我们得到原始的 Softmax 概率。如果 $T > 1$,分布变得更平坦(更均匀),增加了随机性和多样性,但可能会降低连贯性。如果 $T \to \infty$,分布在词汇表上变得均匀。import torch import torch.nn.functional as F logits = torch.tensor([1.0, -0.5, 3.0, 0.0, 1.5]) # 与之前相同的 logits temperatures = [0.5, 1.0, 2.0] sampled_tokens = {} print(f"Original Logits: {logits}\n") for T in temperatures: scaled_logits = logits / T probabilities = F.softmax(scaled_logits, dim=0) print(f"Temperature = {T}") print(f"Scaled Logits: {scaled_logits.numpy().round(2)}") print(f"Probabilities: {probabilities.numpy().round(3)}") # 根据概率采样一个符号 # 使用多项式进行采样; # 为了说明,我们将多次采样 samples = torch.multinomial( probabilities, num_samples=10, replacement=True ) sampled_list = samples.tolist() print(f"Sampled token indices (10 samples): {sampled_list}\n") sampled_tokens[T] = probabilities.numpy() # 输出: # Original Logits: tensor([1.0000, -0.5000, 3.0000, 0.0000, # 1.5000]) # Temperature = 0.5 # Scaled Logits: [ 2. -1. 6. 0. 3. ] # Probabilities: [0.036 0.002 0.881 0.005 0.076] # Sampled token indices (10 samples): [2, 2, 2, 2, 2, 2, 2, 2, 2, 2] # # 非常可能选择索引 2 # Temperature = 1.0 # Scaled Logits: [ 1. -0.5 3. 0. 1.5] # Probabilities: [0.108 0.024 0.799 0.04 0.129] # Sampled token indices (10 samples): [2, 2, 2, 0, 4, 2, 2, 2, 2, 4] # # 主要选择索引 2,也有其他可能 # Temperature = 2.0 # Scaled Logits: [ 0.5 -0.25 1.5 0. 0.75] # Probabilities: [0.187 0.088 0.46 0.113 0.153] # Sampled token indices (10 samples): [2, 2, 0, 4, 0, 2, 3, 2, 2, 0] # # 更多多样性{"data": [{"x": ["符号 0", "符号 1", "符号 2", "符号 3", "符号 4"], "y": [0.036, 0.002, 0.881, 0.005, 0.076], "type": "bar", "name": "T=0.5", "marker": {"color": "#4263eb"}}, {"x": ["符号 0", "符号 1", "符号 2", "符号 3", "符号 4"], "y": [0.108, 0.024, 0.799, 0.04, 0.129], "type": "bar", "name": "T=1.0", "marker": {"color": "#20c997"}}, {"x": ["符号 0", "符号 1", "符号 2", "符号 3", "符号 4"], "y": [0.187, 0.088, 0.46, 0.113, 0.153], "type": "bar", "name": "T=2.0", "marker": {"color": "#fd7e14"}}], "layout": {"title": "温度对 Softmax 概率的影响", "xaxis": {"title": "符号索引"}, "yaxis": {"title": "概率", "range": [0, 1]}, "barmode": "group", "height": 300, "margin": {"l": 50, "r": 20, "t": 40, "b": 40}}}针对大小为 5 的词汇表上的概率分布,这些分布是使用应用于相同初始 logits 的不同温度值(T)计算得出的。较低的温度将概率质量集中在最有可能的符号上(索引 2),而较高的温度则产生更均匀的分布。其他采样策略除了温度,Top-k 采样(仅从 $k$ 个最有可能的符号中采样)和 Top-p(核)采样(从累积概率超过阈值 $p$ 的最小符号集合中采样)等其他方法常用于平衡生成文本的质量和多样性。扎实掌握这些概率与统计基础,对于处理大型语言模型来说必不可少。它能帮助您推断模型预测,通过交叉熵等损失函数理解训练流程,并使用采样技术控制文本生成。