torch.optim

以下是关于 torch.optim 的总结和解释:


1. torch.optim 是什么?

torch.optim 是 PyTorch 中用于实现各种优化算法的包。它提供了许多常用的优化器(如 SGD、Adam 等),并且接口设计通用,便于扩展和集成更复杂的优化算法。


2. 如何使用优化器?

(1) 构建优化器

要使用 torch.optim,需要创建一个优化器对象。该对象会保存当前状态,并基于计算出的梯度更新模型参数。

  • 基本用法
    将模型的参数传递给优化器,并设置优化选项(如学习率、动量等):

    optimizer = optim.SGD(model.parameters(), lr=0.01, momentum=0.9)
    optimizer = optim.Adam([var1, var2], lr=0.0001)
    
  • 命名参数用法
    如果需要处理命名参数,可以使用 named_parameters() 方法:

    optimizer = optim.SGD(model.named_parameters(), lr=0.01, momentum=0.9)
    optimizer = optim.Adam([('layer0', var1), ('layer1', var2)], lr=0.0001)
    

(2) 每参数选项

torch.optim 支持为不同的参数组指定独立的优化选项。例如,可以为不同的层设置不同的学习率:

optimizer = optim.SGD([
    {'params': model.base.parameters(), 'lr': 1e-2},
    {'params': model.classifier.parameters()}
], lr=1e-3, momentum=0.9)
  • model.base 使用学习率为 1e-2
  • model.classifier 使用默认学习率为 1e-3
  • 所有参数共享动量值 0.9

(3) 参数分组示例:避免对偏置项进行权重衰减

有时我们需要对某些参数(如偏置项)应用不同的正则化策略。可以通过分组实现:

bias_params = [p for name, p in model.named_parameters() if 'bias' in name]
others = [p for name, p in model.named_parameters() if 'bias' not in name]

optimizer = optim.SGD([
    {'params': others},
    {'params': bias_params, 'weight_decay': 0}
], weight_decay=1e-2, lr=1e-2)
  • 偏置项不应用权重衰减(weight_decay=0)。
  • 其他参数使用默认权重衰减(weight_decay=1e-2)。

3. 更新参数(优化步骤)

所有优化器都实现了 step() 方法,用于更新参数。有两种使用方式:

(1) 简单调用

适用于大多数优化器(如 SGD、Adam)。在计算梯度后调用 step()

for input, target in dataset:
    optimizer.zero_grad()  # 清空梯度
    output = model(input)  # 前向传播
    loss = loss_fn(output, target)  # 计算损失
    loss.backward()  # 反向传播,计算梯度
    optimizer.step()  # 更新参数

(2) 使用闭包

某些优化算法(如 LBFGS、共轭梯度)需要多次重新评估函数值。这时需要传入一个闭包,允许优化器重新计算模型:

for input, target in dataset:
    def closure():
        optimizer.zero_grad()  # 清空梯度
        output = model(input)  # 前向传播
        loss = loss_fn(output, target)  # 计算损失
        loss.backward()  # 反向传播,计算梯度
        return loss  # 返回损失值

    optimizer.step(closure)  # 更新参数

4. 总结

  • 核心功能
    torch.optim 提供了多种优化器(如 SGD、Adam),并支持灵活的参数分组和优化选项。

  • 构建优化器

    • 可以直接传递模型参数或命名参数。
    • 支持每参数选项(如不同学习率、权重衰减)。
  • 更新参数

    • 大多数优化器通过 optimizer.step() 更新参数。
    • 对于复杂优化算法(如 LBFGS),需要使用闭包。
  • 应用场景

    • 设置不同层的学习率。
    • 针对特定参数(如偏置项)调整优化选项。
    • 在训练过程中动态调整超参数。

torch.optim 的灵活性使其成为深度学习模型训练中的重要工具,能够满足从简单到复杂的优化需求。

总结解释

torch.optim.Optimizer 是 PyTorch 中所有优化器的基类,它为创建和管理优化算法提供了基础结构。以下是对 Optimizer 类及其相关概念、方法以及不同优化算法实现的总结:

1. 基础介绍

  • 参数要求
    传递给 Optimizer 的参数集合需要具有确定性的顺序,并且在不同的运行之间保持一致。这意味着像集合或字典值迭代器这样的对象不满足要求。

  • 主要参数

    • params: 一个包含 torch.Tensor 或者 dict 的可迭代对象,指定了哪些张量需要被优化。
    • defaults: 包含优化选项默认值的字典(当参数组未指定时使用)。

2. 主要方法

  • add_param_group
    向优化器的 param_groups 添加一个新的参数组。

  • load_state_dict & state_dict
    分别用于加载和保存优化器的状态。这对于恢复训练特别有用。

  • register_load_state_dict_pre_hook & register_load_state_dict_post_hook
    注册在调用 load_state_dict() 之前和之后执行的钩子。

  • step
    执行单个优化步骤以更新参数。某些优化器可能需要提供闭包来重新计算损失。

  • zero_grad
    将所有优化的 torch.Tensor 的梯度重置为零。

3. 钩子机制

  • 提供了注册钩子的功能,允许用户在特定事件发生前后插入自定义逻辑,如在执行 optimizer.step() 之前或之后,或者在保存/加载状态字典时。

4. 支持的优化算法

PyTorch 提供了一系列内置优化算法,包括但不限于:

  • Adadelta, Adagrad, Adam, AdamW, RMSprop, SGD 等
    每种算法都有其特定的应用场景和优势。

5. 实现分类

优化器的实现可以分为三类:

  • for-loop:最基本的形式,通过循环遍历参数进行计算。
  • foreach:更高效的实现方式,将多个参数组合成一个多张量并一次性处理,减少了内核调用次数。
  • fused:进一步融合了计算过程到单个内核中,理论上性能最优,但稳定性仍在测试中。
可用性和稳定性
  • 大多数现代优化器默认采用 foreach 实现,因其通常比传统的 for-loop 更快。
  • 对于一些优化器(如 Adam, AdamW, SGD),还提供了 fused 实现,尤其在 GPU 上能提供更好的性能,不过目前这些实现还在 beta 测试阶段,特别是在 CPU 和 MPS 设备上的支持有限。

这个设计使得 PyTorch 能够灵活地适应不同的硬件环境和性能需求,同时保证了代码的可读性和通用性。根据具体的应用场景选择合适的优化器和其实现方式,可以帮助提高模型训练的效率和效果。

posted @ 2025-04-27 11:15  玉米面手雷王  阅读(101)  评论(0)    收藏  举报