LLM笔记(五)概率论

1. 随机变量与概率分布:模型输出的基础

在LLM中,随机变量最直观的体现就是模型预测的下一个token。每个时刻,模型都会输出一个概率分布,表示词汇表中每个token可能是"下一个词"的概率。

直观理解

想象模型在处理句子"我喜欢北京的"后需要预测下一个词。此时,模型会为词汇表中的每个候选token分配一个概率:

  • "天安门":0.3
  • "故宫":0.25
  • "美食":0.2
  • "文化":0.15
  • 其他词:0.1

这个分布通过softmax函数从模型的logits输出转换而来:

python 复制代码
# logits是模型输出的未归一化对数概率
logits = model(input_ids)[:, -1, :]  # 获取最后一个位置的logits
probabilities = torch.softmax(logits, dim=-1)  # 转换为概率分布

深层意义

概率分布不仅让模型能够进行采样生成,还能反映模型的不确定性程度。分布的形状(是否集中、平坦或有多个峰值)揭示了模型对当前预测的信心程度。

2. 条件概率:语言模型的核心

LLM是自回归(autoregressive)模型,即通过计算条件概率 P ( x t ∣ x < t ) P(x_t | x_{<t}) P(xt∣x<t) 来生成序列。整个序列的联合概率分解为一系列条件概率的乘积:

P ( x 1 , x 2 , ... , x T ) = ∏ t = 1 T P ( x t ∣ x < t ) P(x_1, x_2, \dots, x_T) = \prod_{t=1}^T P(x_t | x_{<t}) P(x1,x2,...,xT)=t=1∏TP(xt∣x<t)

实际运作方式

当模型生成文本时,每一步都依赖于前面已生成的所有内容:

  1. 第一步: P ( x 1 ) P(x_1) P(x1) - 生成第一个token(无条件)
  2. 第二步: P ( x 2 ∣ x 1 ) P(x_2|x_1) P(x2∣x1) - 基于第一个token生成第二个
  3. 第三步: P ( x 3 ∣ x 1 , x 2 ) P(x_3|x_1,x_2) P(x3∣x1,x2) - 基于前两个token生成第三个

以此类推,形成条件概率链。

例子说明

假设模型在生成一个句子:

  • 首先生成"我"(假设概率为0.1)
  • 然后基于"我"生成"喜欢"(条件概率为0.3)
  • 接着基于"我喜欢"生成"学习"(条件概率为0.2)

整个序列"我喜欢学习"的联合概率为:0.1 × 0.3 × 0.2 = 0.006

这种条件概率框架使LLM能够捕捉语言的上下文依赖性,这是它们强大能力的关键所在。

3. 最大似然估计:训练的统计基础

LLM训练的核心目标是最大化训练数据的似然概率,等价于最小化负对数似然(即交叉熵损失):

L ( θ ) = − ∑ t log ⁡ P θ ( x t ∣ x < t ) \mathcal{L}(\theta) = -\sum_{t}\log P_\theta(x_t | x_{<t}) L(θ)=−t∑logPθ(xt∣x<t)

为什么使用对数?

对数变换有几个重要优势:

  • 将乘法转换为加法,避免小数值相乘导致的数值下溢
  • 使优化过程更加稳定
  • 与信息论中的交叉熵概念直接对应

训练示例

考虑训练过程中的一个小批量文本:"我爱北京天安门":

python 复制代码
def compute_loss(model, tokens):
    # tokens: [batch_size, sequence_length]
    logits = model(tokens[:, :-1])  # 预测除最后一个token外的所有位置
    targets = tokens[:, 1:]  # 目标是下一个token
    
    # 计算每个位置的负对数似然
    loss = F.cross_entropy(
        logits.view(-1, vocab_size), 
        targets.view(-1),
        reduction='none'
    )
    
    # 返回平均损失
    return loss.mean()

通过最小化这个损失函数,模型参数θ将被调整以增大训练数据的概率,从而"学习"语言的统计模式。

4. 期望与方差:衡量模型行为

期望值 E [ f ( X ) ] \mathbb{E}[f(X)] E[f(X)] 和方差 Var [ X ] \text{Var}[X] Var[X] 在LLM中有多种应用:

期望的应用

  1. 评估指标计算:计算平均惊讶度(negative log-likelihood)或平均困惑度

    python 复制代码
    # 计算平均惊讶度
    def average_surprisal(model, text):
        tokens = tokenize(text)
        log_probs = model.log_probs(tokens)
        return -log_probs.mean().item()
  2. 信息提取:在多次采样中提取"稳定"信息

    python 复制代码
    # 通过多次采样获取稳定答案
    responses = [model.generate(prompt) for _ in range(10)]

