- ubuntu12.04环境下使用kvm ioctl接口实现最简单的虚拟机
- Ubuntu 通过无线网络安装Ubuntu Server启动系统后连接无线网络的方法
- 在Ubuntu上搭建网桥的方法
- ubuntu 虚拟机上网方式及相关配置详解
CFSDN坚持开源创造价值,我们致力于搭建一个资源共享平台,让每一个IT人在这里找到属于你的精彩世界.
这篇CFSDN的博客文章Pytorch中的backward()多个loss函数用法由作者收集整理,如果你对这篇文章有兴趣,记得点赞哟.
假若有多个loss函数,如何进行反向传播和更新呢?
1
2
3
4
5
6
7
8
9
10
|
x
=
torch.tensor(
2.0
, requires_grad
=
True
)
y
=
x
*
*
2
z
=
x
# 反向传播
y.backward()
x.grad
tensor(
4.
)
z.backward()
x.grad
tensor(
5.
)
## 累加
|
补充:Pytorch中torch.autograd ---backward函数的使用方法详细解析,具体例子分析 。
官方定义:
torch.autograd.backward(tensors, grad_tensors=None, retain_graph=None, create_graph=False, grad_variables=None) 。
Computes the sum of gradients of given tensors w.r.t. graph leaves.The graph is differentiated using the chain rule. If any of tensors are non-scalar (i.e. their data has more than one element) and require gradient, the function additionally requires specifying grad_tensors. It should be a sequence of matching length, that contains gradient of the differentiated function w.r.t. corresponding tensors (None is an acceptable value for all tensors that don't need gradient tensors). This function accumulates gradients in the leaves - you might need to zero them before calling it. 。
翻译和解释:
参数tensors如果是标量,函数backward计算参数tensors对于给定图叶子节点的梯度( graph leaves,即为设置requires_grad=True的变量).
参数tensors如果不是标量,需要另外指定参数grad_tensors,参数grad_tensors必须和参数tensors的长度相同。在这一种情况下,backward实际上实现的是代价函数(loss = torch.sum(tensors*grad_tensors); 注:torch中向量*向量实际上是点积,因此tensors和grad_tensors的维度必须一致 )关于叶子节点的梯度计算,而不是参数tensors对于给定图叶子节点的梯度。如果指定参数grad_tensors=torch.ones((size(tensors))),显而易见,代价函数关于叶子节点的梯度,也就等于参数tensors对于给定图叶子节点的梯度.
每次backward之前,需要注意叶子梯度节点是否清零,如果没有清零,第二次backward会累计上一次的梯度.
1
2
3
4
5
6
|
import
torch
x
=
torch.randn((
3
),dtype
=
torch.float32,requires_grad
=
True
)
y
=
torch.randn((
3
),dtype
=
torch.float32,requires_grad
=
True
)
z
=
torch.randn((
3
),dtype
=
torch.float32,requires_grad
=
True
)
t
=
x
+
y
loss
=
t.dot(z)
#求向量的内积
|
在调用 backward 之前,可以先手动求一下导数,应该是:
用代码实现求导:
1
2
3
4
|
loss.backward(retain_graph
=
True
)
print
(z,x.grad,y.grad)
#预期打印出的结果都一样
print
(t,z.grad)
#预期打印出的结果都一样
print
(t.grad)
#在这个例子中,x,y,z就是叶子节点,而t不是,t的导数在backward的过程中求出来回传之后就会被释放,因而预期结果是None
|
结果和预期一致:
tensor([-2.6752, 0.2306, -0.8356], requires_grad=True) tensor([-2.6752, 0.2306, -0.8356]) tensor([-2.6752, 0.2306, -0.8356]) 。
tensor([-1.1916, -0.0156, 0.8952], grad_fn=<AddBackward0>) tensor([-1.1916, -0.0156, 0.8952]) None 。
敲重点:
注意到前面函数的解释中,在参数tensors不是标量的情况下,tensor.backward(grad_tensors)实现的是代价函数(torch.sum(tensors*grad_tensors))关于叶子节点的导数.
在上面例子中,loss = t.dot(z),因此用t.backward(z),实现的就是loss对于所有叶子结点的求导,实际运算结果和预期吻合.
1
2
3
|
t.backward(z,retain_graph
=
True
)
print
(z,x.grad,y.grad)
print
(t,z.grad)
|
运行结果如下:
tensor([-0.7830, 1.4468, 1.2440], requires_grad=True) tensor([-0.7830, 1.4468, 1.2440]) tensor([-0.7830, 1.4468, 1.2440]) 。
tensor([-0.7145, -0.7598, 2.0756], grad_fn=<AddBackward0>) None 。
上面的结果中,出现了一个问题,虽然loss关于x和y的导数正确,但是z不再是叶子节点了.
问题1:
当使用t.backward(z,retain_graph=True)的时候, print(z.grad)结果是None,这意味着z不再是叶子节点,这是为什么呢?
另外一个尝试,loss = t.dot(z)=z.dot(t),但是如果用z.backward(t)替换t.backward(z,retain_graph=True),结果却不同.
1
2
3
|
z.backward(t)
print
(z,x.grad,y.grad)
print
(t,z.grad)
|
运行结果:
tensor([-1.0716, -1.3643, -0.0016], requires_grad=True) None None 。
tensor([-0.7324, 0.9763, -0.4036], grad_fn=<AddBackward0>) tensor([-0.7324, 0.9763, -0.4036]) 。
问题2:
上面的结果中可以看到,使用z.backward(t),x和y都不再是叶子节点了,z仍然是叶子节点,且得到的loss相对于z的导数正确.
上述仿真出现的两个问题,我还不能解释,希望和大家交流.
问题1:
当使用t.backward(z,retain_graph=True)的时候, print(z.grad)结果是None,这意味着z不再是叶子节点,这是为什么呢?
问题2:
上面的结果中可以看到,使用z.backward(t),x和y都不再是叶子节点了,z仍然是叶子节点,且得到的loss相对于z的导数正确.
另外强调一下,每次backward之前,需要注意叶子梯度节点是否清零,如果没有清零,第二次backward会累计上一次的梯度.
1
2
3
4
5
6
7
8
9
|
#测试1,:对比上两次单独执行backward,此处连续执行两次backward
t.backward(z,retain_graph
=
True
)
print
(z,x.grad,y.grad)
print
(t,z.grad)
z.backward(t)
print
(z,x.grad,y.grad)
print
(t,z.grad)
# 结果x.grad,y.grad本应该是None,因为保留了第一次backward的结果而打印出上一次梯度的结果
tensor([
-
0.5590
,
-
1.4094
,
-
1.5367
], requires_grad
=
True
) tensor([
-
0.5590
,
-
1.4094
,
-
1.5367
]) tensor([
-
0.5590
,
-
1.4094
,
-
1.5367
])tensor([
-
1.7914
,
0.8761
,
-
0.3462
], grad_fn
=
<AddBackward0>) Nonetensor([
-
0.5590
,
-
1.4094
,
-
1.5367
], requires_grad
=
True
) tensor([
-
0.5590
,
-
1.4094
,
-
1.5367
]) tensor([
-
0.5590
,
-
1.4094
,
-
1.5367
])tensor([
-
1.7914
,
0.8761
,
-
0.3462
], grad_fn
=
<AddBackward0>) tensor([
-
1.7914
,
0.8761
,
-
0.3462
])
|
1
2
3
4
5
6
7
8
9
10
|
#测试2,:连续执行两次backward,并且清零,可以验证第二次backward没有计算x和y的梯度
t.backward(z,retain_graph
=
True
)
print
(z,x.grad,y.grad)
print
(t,z.grad)
x.grad.data.zero_()
y.grad.data.zero_()
z.backward(t)
print
(z,x.grad,y.grad)
print
(t,z.grad)
tensor([
0.8671
,
0.6503
,
-
1.6643
], requires_grad
=
True
) tensor([
0.8671
,
0.6503
,
-
1.6643
]) tensor([
0.8671
,
0.6503
,
-
1.6643
])tensor([
1.6231e
+
00
,
1.3842e
+
00
,
4.6492e
-
06
], grad_fn
=
<AddBackward0>) Nonetensor([
0.8671
,
0.6503
,
-
1.6643
], requires_grad
=
True
) tensor([
0.
,
0.
,
0.
]) tensor([
0.
,
0.
,
0.
])tensor([
1.6231e
+
00
,
1.3842e
+
00
,
4.6492e
-
06
], grad_fn
=
<AddBackward0>) tensor([
1.6231e
+
00
,
1.3842e
+
00
,
4.6492e
-
06
])
|
以上为个人经验,希望能给大家一个参考,也希望大家多多支持我.
原文链接:https://blog.csdn.net/haoxue2011/article/details/102540945 。
最后此篇关于Pytorch中的backward()多个loss函数用法的文章就讲到这里了,如果你想了解更多关于Pytorch中的backward()多个loss函数用法的内容请搜索CFSDN的文章或继续浏览相关文章,希望大家以后支持我的博客! 。
已关闭。此问题不符合Stack Overflow guidelines 。目前不接受答案。 这个问题似乎与 help center 中定义的范围内的编程无关。 . 已关闭 3 年前。 此帖子于去年编辑
据我所知,在使用 GPU 训练和验证模型时,GPU 内存主要用于加载数据,向前和向后。据我所知,我认为 GPU 内存使用应该相同 1) 训练前,2) 训练后,3) 验证前,4) 验证后。但在我的例子中
我正在尝试在 PyTorch 中将两个复数矩阵相乘,看起来 the torch.matmul functions is not added yet to PyTorch library for com
我正在尝试定义二分类问题的损失函数。但是,目标标签不是硬标签0,1,而是0~1之间的一个 float 。 Pytorch 中的 torch.nn.CrossEntropy 不支持软标签,所以我想自己写
我正在尝试让 PyTorch 与 DataLoader 一起工作,据说这是处理小批量的最简单方法,在某些情况下这是获得最佳性能所必需的。 DataLoader 需要一个数据集作为输入。 大多数关于 D
Pytorch Dataloader 的迭代顺序是否保证相同(在温和条件下)? 例如: dataloader = DataLoader(my_dataset, batch_size=4,
PyTorch 的负对数似然损失,nn.NLLLoss定义为: 因此,如果以单批处理的标准重量计算损失,则损失的公式始终为: -1 * (prediction of model for correct
在PyTorch中,new_ones()与ones()有什么区别。例如, x2.new_ones(3,2, dtype=torch.double) 与 torch.ones(3,2, dtype=to
假设我有一个矩阵 src带形状(5, 3)和一个 bool 矩阵 adj带形状(5, 5)如下, src = tensor([[ 0, 1, 2], [ 3, 4,
我想知道如果不在第 4 行中使用“for”循环,下面的代码是否有更有效的替代方案? import torch n, d = 37700, 7842 k = 4 sample = torch.cat([
我有三个简单的问题。 如果我的自定义损失函数不可微会发生什么? pytorch 会通过错误还是做其他事情? 如果我在我的自定义函数中声明了一个损失变量来表示模型的最终损失,我应该放 requires_
我想知道 PyTorch Parameter 和 Tensor 的区别? 现有answer适用于使用变量的旧 PyTorch? 最佳答案 这就是 Parameter 的全部想法。类(附加)在单个图像中
给定以下张量(这是网络的结果 [注意 grad_fn]): tensor([121., 241., 125., 1., 108., 238., 125., 121., 13., 117., 12
什么是__constants__在 pytorch class Linear(Module):定义于 https://pytorch.org/docs/stable/_modules/torch/nn
我在哪里可以找到pytorch函数conv2d的源代码? 它应该在 torch.nn.functional 中,但我只找到了 _add_docstr 行, 如果我搜索conv2d。我在这里看了: ht
如 documentation 中所述在 PyTorch 中,Conv2d 层使用默认膨胀为 1。这是否意味着如果我想创建一个简单的 conv2d 层,我必须编写 nn.conv2d(in_chann
我阅读了 Pytorch 的源代码,发现它没有实现 convolution_backward 很奇怪。函数,唯一的 convolution_backward_overrideable 函数是直接引发错
我对编码真的很陌生,现在我正在尝试将我的标签变成一种热门编码。我已经完成将 np.array 传输到张量,如下所示 tensor([4., 4., 4., 4., 4., 4., 4., 4., 4.
我正在尝试实现 text classification model使用CNN。据我所知,对于文本数据,我们应该使用一维卷积。我在 pytorch 中看到了一个使用 Conv2d 的示例,但我想知道如何
我有一个多标签分类问题,我正试图用 Pytorch 中的 CNN 解决这个问题。我有 80,000 个训练示例和 7900 个类;每个示例可以同时属于多个类,每个示例的平均类数为 130。 问题是我的
我是一名优秀的程序员,十分优秀!