Jiahong 的个人博客

凡事预则立,不预则废


  • Home

  • Tags

  • Archives

  • Navigation

  • Search

NLP——LLM内存优化技术总结

本文主要介绍内存优化相关技术


LLM内存优化技术总结

  • LLM(大型语言模型)在内存优化方面采用了多种技术,常见的方法包括

梯度检查点(Gradient Checkpointing)

  • 在前向传播时只保存部分激活值,其余的在反向传播时重新计算,主要用在预训练阶段
  • 特点:显著减少内存占用,但会增加计算量

混合精度训练(Mixed Precision Training)

  • 使用16位浮点数(FP16)代替32位浮点数(FP32)进行计算和存储,通过自动混合精度(AMP)工具实现,关键部分(如梯度更新)仍使用FP32以保证数值稳定性
  • 特点:减少内存使用并提升计算速度,但对显卡有要求,适用于支持FP16的硬件(如NVIDIA Tensor Core GPU)

模型并行(Model Parallelism)

  • 将模型的不同层分配到多个设备上,减少单个设备的内存负担
  • 特点:支持更大模型的训练,但增加了通信开销

数据并行(Data Parallelism)

  • 将数据批次分配到多个设备上,每个设备拥有完整的模型副本
  • 特点:通过增加设备数量来分摊内存压力

梯度累积(Gradient Accumulation)

  • 在多个小批次上累积梯度后再更新模型参数,多次累计梯度后一次更新参数,能够用小内存实现大梯度更新参数
  • 特点:减少单次内存需求,支持更大的批次训练

参数卸载(Parameter Offloading)

  • 将部分模型参数存储在CPU或磁盘上,需要时再加载到GPU,可通过框架(如DeepSpeed的ZeRO-Offload)自动管理参数的加载和卸载
  • 特点:减少GPU内存占用,但可能增加I/O开销

稀疏注意力机制(Sparse Attention)

  • 只计算输入序列中部分位置的注意力权重,通过设计稀疏模式(如局部窗口、随机采样)减少计算量
    • 稀疏注意力机制(Sparse Attention)是一种优化 Transformer 模型中注意力计算的技术,旨在减少计算复杂度和内存占用。它通过限制每个输入位置只与部分其他位置进行注意力计算,而不是与所有位置进行全连接计算,从而实现高效的计算和内存管理
  • 特点:降低内存和计算复杂度、支持更长序列等,对效果是有损的

量化(Quantization)

  • 将模型参数从高精度(如FP32)转换为低精度(如INT8),比如 QLoRA 等可以做到更低的量化,大幅降低模型微调和推理的内存
  • 特点:减少内存占用和计算量,对效果可能有损

知识蒸馏(Knowledge Distillation)

  • 用大模型训练小模型,使其性能接近大模型,小模型模仿大模型的输出
  • 特点:减少内存和计算资源需求,可加速模型的部署和推理

内存高效优化器(Memory-Efficient Optimizers)

  • 使用如Adafactor等优化器,减少存储优化状态的内存
    • AdaFactor是一种优化算法,旨在减少在训练深度学习模型时的内存占用,同时保持或提高模型性能。它是由Google的研究人员提出的一种自适应学习率优化器,其特点是显存成本(Memory Cost)是次线性的(Sublinear),意味着随着参数数量的增长,所需的额外内存不会线性增长
  • 特点:降低训练时的内存使用

分层训练(Layer-wise Training)

  • 逐层训练模型,每次只加载当前层的参数和梯度
  • 特点:减少内存需求,但可能影响模型性能

内存池(Memory Pooling)

  • 预先分配并复用内存块,减少频繁分配和释放的开销
  • 特点:提高内存使用效率

模型剪枝(Model Pruning)

  • 通过删减网络结构,移除不重要的神经元或连接,实现模型压缩
  • 特点:减少模型大小和内存占用,但这种方式不常用

低秩分解(Low-Rank Factorization)

  • 将大矩阵分解为多个小矩阵,常见的方式就是LoRA相关的技术,也可以和量化结合,如QLoRA等
  • 特点:减少内存和计算需求,适用于各种微调场景

vLLM推理框架

  • vLLM 是一个专注于高效推理的框架,要用于推理阶段 ,通过 PagedAttention、连续批处理、量化等技术优化内存和计算效率,显著提升吞吐量和响应速度
  • PagedAttention
    • 这是 vLLM 的核心技术,灵感来源于操作系统的虚拟内存分页机制。它通过分页管理注意力机制中的键值(KV)缓存,显著减少了内存浪费,并支持动态调整缓存大小,从而提高了吞吐量和内存利用率
  • 连续批处理(Continuous Batching)
    • vLLM 支持将多个请求批量处理,通过共享计算资源(如 KV 缓存)来减少重复计算,从而提高吞吐量
  • 量化技术
    • 支持多种量化方法(如 GPTQ、AWQ、FP8 KV Cache 等),通过降低模型参数的精度来减少内存占用和计算开销
  • 张量并行(Tensor Parallelism)
    • 支持将模型分布到多个 GPU 上运行,通过并行计算加速推理过程
  • 推测解码(Speculative Decoding) ,也称为 投机采样
    • 使用较小的模型预测词元,再用大模型验证结果,从而加速文本生成
  • Flash Attention
    • 优化 Transformer 模型的注意力计算,减少计算复杂度和内存占用
  • OpenAI 兼容 API
    • 提供与 OpenAI API 兼容的接口,便于集成到现有应用中
  • 多 LoRA 支持
    • 支持多 LoRA(低秩适应)模型,允许在同一框架下运行多个微调模型

ZeRO显存优化技术

  • ZeRO(Zero Redundancy Optimizer)是一种用于训练阶段的显存优化技术,主要用于训练阶段,通过分片存储、通信优化和混合精度训练等技术减少显存占用,支持更大规模的模型训练
  • ZERO 技术最初是微软在 2020 年的论文 ZeRO: Memory Optimization Towards Training Trillion Parameter Models 中被提出的,详细阐述了 ZERO 的三个阶段(ZERO-1、ZERO-2、ZERO-3)及其内存优化原理
  • ZERO 技术也是 DeepSpeed 框架的核心创新之一(注:DeepSpeed 是微软开发的一个用于大规模深度学习训练的优化库)
  • 分片存储(Sharding)
    • ZeRO 将模型参数、梯度和优化器状态分片存储到多个 GPU 上,从而减少单个 GPU 的内存占用。分为三个阶段:
      • ZeRO Stage 1(ZeRO-1) :仅分片优化器状态
      • ZeRO Stage 2(ZeRO-2) :分片优化器状态和梯度
      • ZeRO Stage 3(ZeRO-3) :分片优化器状态、梯度和模型参数
  • 通信优化
    • ZeRO 通过优化 GPU 间的通信(如 All-Reduce 和 Reduce-Scatter 等GPU通信操作),减少分布式训练中的通信开销
  • 混合精度训练
    • 支持 FP16 和 FP8 等低精度训练,减少显存占用并加速计算
  • 重计算(Gradient Checkpointing)
    • 在前向传播时只保存部分激活值,反向传播时重新计算其余部分,从而减少显存占用
  • 负载均衡
    • 在 MoE(Mixture of Experts)模型中,通过优化路由策略和负载分配,避免专家模型之间的负载不均衡
  • 后来微软 DeepSpeed 团队继续对 ZERO 技术进行扩展,退出了 ZeRO-Offload 和 ZeRO-Infinity 等高级技术:
    • ZeRO-Offload 可以将已划分的优化器状态和梯度卸载到 CPU 内存中
    • ZeRO-Infinity 是 ZeRO-3 的扩展,它可以利用 CPU 和 NVMe 内存来进一步扩展 GPU 的内存,支持训练更大型的模型

