【diffusers极速入门(六)】缓存梯度和自动放缩学习率以及代码详解

63 篇文章 2 订阅
31 篇文章 1 订阅

系列文章目录



在深度学习训练过程中,缓存梯度和自动放缩学习率是两个非常重要的技术,它们能够帮助提高训练效率和稳定性。以下是对这两个技术的详细解释以及对应的代码解释。

本文解释的代码来源于 /path/to/diffusers/examples/dreambooth/train_dreambooth_sd3.py

一、缓存梯度是什么?

标准训练过程: 前向传播和反向传播各进行一次,没有额外的计算。
缓存梯度技术: 前向传播仅进行一次,但反向传播过程中由于需要重新计算未存储的激活值,导致反向传播时间增加。

  • 缓存梯度(Gradient Checkpointing)是一种技术,通过在前向传播过程中存储部分中间激活值,减少内存占用量
  • 这样可以在反向传播时重新计算这些激活值,以节省显存。
  • 这种方法通常会导致反向传播速度变慢,但可以训练更深和更大的模型。

为什么只是反向传播变慢?

  1. 训练过程中,标准的前向和反向传播过程:
    • 前向传播(Forward Pass): 计算模型的输出,同时存储所有中间激活值(即每一层的输出)
    • 反向传播(Backward Pass): 使用存储的中间激活值计算梯度,并更新模型参数
  2. 缓存梯度技术的工作原理
    • 其主要目标是减少内存占用。
    • 它的工作原理如下:
      • 前向: 仅存储部分关键的中间激活值(检查点),其余的中间激活值不存储。
      • 反向: 当需要用到未存储的中间激活值时,重新计算这些激活值
  3. 为什么反向传播变慢?
    因为需要重新计算激活值。在反向传播过程中,当需要计算梯度时,必须重新计算之前未存储的中间激活值。这意味着:每次反向传播到一个未存储的层时,需要从最近的检查点重新进行前向传播,计算出该层的激活值。这种重新计算会导致额外的计算开销。
  4. 具体示例如下
    假设我们有一个简单的三层网络,使用缓存梯度技术并在第二层处设置检查点
前向传播
前向传播
前向传播
反向传播:计算第3层梯度
反向传播: 计算第2层梯度
反向传播: 计算第1层梯度
输入数据
第1层激活值-已存储
第2层:激活值-检查点已存储
第3层: 计算但不存储激活值
  • 如果我们前向只在第2层设置检查点,计算第3层梯度时无需额外计算,但计算第1层梯度时需要重新计算第2层的激活值。
  • 这意味着每次反向传播到第1层时,都需要重新进行一次前向传播到第2层,增加了计算量

相关代码

if args.gradient_checkpointing:
    transformer.enable_gradient_checkpointing()
    if args.train_text_encoder:
        text_encoder_one.gradient_checkpointing_enable()
        text_encoder_two.gradient_checkpointing_enable()
        text_encoder_three.gradient_checkpointing_enable()
...
parser.add_argument(
    "--gradient_checkpointing",
    action="store_true",
    help="Whether or not to use gradient checkpointing to save memory at the expense of slower backward pass.",
)
  • 检查是否启用缓存梯度: if args.gradient_checkpointing: 检查命令行参数中是否启用了缓存梯度。
  • 启用缓存梯度:
    • transformer.enable_gradient_checkpointing():为 transformer 模型启用缓存梯度。
    • text_encoder_one.gradient_checkpointing_enable() 等:为多个文本编码器启用缓存梯度。
  • 命令行参数: --gradient_checkpointing 是一个布尔类型参数,用于指示是否启用缓存梯度。启用后,可以通过 action=“store_true” 将其设置为 true。

