optimizer.zero_grad(), loss.backward(), optimizer.step()的理解及使用

这篇具有很好参考价值的文章主要介绍了optimizer.zero_grad(), loss.backward(), optimizer.step()的理解及使用。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

用法介绍

这三个函数的作用是将梯度归零(optimizer.zero_grad()),然后反向传播计算得到每个参数的梯度值(loss.backward()),最后通过梯度下降执行一步参数更新(optimizer.step())。

简单的说就是进来一个batch的数据,先将梯度归零,计算一次梯度,更新一次网络。

model = MyModel()
criterion = nn.CrossEntropyLoss()
optimizer = torch.optim.SGD(model.parameters(), lr=0.001, momentum=0.9, weight_decay=1e-4)
scheduler = torch.optim.lr_scheduler.CosineAnnealingLR(optimizer, T_max=10000)
 
for epoch in range(1, epochs):
    for i, (inputs, labels) in enumerate(train_loader):
    	inputs= inputs.to(device=device)
    	labels= labels.to(device=device)
    	# forward
        output= model(inputs)
        loss = criterion(output, labels)
        # backward
        optimizer.zero_grad()
        loss.backward()
        # gardient descent or adam step
        optimizer.step()
    scheduler.step()

另外一种:将optimizer.zero_grad() 放在 optimizer.step() 后面,即梯度累加。

  1. 获取loss:输入图像和标签,通过infer计算得到预测值,计算损失函数;
  2. loss.backward() 反向传播,计算当前梯度;
  3. 多次循环步骤1-2,不清空梯度,使梯度累加在已有梯度上;
  4. 梯度累加了一定次数后,先optimizer.step() 根据累计的梯度更新网络参数,然后optimizer.zero_grad() 清空过往梯度,为下一波梯度累加做准备;

总结来说:梯度累加就是,每次获取1个batch的数据,计算1次梯度,梯度不清空,不断累加,累加一定次数后,根据累加的梯度更新网络参数,然后清空梯度,进行下一次循环。

一定条件下,batchsize越大训练效果越好,梯度累加则实现了batchsize的变相扩大,如果accumulation_steps为8,则batchsize ‘变相’ 扩大了8倍,是我们这种乞丐实验室解决显存受限的一个不错的trick,使用时需要注意,学习率也要适当放大。
参考链接:https://blog.csdn.net/weixin_36670529/article/details/108630740

optimizer.zero_grad():

param_groups:Optimizer类在实例化时会在构造函数中创建一个param_groups列表,列表中有num_groups个长度为6的param_group字典(num_groups取决于你定义optimizer时传入了几组参数),每个param_group包含了 [‘params’, ‘lr’, ‘momentum’, ‘dampening’, ‘weight_decay’, ‘nesterov’] 这6组键值对。

param_group[‘params’]:由传入的模型参数组成的列表,即实例化Optimizer类时传入该group的参数,如果参数没有分组,则为整个模型的参数model.parameters(),每个参数是一个torch.nn.parameter.Parameter对象。

def zero_grad(self):
    r"""Clears the gradients of all optimized :class:`torch.Tensor` s."""
    for group in self.param_groups:
        for p in group['params']:
            if p.grad is not None:
                p.grad.detach_()
                p.grad.zero_()

optimizer.zero_grad()函数会遍历模型的所有参数,通过p.grad.detach_()方法截断反向传播的梯度流,再通过p.grad.zero_()函数将每个参数的梯度值设为0,即上一次的梯度记录被清空。

因为训练的过程通常使用mini-batch方法,所以如果不将梯度清零的话,梯度会与上一个batch的数据相关,因此该函数要写在反向传播和梯度下降之前。

loss.backward():

PyTorch的反向传播(即tensor.backward())是通过autograd包来实现的,autograd包会根据tensor进行过的数学运算来自动计算其对应的梯度。

具体来说,torch.tensor是autograd包的基础类,如果你设置tensor的requires_grads为True,就会开始跟踪这个tensor上面的所有运算,如果你做完运算后使用tensor.backward(),所有的梯度就会自动运算,tensor的梯度将会累加到它的.grad属性里面去。

更具体地说,损失函数loss是由模型的所有权重w经过一系列运算得到的,若某个w的requires_grads为True,则w的所有上层参数(后面层的权重w)的.grad_fn属性中就保存了对应的运算,然后在使用loss.backward()后,会一层层的反向传播计算每个w的梯度值,并保存到该w的.grad属性中。

如果没有进行tensor.backward()的话,梯度值将会是None,因此loss.backward()要写在optimizer.step()之前。

optimizer.step():

以SGD为例,torch.optim.SGD().step()源码如下:

def step(self, closure=None):
    """Performs a single optimization step.
    Arguments:
        closure (callable, optional): A closure that reevaluates the model
            and returns the loss.
    """
    loss = None
    if closure is not None:
        loss = closure()

    for group in self.param_groups:
        weight_decay = group['weight_decay']
        momentum = group['momentum']
        dampening = group['dampening']
        nesterov = group['nesterov']

        for p in group['params']:
            if p.grad is None:
                continue
            d_p = p.grad.data
            if weight_decay != 0:
                d_p.add_(weight_decay, p.data)
            if momentum != 0:
                param_state = self.state[p]
                if 'momentum_buffer' not in param_state:
                    buf = param_state['momentum_buffer'] = torch.clone(d_p).detach()
                else:
                    buf = param_state['momentum_buffer']
                    buf.mul_(momentum).add_(1 - dampening, d_p)
                if nesterov:
                    d_p = d_p.add(momentum, buf)
                else:
                    d_p = buf

            p.data.add_(-group['lr'], d_p)

    return loss