附录:大模型推理中的模型量化技术总结

  • 大模型推理中,模型量化旨在减少模型的存储和计算需求,同时尽量保持模型的性能

GPTQ(Gradient-based Post-training Quantization)

  • TLDR:基于梯度的后训练量化方法
  • 基本原理:
    • 在模型训练完成后,对模型权重进行量化
    • 通过优化目标函数来最小化量化误差,利用梯度调整量化时的权重误差,使量化后模型与未量化模型的表现尽可能接近
    • 采用误差反馈机制,将量化误差传播到后续层进行补偿,减少累积误差对模型输出的影响
  • 特点:
    • 适用于 8-bit 或更低的量化需求,尤其对大语言模型量化效果好
    • 不需要额外的训练数据,精度损失相对较小,特别适合复杂模型
    • 针对 GPU 使用进行了优化,在 GPU 推理时性能较好,能将权重动态去量化为 float16,提高性能的同时保持低内存占用

AWQ(Activation-aware Quantization)

  • TLDR:关注激活值的量化方法,量化过程中考虑激活值分布对模型性能的影响
  • 基本原理:
    • 分析激活值的分布特性,对激活值进行适应性处理
    • 采用非均匀量化,针对不同的激活值范围选择不同的量化尺度
  • 特点:
    • 精度较高,通过对激活值分布的考虑,能更好地保留模型的性能
    • 计算复杂度较大,因为需要分析激活值分布并进行非均匀量化操作

GGUF(Generalized Global Uniform Quantization Framework)

  • TLDR:一种通用的全局统一量化框架,用于处理大规模神经网络
  • 基本原理:
    • 通常采用全局统一量化策略,假设模型的所有层或某一类参数具有相似的分布,对整个模型的权重或激活值采用相同的量化参数
    • 采用均匀量化,将所有数值线性地映射到一个均匀的范围,并引入缩放因子,在推理阶段重定标量化后的数值,避免数值溢出或精度过低
  • 特点:
    • 简单高效,适用于资源受限的部署场景,如普通 CPU 环境
    • 兼容 Windows 和 Linux 操作系统
    • 提供从 2-bit 到 8-bit 的多级量化选项
    • 由于采用统一量化策略,可能导致某些模型层的精度损失

DL——Teacher-Forcing方法

本文主要介绍Transformer和Attention相关内容


整体总结

  • 教师强制(Teacher Forcing) 是一种在训练序列生成模型(包括循环神经网络 RNN、长短期记忆网络 LSTM 等)时使用的方法
  • 其核心思想是在训练过程中强制模型使用真实的目标序列作为输入 ,而非模型自身的预测结果,从而解决序列生成任务中可能出现的误差累积问题
  • 大模型的 SFT 方法就是一种 Teacher Forcing 方法,属于一种 Token-level 的行为克隆

Teacher Forcing 的基本原理

  • 在序列生成任务(如机器翻译、文本生成、语音识别等)中,模型需要根据历史输入和已生成的序列来预测下一个输出
  • 传统训练方式下,若直接使用模型前一步的预测结果作为下一步的输入,一旦某一步预测错误,后续预测可能会因误差累积而“偏离轨道”,导致训练不稳定
  • 教师强制的做法 :在每一步训练中,强制使用真实的目标序列(而非模型上一步的预测值)作为下一步的输入
    • 例如:在机器翻译中,当生成第二个词时,不使用模型预测的第一个词,而是直接使用参考译文中的第一个词,以此类推

Teacher Forcing 的具体流程(以LSTM为例)

  • 假设我们有一个序列生成任务,目标序列为 \( y_1, y_2, y_3, \dots, y_T \),模型输入为 \( x_1, x_2, \dots, x_T \),则训练过程如下:
    • 第一步 :输入 \( x_1 \),模型预测 \( \hat{y}_1 \),与真实值 \( y_1 \) 计算损失并更新参数
    • 第二步 :不使用 \( \hat{y}_1 \),而是将真实值 \( y_1 \) 作为输入,结合 \( x_2 \),模型预测 \( \hat{y}_2 \),计算损失并更新参数
    • 后续步骤 :重复上述过程,每一步都用真实的 \( y_{t-1} \) 作为当前步的部分输入,直至生成 \( \hat{y}_T \)。

Teacher Forcing 的优缺点分析

优点

  • 训练更稳定 :避免因早期预测错误导致的误差累积,模型更容易收敛
  • 加速收敛 :真实目标序列提供了更准确的监督信号,减少了训练迭代次数
  • 降低训练难度 :尤其适合复杂序列任务(如长文本生成),避免模型“发散”

缺点

  • 训练与推理偏差 :推理时(如实际生成文本)无法获取真实目标序列,需依赖模型自身预测,可能导致“暴露偏差(Exposure Bias)”(即训练时的输入分布与推理时不一致)
  • 缺乏抗噪能力 :模型可能过度依赖真实标签,对预测误差的鲁棒性较差

其他相关训练方法的对比

  • 教师强制 :始终使用真实标签作为输入
  • 为解决教师强制的“暴露偏差”问题,有人提出了 Scheduled Sampling(计划采样) 方法:
    • Scheduled Sampling :在训练初期以高概率使用真实标签,随着训练推进,逐渐增加使用模型预测值的概率,使模型逐步适应推理时的输入分布
    • Scheduled Sampling通过平衡“教师指导”和“自主预测”,减少训练与推理的差异,提升模型泛化能力

代码示例

  • PyTorch实现简单教师强制训练
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    import torch
    import torch.nn as nn
    import torch.optim as optim

    class LSTMModel(nn.Module):
    def __init__(self, input_size, hidden_size, output_size):
    super(LSTMModel, self).__init__()
    self.lstm = nn.LSTM(input_size, hidden_size)
    self.fc = nn.Linear(hidden_size, output_size)

    def forward(self, x, hidden):
    lstm_out, hidden = self.lstm(x, hidden)
    output = self.fc(lstm_out)
    return output, hidden

    def train_with_teacher_forcing(model, input_seq, target_seq, criterion, optimizer):
    model.train()
    hidden = model.init_hidden()
    optimizer.zero_grad()
    loss = 0

    for t in range(target_seq.size(0)):
    output, hidden = model(input_seq[t].unsqueeze(0), hidden)
    input_seq[t+1] = target_seq[t] # 下一时间步的输入使用真实目标值(Teacher Forcing 方法的核心代码)
    loss += criterion(output, target_seq[t].unsqueeze(0))

    loss.backward()
    optimizer.step()
    return loss.item()

DL——TensorBoard的使用