二、自动放缩学习率

  • 自动放缩学习率是一种根据训练配置自动调整初始学习率的方法
  • 当使用多个 GPU 或者增加批量大小时,需要相应地调整学习率以保持训练的稳定性和效果。
  • 常见的做法是将学习率(learning_rate)乘以一个因子,该因子与 GPU 数量(num_processes)、梯度累积步数(gradient_accumulation_steps)和批量大小(train_batch_size)相关。
  • 具体如下方代码所示
if args.scale_lr:
    args.learning_rate = (
        args.learning_rate * args.gradient_accumulation_steps * args.train_batch_size * accelerator.num_processes
    )
...
parser.add_argument(
    "--scale_lr",
    action="store_true",
    default=False,
    help="Scale the learning rate by the number of GPUs, gradient accumulation steps, and batch size.",
)
parser.add_argument(
    "--learning_rate",
    type=float,
    default=1e-4,
    help="Initial learning rate (after the potential warmup period) to use.",
)
parser.add_argument(
        "--gradient_accumulation_steps",
        type=int,
        default=1,
        help="Number of updates steps to accumulate before performing a backward/update pass.",
    )
parser.add_argument(
        "--train_batch_size", type=int, default=4, help="Batch size (per device) for the training dataloader."
    )

  • 检查是否启用自动放缩学习率: if args.scale_lr: 检查命令行参数中是否启用了自动放缩学习率。
  • 计算新学习率: 根据梯度累积步数、批量大小和 GPU 数量(由 accelerator.num_processes 提供)调整学习率。
    • 通过 args.learning_rate * args.gradient_accumulation_steps * args.train_batch_size * accelerator.num_processes 计算得到新的学习率。
    • 命令行参数:
      • –scale_lr 是一个布尔类型参数,用于指示是否启用自动放缩学习率,默认值为 False。
      • –learning_rate 用于指定初始学习率,默认值为 1e-4。

总结

  • 缓存梯度(Gradient Checkpointing): 通过在前向传播过程中存储部分中间激活值,减少显存占用,代价是反向传播速度变慢。适用于需要训练非常深或大的模型的情况。
  • 自动放缩学习率(Learning Rate Scaling): 根据训练配置(如 GPU 数量(num_processes)、梯度累积步数和批量大小)自动调整学习率,以适应不同的训练环境和配置,确保训练的稳定性和效果。
  • 18
    点赞
  • 9
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
如果提供足够多和精确的描述,我们可以更明确地了解diffusers pipeline和Semantic Guidance的diffusers pipeline之间的差异。 Diffusers pipeline是一种生成图像的技术流程,它主要关注优化图像的像素级别特征,例如颜色、纹理等。它通常使用优化算法,如梯度下降,通过最小化或最大化某个损失函数来生成图像。这种方法通常没有直接考虑图像中的语义信息,而是依赖于视觉特征的优化。 相比之下,Semantic Guidance的diffusers pipeline在生成过程中引入了语义信息,以确保生成的图像与期望的语义内容相符。这种方法使用预训练的语义分割模型或其他语义理解方法来提取图像中的语义标签或特征。然后,通过设置目标语义分布或引入语义损失函数,将语义信息作为指导来约束生成图像。 具体而言,Semantic Guidance的diffusers pipeline在优化生成过程中会考虑以下方面: 1. 语义分割:使用预训练的语义分割模型提取图像中不同物体的语义标签或特征。 2. 目标语义分布:设置一个目标语义分布来约束生成图像中需要有哪些语义元素,并使生成图像与目标语义分布之间的差异最小化。 3. 语义损失函数:引入语义损失函数来度量生成图像与目标语义分布之间的差异,并将其加入到优化过程中。 通过引入语义信息,Semantic Guidance的diffusers pipeline可以更好地控制生成图像的语义内容,使生成结果更具有语义一致性和可解释性。 总结而言,diffusers pipeline主要关注像素级别特征的优化,而Semantic Guidance的diffusers pipeline在生成过程中引入了语义信息,以更好地控制生成图像的语义内容。这使得生成的图像更具有语义合理性和一致性。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值