首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >当使用.clamp而不是torch.relu时,给出了不同的梯度

当使用.clamp而不是torch.relu时,给出了不同的梯度
EN

Stack Overflow用户
提问于 2020-03-10 13:10:05
回答 1查看 3.3K关注 0票数 8

我仍然在研究我对PyTorch自动梯度系统的理解。我正在努力的一件事是理解为什么.clamp(min=0)nn.functional.relu()似乎有不同的反向传球。

它特别令人困惑,因为.clamp在PyTorch教程(如https://pytorch.org/tutorials/beginner/pytorch_with_examples.html#pytorch-nn )中的使用与relu相当。

我在分析具有一个隐藏层和relu激活(输出层线性)的简单全连通网络的梯度时发现了这一点。

据我所知,以下代码的输出应该是零。我希望有人能告诉我我错过了什么。

代码语言:javascript
复制
import torch
dtype = torch.float

x = torch.tensor([[3,2,1],
                  [1,0,2],
                  [4,1,2],
                  [0,0,1]], dtype=dtype)

y = torch.ones(4,4)

w1_a = torch.tensor([[1,2],
                     [0,1],
                     [4,0]], dtype=dtype, requires_grad=True)
w1_b = w1_a.clone().detach()
w1_b.requires_grad = True



w2_a = torch.tensor([[-1, 1],
                     [-2, 3]], dtype=dtype, requires_grad=True)
w2_b = w2_a.clone().detach()
w2_b.requires_grad = True


y_hat_a = torch.nn.functional.relu(x.mm(w1_a)).mm(w2_a)
y_a = torch.ones_like(y_hat_a)
y_hat_b = x.mm(w1_b).clamp(min=0).mm(w2_b)
y_b = torch.ones_like(y_hat_b)

loss_a = (y_hat_a - y_a).pow(2).sum()
loss_b = (y_hat_b - y_b).pow(2).sum()

loss_a.backward()
loss_b.backward()

print(w1_a.grad - w1_b.grad)
print(w2_a.grad - w2_b.grad)

# OUT:
# tensor([[  0.,   0.],
#         [  0.,   0.],
#         [  0., -38.]])
# tensor([[0., 0.],
#         [0., 0.]])
# 
EN

Stack Overflow用户

回答已采纳

发布于 2020-08-14 00:32:26

原因是clamprelu0上产生不同的梯度。用标量张量x = 0检查两个版本:(x.clamp(min=0) - 1.0).pow(2).backward()(relu(x) - 1.0).pow(2).backward()。生成的x.grad对于relu版本是0,而对于clamp版本则是-2。这意味着relu选择x == 0 --> grad = 0,而clamp选择x == 0 --> grad = 1

票数 4
EN
查看全部 1 条回答
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/60618346

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档