整体说明

  • TensorBoard 是 TensorFlow 提供的可视化工具,能帮助理解、调试和优化深度学习模型
  • 安装 TensorBoard
    1
    pip install tensorboard

启动 TensorBoard

  • 可以使用命令行工具执行下面的命令从一个指定目录启动 TensorBoard:

    1
    tensorboard --logdir=path/to/logs --port=6006 --host=0.0.0.0
  • 参数解释:

    • --logdir:这个参数用于指定 TensorFlow 事件文件所在的目录
      • TensorBoard 会对该目录进行监控,一旦有新的事件文件生成,它就会实时更新可视化内容
      • 可以只指定一个目录,也可以通过逗号分隔的方式指定多个目录,或者使用通配符来匹配多个目录
      • 一个目录下可以有多个子目录,TensorBoard 会同时显示,可通过页面选择勾选目标子文件夹
    • --port:此参数用于设置 TensorBoard 服务监听的端口,默认使用 6006 端口
      • 如果你想在同一台机器上同时运行多个 TensorBoard 实例,可以为它们指定不同的端口后分别启动
    • --host:通过这个参数可以设置 TensorBoard 服务监听的 IP 地址
      • 默认是 localhost(即 127.0.0.1),此时仅能在本机上访问
      • 若你想让其他机器能够访问当前机器上的 TensorBoard,可将其设置为 0.0.0.0

TensorBoard 展示细节

  • TensorBoard 启动之后,通过浏览器即可访问
  • 最常用的 TensorBoard 页面包含 Scalars、Graphs、Histograms 等,点击这些选项卡可以查看不同类型的可视化数据

TensorBoard 文件的生成

PyTorch TensorBoard 示例

  • 使用 PyTorch 生成 TensorBoard 文件的示例
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    import torch
    from torch.utils.tensorboard import SummaryWriter

    # 创建 SummaryWriter 对象,指定日志保存目录
    writer = SummaryWriter('runs/pytorch_demo')

    # 模拟训练过程
    for epoch in range(100):
    # 模拟损失值(通常是训练过程中计算得到的)
    loss = 0.9 ** epoch

    # 记录损失值到 TensorBoard
    writer.add_scalar('Loss/train', loss, epoch)

    # 模拟模型权重
    weights = torch.randn(10) * (0.95 ** epoch)

    # 记录直方图到 TensorBoard
    writer.add_histogram('Weights', weights, epoch)

    # 关闭 writer
    writer.close()

PyTorch TensorBoard 示例

  • 使用 TensorFlow 生成 TensorBoard 文件的示例
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    import tensorflow as tf
    import numpy as np

    # 创建 SummaryWriter 对象,指定日志保存目录
    writer = tf.summary.create_file_writer('runs/tensorflow_demo')

    # 模拟训练过程
    for epoch in range(100):
    # 模拟损失值
    loss = 0.9 ** epoch

    # 记录损失值到 TensorBoard
    with writer.as_default():
    tf.summary.scalar('Loss/train', loss, step=epoch)

    # 模拟模型权重
    weights = np.random.randn(10) * (0.95 ** epoch)

    # 记录直方图到 TensorBoard
    with writer.as_default():
    tf.summary.histogram('Weights', weights, step=epoch)

一些说明

  • TensorBoard 可以同时显示多个项目的数据,如上述示例就在同一个目录 runs 下分别创建了 PyTorch 和 TensorFlow 的文件夹
  • 训练过程中数据不会自动刷新,可以随时刷新浏览器查看实时更新的数据

Python——Ray-使用笔记


远程调用时传入的函数指针必须是远程函数

  • 在 Ray 中不支持直接传入 local 函数指针作为远程函数的执行对象,需通过 Ray 装饰器(@ray.remote)将函数注册为远程可执行,再通过 函数名.remote() 调用(本质是基于函数标识而非指针传递)
  • 总结:
    • 不推荐将普通函数作为参数传递给 Ray 远程函数
    • 推荐使用 @ray.remote 装饰器或在远程函数内部定义逻辑
    • 注意:一些代码在单机环境下可能碰巧能运行,但不具有可移植性和可靠性(这一点需要注意 Ray 本地调试通过可能也无法分布式运行)

错误示例(未注册本地函数)

  • 若 add 未被 @ray.remote 注册,它只是一个本地函数 ,无法在 Ray 分布式环境中执行,直接传递给远程函数(如 execute_func)会报错

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    import ray

    ray.init(ignore_reinit_error=True)

    # 未注册的本地函数
    def add(a, b):
    return a + b

    # 已注册的远程函数
    @ray.remote
    def execute_func(func, x, y):
    # 此处调用本地函数会失败,因为 func 在远程节点无定义
    # # 远程节点的工作进程无法导入本地主模块的 add_local 函数,也无法序列化传递普通函数,可能会直接抛出 SerializationError
    # # 单进程/单节点下调用指针函数可以执行,但是分布式情况下,local_func 无法被序列化,会出错
    return func(x, y) # 报错:NameError,PicklingError 或 SerializationError

    # 调用会抛出异常
    try:
    result = ray.get(execute_func.remote(add, 4, 6))
    except Exception as e:
    print("错误:", e) # 提示无法序列化或找不到函数

    ray.shutdown()
  • 核心原因:Ray 远程函数执行依赖序列化传输和集群节点间代码同步

    • 未注册的本地函数无法被序列化为集群可识别的任务,且远程节点没有该函数的定义,会导致执行失败

正确示例(远程函数调用)

  • Ray 的远程函数依赖集群调度,通过 @ray.remote 显式注册后使用远程调用函数调用

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    import ray

    ray.init(ignore_reinit_error=True)

    # 定义远程函数(会注册到 Ray 集群)
    @ray.remote
    def add(a, b):
    return a + b

    # 远程函数,可接收其他远程函数的调用结果
    @ray.remote
    def execute_func(func, x, y):
    # 这里 func 是远程函数标识,通过 .remote() 触发执行
    result = ray.get(func.remote(x, y)) # 使用远程调用的方式调用函数指针,实现调用远程函数,正确!
    # result = func(x, y) # remote 函数无法被直接调用,错误!
    # result = add(x,y) # remote 函数无法被直接调用,错误!
    # result = add_local(x, y) # add_local 当做 local 函数调用(注意:不再是指针传入),正确!
    return result

    # # 不使用 remote 直接调用 远程函数,错误
    # result1 = add(2, 3)

    # 使用remote直接调用远程函数,正确
    result1 = ray.get(add.remote(2, 3))
    print("直接调用结果:", result1) # 输出:5

    # 间接通过另一个远程函数调用(模拟"传递函数逻辑")
    result2 = ray.get(execute_func.remote(add, 2, 3))
    print("间接调用结果:", result2) # 输出:10

    ray.shutdown()
  • Ray 的远程函数依赖集群调度,需通过 @ray.remote 显式注册,无法像本地代码那样传递函数指针(内存地址在分布式环境中无效)

  • 若需在远程函数中复用其他函数逻辑,直接传递已注册的远程函数名(如示例中的 add),再通过 func.remote() 调用即可

Python——Ray-option函数讲解