方差的应用

  1. 不确定性量化:高方差表示模型对某些预测的不确定性高

    python 复制代码
    # 计算预测方差
    logits = model(input_ids)
    probs = F.softmax(logits, dim=-1)
    entropy = -torch.sum(probs * torch.log(probs), dim=-1)  # 高熵≈高方差≈高不确定性
  2. 多样性控制:在生成时,可以基于方差调整采样策略

方差和期望共同帮助我们理解模型的统计行为,不仅在评估模型性能时有用,也为生成策略提供了理论指导。

5. 贝叶斯定理:从先验到后验

虽然传统LLM训练不直接使用贝叶斯方法,但贝叶斯思想在多个方面得到应用:

P ( θ ∣ D ) ∝ P ( D ∣ θ ) P ( θ ) P(\theta | D) \propto P(D | \theta)P(\theta) P(θ∣D)∝P(D∣θ)P(θ)

实际应用

  1. 参数正则化:权重衰减可看作对参数的高斯先验

    python 复制代码
    # L2正则化(权重衰减)
    loss = task_loss + weight_decay * sum(p.pow(2).sum() for p in model.parameters())
  2. 小样本学习:少样本(few-shot)提示可视为后验更新

    • 没有示例时,模型使用先验P(θ)
    • 提供few-shot示例后,模型更新为后验P(θ|少量示例)
  3. 推理校准:后验调整可以改善模型预测

    python 复制代码
    # 简单的后验校准示例
    def calibrate_probabilities(probs, temperature=1.0, label_smoothing=0.0):
        # 温度缩放
        scaled_logits = torch.log(probs) / temperature
        calibrated = F.softmax(scaled_logits, dim=-1)
        
        # 标签平滑(混合均匀先验)
        if label_smoothing > 0:
            uniform = torch.ones_like(calibrated) / calibrated.size(-1)
            calibrated = (1 - label_smoothing) * calibrated + label_smoothing * uniform
            
        return calibrated

贝叶斯框架为我们提供了整合先验知识和更新置信度的强大工具,这在微调、迁移学习和不确定性建模中特别有价值。

6. 采样方法:平衡确定性与创造性

生成文本时,我们需要从模型的概率分布中采样。不同采样策略影响生成文本的多样性和质量:

温度采样

调整温度T可以控制分布的平滑度:
P T ( x ) ∝ P ( x ) 1 / T P_T(x) \propto P(x)^{1/T} PT(x)∝P(x)1/T

python 复制代码
def temperature_sampling(logits, temperature=1.0):
    # temperature=0会变成贪婪搜索
    # temperature<1使分布更尖锐(更确定)
    # temperature>1使分布更平坦(更多样)
    scaled_logits = logits / temperature
    probs = F.softmax(scaled_logits, dim=-1)
    next_token = torch.multinomial(probs, num_samples=1)
    return next_token
  • 温度接近0:贪婪搜索,总是选最高概率词
  • 温度为1:保持原始分布
  • 温度大于1:增加低概率事件的采样机会

Top-k与Nucleus采样

这些方法通过截断分布尾部来减少低质量样本:

python 复制代码
def top_k_sampling(logits, k=50):
    # 只保留概率最高的k个token
    values, indices = torch.topk(logits, k)
    probs = F.softmax(values, dim=-1)
    next_token = indices[torch.multinomial(probs, num_samples=1)]
    return next_token

def nucleus_sampling(logits, p=0.9):
    # 保留累积概率达到p的最小token集合
    sorted_logits, sorted_indices = torch.sort(logits, descending=True)
    cumulative_probs = torch.cumsum(F.softmax(sorted_logits, dim=-1), dim=-1)
    
    # 找到第一个累积概率超过p的位置
    sorted_indices_to_keep = cumulative_probs <= p
    
    # 在某些情况下,我们至少保留一个token
    if torch.sum(sorted_indices_to_keep) == 0:
        sorted_indices_to_keep[0] = True
        
    indices_to_keep = sorted_indices[sorted_indices_to_keep]
    logits_to_keep = logits[indices_to_keep]
    
    probs = F.softmax(logits_to_keep, dim=-1)
    next_token = indices_to_keep[torch.multinomial(probs, num_samples=1)]
    return next_token

这些采样方法直接影响生成文本的质量,是LLM应用中的关键决策点。温度和采样策略的选择取决于任务要求:

  • 事实性问答:低温度,偏好确定性高的输出
  • 创意写作:较高温度,允许更多样的输出
  • 代码生成:通常使用较低温度但带nucleus采样,平衡正确性和多样性

7. 马尔可夫性:序列依赖的表示

虽然Transformer架构理论上可以考虑任意长的上下文,但实际上,LLM仍然是一种强化版的马尔可夫模型:当前token的生成依赖于固定长度窗口内的历史。

马尔可夫性与上下文窗口

