pytorch loss反向传播出错的解决方案

作者:liguiyuan112 时间:2023-04-06 07:20:55 

今天在使用pytorch进行训练,在运行 loss.backward() 误差反向传播时出错 :

RuntimeError: grad can be implicitly created only for scalar outputs

File "train.py", line 143, in train
loss.backward()
File "/usr/local/lib/python3.6/dist-packages/torch/tensor.py", line 198, in backward
torch.autograd.backward(self, gradient, retain_graph, create_graph)
File "/usr/local/lib/python3.6/dist-packages/torch/autograd/__init__.py", line 94, in backward
grad_tensors = _make_grads(tensors, grad_tensors)
File "/usr/local/lib/python3.6/dist-packages/torch/autograd/__init__.py", line 35, in _make_grads
raise RuntimeError("grad can be implicitly created only for scalar outputs")
RuntimeError: grad can be implicitly created only for scalar outputs

问题分析:

因为我们在执行 loss.backward() 时没带参数,这与 loss.backward(torch.Tensor(1.0)) 是相同的,参数默认就是一个标量。

但是由于自己的loss不是一个标量,而是二维的张量,所以就会报错。

解决办法:

1. 给 loss.backward() 指定传递给后向的参数维度:


loss = criterion(pred, targets)
loss.backward()
# 改为:
loss = criterion(pred, targets)
loss.backward(loss.clone().detach())

2. 修改loss函数的输出维度

把张量的输出修改为标量,比如说多多个维度的loss求和或求均值等。此方法对于某些任务不一定适用,可以尝试自己修改。


criterion = nn.L1Loss(reduction='none')
# 把参数去掉,改为:
criterion = nn.L1Loss()

这里顺便介绍一下pytorch loss函数里面 的reduction 参数

在新的pytorch版本里,使用reduction 参数取代了旧版本的size_average和reduce参数。

reduction 参数有三种选择:

'elementwise_mean':为默认情况,表明对N个样本的loss进行求平均之后返回(相当于reduce=True,size_average=True);

'sum':指对n个样本的loss求和(相当于reduce=True,size_average=False);

'none':表示直接返回n分样本的loss(相当于reduce=False)

补充:在Pytorch下,由于反向传播设置错误导致 loss不下降的原因及解决方案

在Pytorch下,由于反向传播设置错误导致 loss不下降的原因及解决方案

刚刚接触深度学习一段时间,一直在研究计算机视觉方面,现在也在尝试实现自己的idea,从中也遇见了一些问题,这次就专门写一下,自己由于在反向传播(backward)过程中参数没有设置好,而导致的loss不下降的原因。

对于多个网络交替

描述

简单描述一下我的网络结构,我的网络是有上下两路,先对第一路网络进行训练,使用groud truth对这一路的结果进行监督loss_steam1,得到训练好的feature.然后再将得到的feature级联到第二路,通过网络得到最后的结果,再用groud truth进行监督loss。

整个网络基于VGG19网络,在pytorch下搭建,有GPU环境:

pytorch loss反向传播出错的解决方案

出现的情况,loss_steam1不怎么下降

这个问题确实折麽自己一段时间,结果发现自己出现了一个问题,下面将对这个问题进行分析和解答:

PyTorch梯度传递

在PyTorch中,传入网络计算的数据类型必须是Variable类型, Variable包装了一个Tensor,并且保存着梯度和创建这个Variablefunction的引用,换句话说,就是记录网络每层的梯度和网络图,可以实现梯度的反向传递.
则根据最后得到的loss可以逐步递归的求其每层的梯度,并实现权重更新。

在实现梯度反向传递时主要需要三步:

1、初始化梯度值:net.zero_grad() 清除网络状态

2、反向求解梯度:loss.backward() 反向传播求梯度

3、更新参数:optimizer.step() 更新参数

解决方案

自己在写代码的时候,还是没有对自己的代码搞明白。在反向求解梯度时,对第一路没有进行反向传播,这样肯定不能使这一路的更新,所以我就又加了一步:

loss_steam1.backward( retain_graph = True) //因为每次运行一次backward时,如果不加retain_graph = True,运行完后,计算图都会free掉。


loss.backward()

这样就够了么?我当时也是这么认为的结果发现loss_steam1还是没有降,又愁了好久,结果发现梯度有了,不更新参数,怎么可能有用!


optimizer_steam1.step() //这项必须加
optimizer.step()

哈哈!这样就完成了,效果也确实比以前好了很多。

以上为个人经验,希望能给大家一个参考,也希望大家多多支持脚本之家。如有错误或未考虑完全的地方,望不吝赐教。

来源:https://blog.csdn.net/u012505617/article/details/107530252

标签:pytorch,loss,反向传播
0
投稿

猜你喜欢

  • po+selenium+unittest自动化测试项目实战

    2022-05-03 14:46:46
  • python flask开发的简单基金查询工具

    2023-10-29 21:35:42
  • 使用vue.js制作分页组件

    2024-05-02 16:36:27
  • python实现读取excel表格详解方法

    2023-03-12 04:48:37
  • 苹果的“创新”

    2010-01-12 13:45:00
  • Python学习笔记之lambda表达式用法详解

    2022-01-28 15:39:37
  • Tag与Tagging

    2009-10-15 12:59:00
  • 成功解决ValueError: Supported target types are:('binary', 'multiclass'). Got 'continuous' instead.

    2023-01-24 03:59:00
  • mysql 之通过配置文件链接数据库

    2024-01-17 13:32:28
  • Django celery异步任务实现代码示例

    2021-12-10 21:38:40
  • 便捷提取python导入包的属性方法

    2022-05-11 05:07:17
  • mac下如何将python2.7改为python3

    2023-12-07 17:14:43
  • SQL server分页的4种方法示例(很全面)

    2024-01-27 15:09:47
  • 解决SQL Server的“此数据库没有有效所有者”问题

    2011-12-14 18:29:35
  • 自适应线性神经网络Adaline的python实现详解

    2023-11-03 03:57:40
  • Django的CVB实例详解

    2023-11-04 06:47:26
  • 详解python中asyncio模块

    2022-06-14 05:25:13
  • 使用Python实现从各个子文件夹中复制指定文件的方法

    2023-11-09 12:04:05
  • JS本地刷新返回上一页代码

    2023-08-06 13:59:57
  • php线性表顺序存储实现代码(增删查改)

    2023-11-19 06:51:53
  • asp之家 网络编程 m.aspxhome.com