整体说明

  • 在 Ray 框架中,.option() 是用于配置 Actor 或远程函数(Task) 运行时属性的方法,其参数主要围绕资源分配、调度策略、容错机制等核心功能
  • 注意事项
    • 所有参数均需符合 Ray 框架的预定义类型,传入未支持的参数会抛出错误
    • 不同 Ray 版本可能新增或调整参数,建议结合官方文档(对应版本)查阅细节
    • 这些参数仅用于配置运行时属性,自定义业务参数需通过 Actor 初始化或 Task 函数参数传递(见前文说明)

Actor 配置示例(Task 类似)

  • Actor 使用 .option() 函数的示例
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    @ray.remote
    class MyActor:
    pass

    # 配置 Actor 资源、名称和重启策略
    actor = MyActor.options(
    num_cpus=1,
    num_gpus=0.5,
    name="my_actor",
    max_restarts=2,
    runtime_env={"env_vars": {"LOG_LEVEL": "INFO"}}
    ).remote()

通用核心参数(Actor 和 Task 均支持)

  • num_cpus 参数(类型:int 或 float)
    • 指定运行该 Actor/Task 所需的 CPU 核心数(支持小数,如 0.5 表示半核)
    • 示例:MyActor.options(num_cpus=2).remote()
  • num_gpus 参数(类型:int 或 float)
    • 指定所需的 GPU 数量(需集群实际有 GPU 资源)
    • 示例:my_task.options(num_gpus=1).remote()
  • resources 参数(类型:dict(键为资源名称,值为数量))
    • 指定自定义资源需求(如特定硬件、加速器等)
    • 示例:options(resources={"custom_accelerator": 1})
  • runtime_env 参数(类型:dict)
    • 配置运行环境(如依赖库、环境变量、工作目录等),确保 Actor/Task 在一致的环境中运行
    • 示例:options(runtime_env={"pip": ["numpy==1.21.0"]})
  • name 参数(类型:str)
    • 为 Actor/Task 指定名称,用于日志追踪或通过名称查找 Actor(仅 Actor 有效)
    • 示例:MyActor.options(name="worker-1").remote()

Actor 专属参数(仅 Actor 支持)

  • max_restarts 参数(类型:int)
    • 指定 Actor 崩溃后的最大重启次数(默认 -1 表示无限重启,0 表示不重启)
    • 示例:options(max_restarts=3)
  • max_task_retries 参数(类型:int)
    • 指定 Actor 处理单个任务时的最大重试次数(任务失败后重试)
    • 示例:options(max_task_retries=2)
  • lifetime 参数(类型:str(可选值:"detached" 或 "non_detached"))
    • 设置 Actor 生命周期。"detached" 表示 Actor 可脱离创建它的进程独立存在(进程退出后不销毁)
    • 示例:options(lifetime="detached")
  • placement_group 参数(类型:PlacementGroup 实例)
    • 将 Actor 绑定到特定的 放置组(Placement Group),优化资源 locality(本地性)

Task 专属参数(仅远程函数支持)

  • retry_exceptions 参数(类型:bool 或 tuple)
    • 指定 Task 失败时是否重试,或仅对特定异常重试
    • 示例:options(retry_exceptions=(ConnectionError,))
  • num_returns 参数(类型:int)
    • 指定 Task 返回值的数量(默认 1,用于多返回值场景)
    • 示例:@ray.remote(num_returns=2) def f(): return 1, 2

其他实用参数

  • priority 参数(类型:int)
    • 设置 Task/Actor 任务的调度优先级(数值越高越优先,仅部分调度器支持)
  • memory 参数(类型:int)
    • 指定所需的内存量(字节),超过会被终止(需集群启用内存限制)
  • object_store_memory 参数(类型:int)
    • 指定 Task 可使用的对象存储内存量(字节)

附录:runtime_env 参数的详细说明

  • 在 Ray 框架中,runtime_env 是 option() 方法中用于配置 运行时环境 的核心参数
  • runtime_env 参数的作用是确保远程任务(Task)或 Actor 在分布式集群中运行时,拥有一致的依赖环境、配置和资源,解决“本地能跑,集群跑不通”的环境一致性问题
  • runtime_env 接收一个字典作为参数,支持多种环境配置项,覆盖依赖管理、环境变量、文件同步等核心场景:
  • 工作原理:当通过 option(runtime_env=...) 配置环境后,Ray 会在任务/Actor 启动前执行以下操作:
    • 1)在 提交任务的节点 上收集 runtime_env 定义的依赖、文件和配置
    • 2)将这些资源同步到 集群中的目标节点(通过 Ray 的对象存储或分布式文件系统)
    • 3)在目标节点上自动创建隔离的运行环境(如虚拟环境、Conda 环境),安装依赖并注入环境变量
    • 4)任务/Actor 在该隔离环境中启动,确保环境一致性

更多讨论

  • 在分布式计算中,集群节点的环境可能存在差异(如依赖库版本、环境变量、工作目录等)
  • runtime_env 通过预先定义环境配置,让 Ray 自动在所有执行任务的节点上同步这些配置,确保任务/Actor 在 完全一致的环境 中运行,避免因环境差异导致的错误(如“ModuleNotFoundError”“版本不兼容”等)
  • 适用场景
    • 确保所有 worker 节点使用相同版本的框架(如 PyTorch、TensorFlow)和依赖库
    • 同步本地自定义模块或配置文件到集群,避免手动在每个节点部署代码
    • 不同任务/Actor 可使用独立的依赖环境,避免版本冲突
  • 其他问题
    • 初次加载的性能开销:首次使用 runtime_env 时,同步依赖和文件可能需要时间(尤其是大文件或复杂依赖),后续任务会复用缓存
    • 确保输入路径可读:working_dir、wheel 等路径需确保提交节点和集群节点均可访问(本地路径需为集群共享存储路径,如 NFS)
    • 至少要提前安装 conda 等包:部分配置(如 conda)需集群节点预先安装 Conda,否则会失效

依赖库管理(确保三方库版本一致)

  • pip :指定需要安装的 Python 依赖包及版本,支持通过列表或 requirements.txt 路径配置,示例如下:

    1
    2
    3
    4
    5
    # 直接指定依赖
    runtime_env={"pip": ["numpy==1.24.3", "pandas==2.0.3"]}

    # 通过 requirements.txt 配置
    runtime_env={"pip": "requirements.txt"}
  • conda :指定 Conda 环境配置,支持通过 environment.yml 路径或字典定义环境,示例如下:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    # 通过 environment.yml 配置
    runtime_env={"conda": "environment.yml"}

    # 直接定义 Conda 环境
    runtime_env={
    "conda": {
    "dependencies": ["python=3.9", "numpy=1.24.3"]
    }
    }
  • wheel :指定本地 Wheel 包路径,用于安装自定义或私有库(需确保集群节点可访问路径),示例如下:

    1
    runtime_env={"wheel": "./my_custom_lib-0.1.0-py3-none-any.whl"}

环境变量与配置注入

  • env_vars :定义任务/Actor 运行时的环境变量,键值对形式传递,示例如下:

    1
    2
    3
    4
    5
    6
    runtime_env={
    "env_vars": {
    "LOG_LEVEL": "INFO", # 日志级别
    "DATA_PATH": "/data/training" # 数据路径
    }
    }
  • config :传递自定义配置字典,可在任务/Actor 中通过 ray.get_runtime_context().runtime_env.get("config") 获取,用于业务参数传递,示例如下:

    1
    runtime_env={"config": {"batch_size": 32, "epochs": 10}}