标准马尔可夫模型假设:
P ( x t ∣ x < t ) = P ( x t ∣ x t − k , ... , x t − 1 ) P(x_t | x_{<t}) = P(x_t | x_{t-k}, \ldots, x_{t-1}) P(xt∣x<t)=P(xt∣xt−k,...,xt−1)

LLM则扩展为:
P ( x t ∣ x < t ) = P ( x t ∣ x m a x ( 1 , t − C ) , ... , x t − 1 ) P(x_t | x_{<t}) = P(x_t | x_{max(1,t-C)}, \ldots, x_{t-1}) P(xt∣x<t)=P(xt∣xmax(1,t−C),...,xt−1)

其中C是上下文窗口长度(如GPT-3为2048,Claude 3为200k+)。

有限记忆的影响

上下文窗口限制导致的问题包括:

  • 无法引用超出窗口的信息
  • 长文档理解中的一致性挑战
  • 对长文本生成的连贯性约束

这种有限马尔可夫性质启发了许多改进方向,如长上下文模型、外部内存机制、检索增强等。

8. 蒙特卡洛估计:基于采样的评估

蒙特卡洛方法通过多次随机采样来估计统计特性,在LLM中有重要应用:

应用场景

  1. 不确定性估计:通过多次采样估计预测的置信区间

    python 复制代码
    def estimate_confidence_interval(model, prompt, n_samples=100):
        # 生成多个回答
        responses = [model.generate(prompt) for _ in range(n_samples)]
        
        # 分析回答的分布(例如,对于是/否问题)
        yes_count = sum(1 for r in responses if "是" in r[:10])
        confidence = max(yes_count, n_samples - yes_count) / n_samples
        
        return confidence
  2. 多样性度量:评估生成结果的多样性

    python 复制代码
    def measure_diversity(model, prompt, n_samples=10):
        responses = [model.generate(prompt) for _ in range(n_samples)]
        
        # 计算生成文本之间的平均相似度
        similarities = []
        for i in range(n_samples):
            for j in range(i+1, n_samples):
                sim = compute_similarity(responses[i], responses[j])
                similarities.append(sim)
                
        return sum(similarities) / len(similarities)
  3. 集成预测:整合多次预测结果以提高准确性

    python 复制代码
    def ensemble_prediction(model, prompt, n_samples=10):
        predictions = [model.generate(prompt) for _ in range(n_samples)]
        # 可以通过投票、平均或更复杂的方法整合结果
        return most_common(predictions)

蒙特卡洛方法帮助我们更好地理解模型行为的统计特性,特别是在处理高度不确定或多样化输出的场景中。

9. 随机过程与序列建模:统计依赖的捕捉

语言生成可视为一种离散时间随机过程,LLM通过自注意力机制捕捉这一过程中的统计依赖:

自注意力与随机过程

Transformer的自注意力机制计算:
Attention ( Q , K , V ) = softmax ( Q K T d k ) V \text{Attention}(Q, K, V) = \text{softmax}\left(\frac{QK^T}{\sqrt{d_k}}\right)V Attention(Q,K,V)=softmax(dk QKT)V

这实际上是在估计序列中各位置之间的统计依赖强度。注意力权重可以解释为:位置j对预测位置i的影响程度。

深层统计依赖

LLM通过多层注意力捕捉复杂的统计依赖:

  • 浅层可能关注局部语法模式
  • 深层可能捕捉全局语义依赖
  • 多头注意力则并行捕捉不同类型的依赖关系

这种分层设计使LLM能够学习句法、语义和篇章层面的统计规律,从而生成连贯且有意义的文本。

10. 校准:确保概率预测的可靠性

模型校准衡量预测概率与实际频率的一致性:

校准重要性

假设模型以90%的置信度预测某些事实,如果模型校准良好,这些预测约90%应该是正确的。

python 复制代码
def expected_calibration_error(probs, correct):
    """
    计算预期校准误差
    probs: 预测概率
    correct: 对应的正确与否标记(0/1)
    """
    # 将概率分成几个bin
    n_bins = 10
    bins = np.linspace(0, 1, n_bins + 1)
    bin_indices = np.digitize(probs, bins) - 1
    
    ece = 0
    for bin_idx in range(n_bins):
        # 找到落在这个bin中的预测
        mask = bin_indices == bin_idx
        if not np.any(mask):
            continue
            
        bin_probs = probs[mask]
        bin_correct = correct[mask]
        
        # 计算这个bin中的平均概率和准确率
        avg_prob = np.mean(bin_probs)
        avg_acc = np.mean(bin_correct)
        
        # 加权绝对误差
        ece += np.abs(avg_prob - avg_acc) * (np.sum(mask) / len(probs))
        
    return ece