step()函数的作用是执行一次优化步骤,通过梯度下降法来更新参数的值。因为梯度下降是基于梯度的,所以在执行optimizer.step()函数前应先执行loss.backward()函数来计算梯度。

注意:optimizer只负责通过梯度下降进行优化,而不负责产生梯度,梯度是tensor.backward()方法产生的。文章来源地址https://www.toymoban.com/news/detail-699628.html

到了这里,关于optimizer.zero_grad(), loss.backward(), optimizer.step()的理解及使用的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • torch之optimizer.step() 与 scheduler.step() 的用法

      首先需要明确optimzier优化器的作用, 形象地来说,优化器就是需要根据网络反向传播的梯度信息来更新网络的参数,以起到降低loss函数计算值的作用,这也是机器学习里面最一般的方法论。   optimizer.step()通常用在每个mini-batch之中,可以根据具体的需求来做。只有用了

    2024年02月16日
    浏览(33)
  • pytorch | loss不收敛或者训练中梯度grad为None的问题

    原因定位: https://blog.csdn.net/weixin_44231148/article/details/107240840 Pytorch中自定义网络参数,存在梯度但不进行更新 - 漱石的文章 - 知乎 https://zhuanlan.zhihu.com/p/92729376 https://zhuanlan.zhihu.com/p/508458545 介绍hooks: https://zhuanlan.zhihu.com/p/553627695 https://medium.com/analytics-vidhya/pytorch-hooks-5909c7636

    2024年02月08日
    浏览(36)
  • 损失函数loss和优化器optimizer

    损失函数与优化器的关联_criterion(outputs, labels)_写代码_不错哦的博客-CSDN博客 https://blog.csdn.net/shenjianhua005/article/details/123971915?ops_request_misc=request_id=6583569ecbdc4daf89dbf2d43eac9242biz_id=utm_medium=distribute.pc_search_result.none-task-blog-2~all~koosearch~default-2-123971915-null-null.142^v93^koosearch_v1utm_term=

    2024年02月08日
    浏览(30)
  • DeepSpeed零冗余优化器Zero Redundancy Optimizer

    内容 零概述 培训环境 启用零优化 训练 1.5B 参数 GPT-2 模型 训练 10B 参数 GPT-2 模型 使用 ZeRO-Infinity 训练万亿级模型 使用 ZeRO-Infinity 卸载到 CPU 和 NVMe 分配 Massive Megatron-LM 模型 以内存为中心的平铺 注册外部参数 提取权重 如果您还没有这样做,我们建议您在逐步完成本教程之

    2024年02月09日
    浏览(28)
  • 深入理解PyTorch中的train()、eval()和no_grad()

    ❤️觉得内容不错的话,欢迎点赞收藏加关注😊😊😊,后续会继续输入更多优质内容❤️ 👉有问题欢迎大家加关注私戳或者评论(包括但不限于NLP算法相关,linux学习相关,读研读博相关......)👈 (封面图由文心一格生成) 在PyTorch中,train()、eval()和no_grad()是三个非常重

    2023年04月08日
    浏览(36)
  • loss scale的理解

    近期看代码的时候发现了loss_scale的参数,不知道为什么算loss还需要放缩,在参数说明中,当只有选择了fp16精度的选项时,loss_scale才有效。 查了资料,简单记录一下: 参考:资料 定义: Loss Scaling 在计算loss时适当放大loss,在优化器更新参数时缩小同样倍数梯度。目前apex支

    2024年02月09日
    浏览(22)
  • Generalized Focal Loss论文个人理解

    论文地址:Generalized Focal Loss: Towards Efficient Representation Learning for Dense Object Detection 论文解决问题 研究人员最近更加关注边界框的表示(representation)及其定位质量估计(LQE,本论文中指的是IoU score),导致该领域取得了令人鼓舞的进展。具体来说,边界框表示被建模为简单的狄

    2024年02月01日
    浏览(32)
  • Proximal Policy Optimization (PPO) 算法理解:从策略梯度开始

    近端策略优化(PPO)算法是OpenAI在2017提出的一种强化学习算法,被认为是目前强化学习领域的SOTA方法,也是适用性最广的算法之一。本文将从PPO算法的基础入手,理解从传统策略梯度算法(例如REIFORCE算法)、自然策略梯度算法、信赖域策略优化算法(TRPO)直到PPO算法的演

    2023年04月26日
    浏览(68)
  • 关于num_steps_all = len(train_loader) // configs.gradient_accumulation_steps * configs.epochs的理解,文心一言

    当然可以,我会尽量用简单的语言来解释这行代码。 这行代码计算的是在整个训练过程中,模型参数会更新的总次数。 len(train_loader) :这表示你的训练数据被分成了多少份(或称为“批次”)。想象一下你有100张纸,每张纸上写了一些训练数据,那么这里的 len(train_loader) 就

    2024年02月03日
    浏览(23)
  • python:torch.no_grad()的作用 + requires_grad,grad_fn,grad的含义及使用

    requires_grad: grad_fn: grad: 说法1: 说法2: 代码: 保证param原地数值改变操作下requires_grad=True不变。 参考资料: requires_grad,grad_fn,grad的含义及使用 测试torch.no_grad()的作用 pytorch中torch.no_grad有什么用? PyTorch 中的“with torch no_grad”有什么作用?

    2024年02月17日
    浏览(34)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包