文件与目录同步(确保资源可访问)

  • working_dir :指定工作目录,Ray 会将该目录下的所有文件同步到执行任务的节点,确保代码、配置文件等资源可访问。支持本地路径或 Git 仓库 URL,示例如下:

    1
    2
    3
    4
    5
    # 同步本地目录
    runtime_env={"working_dir": "./my_project"}

    # 同步 Git 仓库(支持分支/标签)
    runtime_env={"working_dir": "https://github.com/my_repo.git#branch=main"}
  • excludes :配合 working_dir 使用,指定同步时需要排除的文件/目录(如日志、缓存文件),避免冗余同步,示例如下:

    1
    2
    3
    4
    runtime_env={
    "working_dir": "./my_project",
    "excludes": ["*.log", "venv/", "data/*"] # 排除日志、虚拟环境和数据目录
    }

其他高级配置

  • py_modules :指定需要导入的自定义 Python 模块路径,支持将本地模块添加到 Python 路径(sys.path),示例如下:

    1
    runtime_env={"py_modules": ["./my_utils"]}  # 同步 my_utils 模块并添加到路径
  • env :指定预定义的环境名称(如 Ray 集群中已配置的共享环境),避免重复配置,示例如下:

    1
    runtime_env={"env": "shared-training-env"}  # 使用集群中预定义的环境

附录:option 中使用 runtime_env 和 启动参数传入 yaml 文件的区别

  • 在 Ray 中,可以使用 ray job submit 命令提交任务到已经启动的 Ray 集群中
  • ray job submit 命令的 --runtime-env 参数也可以通过传入 yaml 文件(或 JSON 格式的字符串)指定 runtime-env 参数
  • 至此,我们有了两种指定方式:
    • 在代码中通过 option 函数(如 @ray.remote 的 runtime_env 参数)指定运行时环境
    • 在 ray job submit 命令中通过 --runtime-env 参数传入 yaml 文件指定运行时环境
  • 两者的生效级别不同:
    • --runtime-env=./runtime_env.yaml 是 全局级别的配置 ,会为整个 Ray Job 中的所有任务(包括所有 Actor、任务函数)设置默认的运行时环境
      • 适用于需要为整个作业统一配置环境的场景(如统一的工作目录、环境变量等)
    • 代码中 option 函数指定(如 @ray.remote(runtime_env=...))是局部级别的配置 ,仅对当前修饰的 Actor 或任务生效
      • 适用于为特定任务/Actor 单独设置差异化环境的场景(如某个任务需要额外的依赖包,而其他任务不需要)
  • 两者的优先级不同:
    • 局部配置(代码中 option 函数)的优先级高于全局配置(命令行 --runtime-env)
    • 当两者配置不冲突时,会进行合并(例如全局配置了 env_vars,局部配置了 pip,最终环境会同时包含这两者)
    • 当两者配置冲突时(如同一环境变量在两处被设置为不同值),局部配置会覆盖全局配置

Math——因果推断

本文介绍因果推断(Causal Inference)相关概念


参考资料

  • 讲的比较好的入门材料:
    • 参考链接:闲聊因果效应(1):当我们聊因果时,我们在聊什么
    • 参考链接:闲聊因果效应(2): 理解因果效应的计算以及PSM、IPW
  • 阿里发的一篇论文,用神经网络实现的二分类Uplift模型:
    • 参考链接:KDD‘22 阿里|DESCN: Deep Entire Space Cross Networks | 多任务、端到端、IPW的共舞

什么时候需要因果推断?

  • 是否需要因果推断主要取决于是否存在混淆因素/混淆因子(Confounders) ,即 treatment 是否是足够随机的(不受其他因素影响)
    • 如果 treatment 是完全随机分配的(即在每个状态下,treatment 是随机决定的),那么观察到的影响差异可以直接归因于 treatment 的变化,此时相关性即因果性 ,理论上不需要复杂的因果推断方法

有“足够多随机数据”时是否需要因果推断?

  • 若“随机”指完全随机实验 :不需要因果推断,直接建模即可
  • 若“随机”仅指数据量大 :仍需因果推断,因为数据量不能解决混淆偏差问题

出价中是否需要因果推断?

  • 如果出价是随机分配的 ,则可以直接用统计模型直接拟合 收益 = f(状态,出价),无需因果推断,因为随机化已消除混淆偏差
  • 如果出价是策略性选择的(如历史数据中出价高低与状态相关),则存在混淆偏差(confounding),必须用因果推断方法(如双重机器学习、倾向得分匹配)来估计条件平均处理效应(CATE)
    • 例如:高收益场景下系统更倾向出高价,此时出价与收益的关联可能混入了状态的影响

因果推断中的一致性假设

  • 一致性假设指的是:对于某一研究对象,其接受的处理(Treatment)与潜在结果(Potential Outcome)之间存在唯一且明确的对应关系
    • 具体来说,若个体 \(i\) 接受了处理 \(Z_i = z\),那么该个体的观测结果 \(Y_i\) 必然等于其在处理 \(z\) 下的潜在结果 \(Y_i(z)\),即:
      $$Y_i = Y_i(Z_i)$$

一致性假设的作用

  • 在因果推断中,我们通常需要比较同一主体在不同处理下的潜在结果差异(如因果效应 \(Y_i(1) - Y_i(0)\)),但现实中个体只能接受一种处理,无法同时观测到两种结果。一致性假设确保了:
    • 当个体接受处理 \(Z=1\) 时,观测结果 \(Y_i\) 等于其潜在结果 \(Y_i(1)\);
    • 当个体接受处理 \(Z=0\) 时,观测结果 \(Y_i\) 等于其潜在结果 \(Y_i(0)\)
  • 如此一来,我们才能通过分组(如处理组和对照组)的观测结果差异,来推断处理的因果效应(如平均因果效应 \(E[Y(1) - Y(0)]\))

目前因果推断的SOTA模型

  • CFR:Estimating individual treatment effect: generalization bounds and algorithms

Math——拟合优度


整体说明

  • 拟合优度(Goodness of Fit)是指所建立的模型对实际观测值的拟合程度
  • 在回归分析中,它衡量了自变量对因变量的解释程度,拟合优度越大,说明拟合越好
    • 拟合越好,意味着:自变量引起的变异占总变异的百分比越高,观察点在回归直线附近越密集

拟合优度的度量:决定系数 \(R^{2}\)

  • 度量拟合优度的常用统计量是决定系数(coefficient of determination) ,一般记作 \(R^{2}\)
  • \(R^{2}\) 的计算公式为:
    $$R^{2}=\frac{SSR}{SST}=1 - \frac{SSE}{SST}$$
    • \(SSR\) 为回归平方和
    • \(SSE\) 为残差平方和
    • \(SST\) 为总离差平方和
    • 注:\(SST = SSR + SSE\)
  • 若用 \(y_{i}\) 表示真实的观测值, \(\bar{y}\) 表示真实观测值的平均值, \(\hat{y}_{i}\) 表示拟合值,则 \(SSR\) 、 \(SSE\) 、 \(SST\) 的具体计算公式如下:
    • 总平方和 \(SST=\sum_{i = 1}^{n}(y_{i}-\bar{y})^{2}\)
    • 回归平方和 \(SSR=\sum_{i = 1}^{n}(\hat{y}_{i}-\bar{y})^{2}\)
    • 残差平方和 \(SSE=\sum_{i = 1}^{n}(y_{i}-\hat{y}_{i})^{2}\)