校准方法

  1. 温度缩放:通过除以温度参数调整logits
  2. Platt缩放:学习线性变换校准概率
  3. 模型集成:多个模型预测结合可提高校准性

良好的校准对于许多应用至关重要,如医疗诊断、金融预测和自动决策系统,因为它们需要依赖模型不仅给出正确答案,还要准确报告自己的确定性。

11. 似然比与对比评估:模型比较的工具

似然比是比较两个概率模型的强大工具:

P model1 ( x ) P model2 ( x ) \frac{P_{\text{model1}}(x)}{P_{\text{model2}}(x)} Pmodel2(x)Pmodel1(x)

实际应用

  1. 对抗训练:通过似然比区分真实vs生成文本

    python 复制代码
    def discriminator_loss(real_data, generated_data, model1, model2):
        # 计算似然比,用于区分真实数据和生成数据
        real_log_probs_1 = model1.log_probs(real_data)
        real_log_probs_2 = model2.log_probs(real_data)
        real_ratio = torch.exp(real_log_probs_1 - real_log_probs_2)
        
        gen_log_probs_1 = model1.log_probs(generated_data)
        gen_log_probs_2 = model2.log_probs(generated_data)
        gen_ratio = torch.exp(gen_log_probs_1 - gen_log_probs_2)
        
        # 优化目标:增大真实数据的比值,减小生成数据的比值
        loss = -torch.mean(torch.log(real_ratio)) - torch.mean(torch.log(1 - gen_ratio))
        return loss
  2. 模型选择:比较不同模型对数据的拟合能力

    python 复制代码
    def compare_models(test_data, model_a, model_b):
        log_probs_a = model_a.log_probs(test_data)
        log_probs_b = model_b.log_probs(test_data)
        
        # 如果比值>1,则模型A更适合数据
        log_ratio = log_probs_a - log_probs_b
        return log_ratio.mean()
  3. 倾向性得分:用于评估生成偏好

    python 复制代码
    def calculate_preference_score(model, prompt_a, prompt_b):
        completion = model.generate(prompt_a)
        
        # 计算完成后的文本在两个不同提示下的对数概率
        log_prob_a = model.conditional_log_prob(completion, prompt_a)
        log_prob_b = model.conditional_log_prob(completion, prompt_b)
        
        # 返回倾向性得分
        return log_prob_a - log_prob_b

似然比是评估和比较概率模型的强大工具,在模型选择、假设检验和对抗学习中都有广泛应用。

概率论视角的综合应用

这些概率论概念不是孤立的,而是形成了一个连贯的理论框架,支撑着LLM的各个方面:

  1. 从训练到推理的完整流

    • 模型定义:条件概率分布 P ( x t ∣ x < t ) P(x_t|x_{<t}) P(xt∣x<t)
    • 训练目标:通过最大似然估计优化参数
    • 推理方法:通过各种采样策略从概率分布中生成样本
    • 评估标准:困惑度、校准误差等概率度量
  2. 不确定性的系统处理

    • 表示:概率分布的熵
    • 传播:通过采样和蒙特卡洛方法
    • 量化:方差、置信区间
    • 通信:校准的概率输出
  3. 概率框架的实际价值

    • 提供理论基础解释模型行为
    • 指导采样策略的选择
    • 启发新的训练和推理方法
    • 评估模型性能的系统标准
相关推荐
oceanweave1 分钟前
【K8S学习之生命周期钩子】详细了解 postStart 和 preStop 生命周期钩子
学习·kubernetes
Blossom.1181 小时前
使用Python实现简单的人工智能聊天机器人
开发语言·人工智能·python·低代码·数据挖掘·机器人·云计算
科技小E1 小时前
EasyRTC嵌入式音视频通信SDK打造带屏IPC全场景实时通信解决方案
人工智能·音视频
ayiya_Oese1 小时前
[模型部署] 3. 性能优化
人工智能·python·深度学习·神经网络·机器学习·性能优化
愚戏师1 小时前
Linux复习笔记(六)shell编程
linux·笔记·shell
仙人掌_lz1 小时前
机器学习与人工智能:NLP分词与文本相似度分析
人工智能·机器学习·自然语言处理
jndingxin2 小时前
OpenCV CUDA模块中矩阵操作------归一化与变换操作
人工智能·opencv
ZStack开发者社区2 小时前
云轴科技ZStack官网上线Support AI,智能助手助力高效技术支持
人工智能·科技
每天都要写算法(努力版)2 小时前
【神经网络与深度学习】通俗易懂的介绍非凸优化问题、梯度消失、梯度爆炸、模型的收敛、模型的发散
人工智能·深度学习·神经网络
Blossom.1182 小时前
Web3.0:互联网的去中心化未来
人工智能·驱动开发·深度学习·web3·去中心化·区块链·交互