Math——最优化问题和KKT条件

凸优化&拉个朗日对偶性的直观理解


凸优化相关书籍

  • 参考链接:优化方法-资料集合

问题定义

  • 一般优化问题的定义:

$$
\begin{align}
\min_{x}\quad &f(x) \\
s.t. \quad &g_{i}(x) \leq 0, i = 1,2,\dots,k \\
&h_{j}(x) = 0, j = 1,2,\dots,l
\end{align}
$$

凸优化问题

  • 如果原始优化问题满足:
    • \(f(x)\) 和 \(g_{i}(x)\) 都是 \(\mathbb{R}^{n}\) 上连续可微的凸函数
    • \(h_{j}(x)\) 为 \(\mathbb{R}^{n}\) 上的仿射函数 (仿射函数是满足 \(h_{j}(x) = a\cdot x + b\) 的函数)
  • 那么,原始优化问题是凸优化问题

凸二次优化问题

  • 若上述凸优化问题还满足:
    • \(f(x)\) 是二次函数
    • \(g_{i}(x)\) 是 \(\mathbb{R}^{n}\) 上的仿射函数
  • 那么,原始优化问题是凸二次优化问题

朗格朗日对偶性

拉格朗日对偶性的推导
  • 原始问题定义为

$$
\begin{align}
\min_{x}\quad &f(x) \\
s.t. \quad &g_{i}(x) \leq 0, i = 1,2,\dots,k \\
&h_{j}(x) = 0, j = 1,2,\dots,l
\end{align}
$$

  • 引进拉格朗日函数有
    $$
    \begin{align}
    L(x,\alpha, \beta) = f(x) + \sum_{i=1}^{k}\alpha_{i}g_{i}(x) + \sum_{j=1}^{l}\beta_{j}h_{j}(x)
    \end{align}
    $$

  • 考虑到
    $$
    \begin{align}
    \max_{\alpha,\beta:\alpha_{i}\geq 0}L(x,\alpha, \beta)
    \end{align}
    $$

    • 当 \(x\) 满足原始问题的解时,上面的式子等价与 \(f(x)\)
    • 否则上面的式子等于无穷大 \(+\infty\)
  • 所以假设原始问题的最优值为 \(p^{\star}\),那么
    $$
    \begin{align}
    p^{\star} = \min_{x}\max_{\alpha,\beta:\alpha_{i}\geq 0}L(x,\alpha, \beta)
    \end{align}
    $$

    • (\(p^{\star}\) 不是最优参数,是最优参数对应的函数值,参数应该用 \(\mathop{\arg\max}_{x}\) 而不是 \(\max_{x}\))
  • 定义对偶问题为:
    $$
    \begin{align}
    &\max_{\alpha,\beta:\alpha_{i}\geq 0}\min_{x}L(x,\alpha, \beta) \\
    &s.t.\quad \alpha_{i} \geq 0,\quad i=1,2,\dots,k
    \end{align}
    $$

  • 假设原始问题的最优解为 \(d^{\star}\),则原始问题与对偶问题的关系为:
    $$
    \begin{align}
    d^{\star} = \max_{\alpha,\beta:\alpha_{i}\geq 0}\min_{x}L(x,\alpha, \beta) = \min_{x}\max_{\alpha,\beta:\alpha_{i}\geq 0}L(x,\alpha, \beta) = p^{\star}
    \end{align}
    $$

KKT条件
  1. 原始可行性 : \(g_{i}(x) \leq 0\), \(h_{j}(x) = 0\)
    • 所有原始约束必须满足
  2. 对偶可行性 : \(\alpha_i \geq 0\)
    • 所有的不等式约束对应的拉格朗日乘子大于等于0
  3. 互补松弛性 : \(\alpha_i g_i(x) = 0\)
    • 对于每个不等式约束 \(g_i(x)\),都有 \(\alpha_i g_i(x) = 0\),这意味着如果一个约束是紧约束(即 \(g_i(x) = 0\) ),那么对应的 \(\alpha_i\) 可以是非零的;如果一个约束是松的(即 \(g_i(x) < 0\) ),那么对应的 \(\alpha_i\) 必须为零
  4. 梯度条件 : \(\nabla_x L(x^, \alpha^, \beta^*) = 0\)
    • 在最优解处,拉格朗日函数关于 \(x\) 的梯度必须为零
  • 其他理解:
    • 对KKT条件其他角度的理解可参考周志华<<机器学习>>P404

Math——相关性指标


PLCC (Pearson Linear Correlation Coefficient)

  • 皮尔逊线性相关系数主要用于衡量预测值与真实值之间的线性相关程度
  • PLCC 反映了预测结果在数值上的准确性
    $$ PLCC = \frac{\sum_{i=1}^{n} (x_i - \bar{x})(y_i - \bar{y})}{\sqrt{\sum_{i=1}^{n} (x_i - \bar{x})^2} \sqrt{\sum_{i=1}^{n} (y_i - \bar{y})^2} } $$
    • \(x_i\) 是第 \(i\) 个样本的预测值
    • \(y_i\) 是第 \(i\) 个样本的真实值(如 MOS 分数)
    • \(\bar{x}\) 和 \(\bar{y}\) 分别是预测值和真实值的平均值
  • PLCC 的特点:
    • 对数值大小敏感
    • 要求数据呈正态分布或接近正态分布效果最好
    • 在计算前,通常需要对预测值进行非线性回归(如 Logistic 映射),以消除模型输出范围与 MOS 分数范围不一致的影响
  • 取值范围:[-1, 1]
    • 1 :完全正线性相关
    • 0 :无线性相关
    • -1 :完全负线性相关
  • 一般在 打分、评估、质量预测、对比两个分数 的场景里:
    • 0.9 ~ 1.0 :极强线性相关
    • 0.7 ~ 0.9 :强线性相关
    • 0.5 ~ 0.7 :中等线性相关
    • 0.3 ~ 0.5 :弱线性相关
    • < 0.3 :几乎无线性相关

SROCC (Spearman Rank-Order Correlation Coefficient)

  • 斯皮尔曼等级相关系数主要用于衡量预测值与真实值之间的单调性相关程度
  • SROCC 只关注数据的相对排序,而不关注具体的数值差异
    $$ SROCC = 1 - \frac{6 \sum_{i=1}^{n} d_i^2}{n(n^2 - 1)} $$
    • \(d_i = rank(x_i) - rank(y_i)\) 是第 \(i\) 个样本的预测值排名与真实值排名之差
    • \(n\) 是样本数量
  • 特点
    • 非参数指标,不要求数据分布
    • 对异常值(Outliers)更具鲁棒性
    • 只要预测值随真实值单调递增,SROCC 就会接近 1,即便它们之间不是线性关系
  • 取值范围:[-1, 1]
    • 1 :完全单调正相关
    • 0 :无单调相关
    • -1 :完全单调负相关
  • 一般分数含义:
    • 0.8 ~ 1.0 :极强单调相关
    • 0.6 ~ 0.8 :强单调相关
    • 0.4 ~ 0.6 :中等单调相关
    • 0.2 ~ 0.4 :弱单调相关
    • < 0.2 :几乎无单调相关

KROCC (Kendall Rank Correlation Coefficient)

  • 肯德尔等级相关系数 主要用于衡量预测值与真实值之间 排序的一致性程度
  • KROCC 基于成对样本的顺序一致性来度量相关性,关注的是变量之间的序数关联而非数值线性关系
    $$
    KROCC = \frac{n_c - n_d}{\sqrt{(n_0 - n_1)(n_0 - n_2)} }
    $$
    • \(n_c\) 为一致对数量:预测值与真实值相对顺序相同的样本对
    • \(n_d\) 为不一致对数量:预测值与真实值相对顺序相反的样本对
    • \(n_0 = \frac{n(n-1)}{2}\) 为总样本对数量
    • \(n_1\)、\(n_2\) 分别为预测值与真实值中存在并列秩的修正项
    • \(n\) 为样本总数
  • 特点:
    • 非参数指标,不依赖数据分布
    • 对异常值不敏感 ,鲁棒性强
    • 更适合小样本、存在并列排名的场景
    • 相比 SROCC,KROCC 对局部排序错误更敏感,解释更直观
  • 取值范围:[-1, 1]
    • 1 :预测值与真实值完全一致排序
    • 0 :随机无序 ,无等级相关
    • -1 :完全相反排序
  • 在质量评估、打分预测、偏好排序等场景中:
    • ≥ 0.60 :极强等级相关
    • 0.40 ~ 0.60 :强等级相关
    • 0.20 ~ 0.40 :中等等级相关
    • 0.10 ~ 0.20 :弱等级相关
    • < 0.10 :几乎无等级相关

附录:SROCC vs PLCC 核心差异对比

  • PLCC 和 SROCC 分别从不同的维度衡量预测值与真实值(Ground Truth)之间的相关性
    • 通常一个优秀的模型应该在两个指标上都接近 1
  • 对比表格:
    特性 PLCC SROCC
    衡量目标 线性相关性 (Linearity) 单调相关性 (Monotonicity)
    计算基础 原始数值 (Raw Values) 排名/等级 (Ranks)
    对异常值敏感度 高(异常值会显著拉低分数) 低(排名变化较小)
    数据分布要求 通常要求正态分布 无要求(非参数统计)
    应用场景 衡量预测精度(数值准不准) 衡量排序能力(好坏顺序对不对)

Math——范数和谱范数


范数的定义

  • 在数学中,范数 (Norm) 是一个函数,它将向量空间中的每个非零向量映射为一个正实数 ,直观上可以理解为向量的“长度”或“大小”
    • 注:常规聊的范数都是针对向量空间的,谱范数(Spectral Norm) 是针对矩阵空间的
  • 对于零向量,范数映射为零
  • 范数需要满足以下三个性质:
    • 1)非负性 (Non-negativity) :对于所有向量 \( x \),有\(|x| \ge 0\),且当且仅当 \(x = 0\) 时,\(|x| = 0\)
    • 2)齐次性 (Homogeneity) :对于所有标量 \( \alpha \) 和向量 \( x \),有 \(|\alpha x| = |\alpha| |x|\)
    • 3)三角不等式 (Triangle Inequality) :对于所有向量 \( x \) 和 \(y\),有 \(|x + y| \le |x| + |y|\)

常见的范数——\(L_p\) 范数

  • \(L_p\) 范数,也称为 Minkowski 范数,定义为:
    $$|x|_p = \left( \sum_{i=1}^n |x_i|^p \right)^{\frac{1}{p} }$$
    • \(x = [x_1, x_2, \dots, x_n]^T\) 是一个 \(n\) 维向量
    • \(p \ge 1\) 是一个实数

\(L_1\) 范数 (Manhattan Norm / Taxicab Norm)

  • 当 \(p=1\) 时,称为 \(L_1\) 范数,表示向量中所有元素的绝对值之和
  • \(L_1\) 范数衡量的是向量元素到原点的曼哈顿距离
    $$|x|_1 = \sum_{i=1}^n |x_i|$$
  • 在机器学习中,常用于稀疏表示和特征选择(如 Lasso 回归),因为它倾向于产生稀疏解

\(L_2\) 范数 (Euclidean Norm)

  • 当 \(p=2\) 时,称为 \(L_2\) 范数,表示向量的欧几里得长度,即从原点到向量的欧几里得距离
    $$|x|_2 = \sqrt{\sum_{i=1}^n |x_i|^2}$$
  • \(L_2\) 范数是最常见的范数,广泛应用于各种领域,如机器学习中的岭回归 (Ridge Regression)、深度学习中的权重衰减 (Weight Decay) 以及距离计算

\(L_\infty\) 范数 (Maximum Norm / Chebyshev Norm)

  • 当 \(p \to \infty\) 时,称为 \(L_\infty\) 范数,表示向量中所有元素的绝对值的最大值
    $$|x|_\infty = \max_{i} |x_i|$$
  • 在一些优化问题中,当需要限制向量中最大分量的大小时会使用到

矩阵范数

  • 矩阵范数是定义在矩阵空间上的范数,除了满足向量范数的三个性质外,对于矩阵乘法还需满足:
    $$
    |AB| \leq |A| |B|
    $$

诱导范数(算子范数)

  • 对于矩阵 \( A \in \mathbb{C}^{m \times n} \),由向量范数 \( |\cdot|_p \) 诱导的矩阵范数定义为:
    $$
    |A|_p = \sup_{x \neq 0} \frac{|Ax|_p}{|x|_p} = \sup_{|x|_p=1} |Ax|_p
    $$
  • 特殊情况下,有以下范数:
    • 1)列和范数(诱导自 \(L_1\) 范数) :
      $$
      |A|_1 = \max_{1 \leq j \leq n} \sum_{i=1}^m |a_{ij}|
      $$
      • 按列求和,再取最大者
    • 2)谱范数(诱导自 \(L_2\) 范数) :
      $$
      |A|_2 = \sqrt{\lambda_{\max}(A^* A)}
      $$
      • 其中 \( \lambda_{\max} \) 表示最大特征值,\( A^* \) 是 \( A \) 的共轭转置
    • 3)行和范数(诱导自 \(L_\infty\) 范数) :
      $$
      |A|_\infty = \max_{1 \leq i \leq m} \sum_{j=1}^n |a_{ij}|
      $$
      • 按行求和,再取最大者

常用的矩阵范数——谱范数

  • 谱范数(Spectral Norm) 是矩阵范数的一种,它通常特指矩阵的 \(L_2\) 范数,即诱导 \(L_2\) 范数
  • 谱范数是矩阵分析中最重要的范数之一,具有许多优良性质

谱范数定义

  • 对于矩阵 \( A \in \mathbb{C}^{m \times n} \),其谱范数定义为:
    $$
    |A|_2 = \sup_{x \neq 0} \frac{|Ax|_2}{|x|_2} = \sigma_{\max}(A)
    $$
    • 其中 \( \sigma_{\max}(A) \) 是 \( A \) 的最大奇异值
  • 谱范数的更容易理解的另一个形式为:
    $$|A|_2 = \max_{x \ne 0} \frac{|Ax|_2}{|x|_2}$$
    • 这个定义表明,谱范数是矩阵 \(A\) 对向量 \(x\) 进行线性变换后 ,最大可能的“放大倍数”
    • 换句话说,它衡量了矩阵 \(A\) 在将单位向量 \(x\) 映射到 \(Ax\) 时,所能达到的最大长度

谱范数计算方法

  • 1) 计算 \( A^* A \)(实矩阵时计算 \( A^T A \) 即可)
    • 注:\( A^* \) 是共轭转置 ,对于实矩阵为普通转置 \( A^T\)
  • 2) 求 \( A^* A \) 的最大特征值 \( \lambda_{\max} \)
  • 3) 谱范数为 \( \sqrt{\lambda_{\max} } \)

谱范数性质

  • 1) 次乘性 :\( |AB|_2 \leq |A|_2 |B|_2 \)
  • 2) 酉不变性 :对于任意酉矩阵 \( U \) 和 \( V \),有 \( |UAV|_2 = |A|_2 \)
    • 注:酉矩阵(Unitary Matrix)的共轭转置(即 Hermitian 转置)等于其逆矩阵:
      $$ U^*U = UU^* = I$$
  • 3) 与Frobenius范数的关系 :\( |A|_2 \leq |A|_F \leq \sqrt{\operatorname{rank}(A)} |A|_2 \)
  • 4) 与特征值的关系 :对于正规矩阵,谱范数等于谱半径 \( \rho(A) = \max |\lambda_i| \)

谱范数的应用

  • 矩阵近似 :在低秩近似中,谱范数度量了近似误差

附录:谱范数与奇异值

  • 谱范数有一个非常重要的性质,它等于矩阵 \(A\) 的最大奇异值
  • 矩阵 \(A\) 的奇异值是其正定半定矩阵 \(A^T A\)(或 \(A A^T\))的特征值的平方根
  • 令 \(\sigma_1 \ge \sigma_2 \ge \dots \ge \sigma_r > 0\) 为矩阵 \(A\) 的非零奇异值,其中 \(r = \text{rank}(A)\)。那么,谱范数可以表示为:
    $$|A|_2 = \sigma_{\max}(A) = \sqrt{\lambda_{\max}(A^T A)}$$
    • \(\sigma_{\max}(A)\) 表示矩阵 \(A\) 的最大奇异值
    • \(\lambda_{\max}(A^T A)\) 表示矩阵 \(A^T A\) 的最大特征值
  • 推导简述 :
    • 考虑 \(A^T A\) 是一个对称半正定矩阵,它的特征值都是非负的
    • 对于任意非零向量 \(x\),我们有:
      $$\frac{|Ax|_2^2}{|x|_2^2} = \frac{(Ax)^T (Ax)}{x^T x} = \frac{x^T A^T A x}{x^T x}$$
    • 根据瑞利商 (Rayleigh Quotient) 的性质,\(\max_{x \ne 0} \frac{x^T M x}{x^T x} = \lambda_{\max}(M)\),其中 \(M\) 是对称矩阵
    • 因此:
      $$\max_{x \ne 0} \frac{|Ax|_2^2}{|x|_2^2} = \lambda_{\max}(A^T A)$$
    • 取平方根后即可得到 \(|A|_2 = \sqrt{\lambda_{\max}(A^T A)} = \sigma_{\max}(A)\)
  • 谱范数用于正则化 :在机器学习中,谱范数可以用于限制模型的复杂度,例如在深度学习中,限制神经网络层的权重矩阵的谱范数可以帮助防止过拟合

附录:共轭转置

  • 共轭转置(Conjugate Transpose),也称为Hermitian转置 ,是线性代数中对矩阵的一种操作,记作 \( A^* \)、\( A^H \) 或 \( A^\dagger \)
  • 共轭转置 对矩阵 \( A \) 进行以下两步运算:
    • 1) 共轭 :将矩阵 \( A \) 的每个元素取复共轭(即实部不变,虚部取反)
    • 2) 转置 :将矩阵的行列互换(即第 \( i \) 行第 \( j \) 列元素变为第 \( j \) 行第 \( i \) 列)

与普通转置对比

  • 普通转置(\( A^T \)) :仅行列互换,不取共轭
  • 实矩阵的共轭转置 :退化为普通转置(因虚部为零)

附录:Schatten-\( p \) 范数是什么?

  • Schatten-\( p \) 范数(Schatten-\( p \) norm)是矩阵空间中一类重要的范数,常用于描述矩阵的“大小”或“强度”
  • Schatten-\( p \) 范数 基于矩阵的奇异值(singular values)定义,适用于更广泛的矩阵分析场景(如紧算子、核范数等)

Schatten-\( p \) 范数的定义

  • 设矩阵 \( A \in \mathbb{C}^{m \times n} \) 的奇异值为 \( \sigma_1 \geq \sigma_2 \geq \cdots \geq \sigma_r > 0 \)(其中 \( r = \min(m, n) \)),则其 Schatten-\( p \) 范数定义为:
    $$
    |A|_{S_p} = \left( \sum_{i=1}^r \sigma_i^p \right)^{1/p}, \quad p \in [1, \infty).
    $$

Schatten-\( p \) 范数的特例

  • 1) \( p = 1 \)(核范数,Nuclear norm)
    $$ |A|_{S_1} = \sum_{i=1}^r \sigma_i $$
    • 用于矩阵低秩恢复、压缩感知等
  • 2) \( p = 2 \)(Frobenius 范数,也称 F 范数)
    $$ |A|_{S_2} = \left( \sum_{i=1}^r \sigma_i^2 \right)^{1/2} = \sqrt{\text{tr}(A^* A)} $$
    • 即矩阵元素的平方和开根号
  • 3) \( p = \infty \)(谱范数,Spectral norm)
    $$ |A|_{S_\infty} = \sigma_1 $$
    • 等于矩阵的最大奇异值,也是算子范数的一种

附录:Frobenius 范数的更多说明

  • Frobenius范数(F 范数)是矩阵的一种常用范数,用于衡量矩阵的“大小”
  • 它将矩阵视为一个向量,计算其所有元素的平方和的平方根
  • 对于一个 \( m \times n \) 的矩阵 \( A = (a_{ij}) \),其Frobenius范数定义为:
    $$
    |A|_F = \sqrt{\sum_{i=1}^{m} \sum_{j=1}^{n} |a_{ij}|^2}
    $$
    • 等价于矩阵所有元素的平方和再开平方
    • 在 PyTorch 中的实现为 A.norm()
1…222324…63
Joe Zhou

Joe Zhou

Stay Hungry. Stay Foolish.

630 posts
53 tags
GitHub E-Mail
© 2026 Joe Zhou
Powered by Hexo
|
Theme — NexT.Gemini v5.1.4