Autograd 自动微分

  深度学习的算法本质上是通过反向传播求导数,Pytorch的Autograd模块实现了此功能。在tensor上的所有操作,Autograd 都能自动求微分,避免了手动计算微分的过程。
  其中,autograd.Variable.是Autograd中核心的类,它简单的封装了Tensor,支持所有tensor的操作。
  tensor在被封装为Variable后,可以调用它的**.backward**实现反向传播,自动计算所有的梯度。Variable的数据结构如下图:

Variable主要包含三个属性:
1  data:保存Varible所包含的tensor
2 grad:保存data对应的梯度,注意,它这里也是一个Variable,而不是个tensor,与data形状一样。
3 gran_fn:指向一个Function对象,用来反向传播计算输入的梯度。
例子如下:
输入一个全为1的3*3的矩阵,为Variable类

import torch
from torch.autograd import Variable
a=torch.ones(3,3)
x =  Variable(a,requires_grad = True)
print(x)

注意这里requires_grad=True表示该变量在自动计算梯度时会保留梯度值,为False则相反。默认为False
输出结果:

tensor([[1., 1., 1.],
        [1., 1., 1.],
        [1., 1., 1.]], requires_grad=True)
        

Varible几乎支持tensor的所有操作,如下:

y=x.sum()
print(y)

输出结果

tensor(9., grad_fn=<SumBackward0>)

查看x和y的grad_fn

print(x.grad_fn)
print(y.grad_fn)

输出结果:

None
<SumBackward0 object at 0x000002289C55CBA8>

可以看到,y是作为x的运算结果产生的,所以y有grad_fn。而x是直接创建的,所以没有

2.关于backward,反向计算导数

backward只能对一个标量求导或者 传入跟变量相关的梯度。

如果Variable是一个标量,无需对backward()指定任何参数,如下:
先看这个:
在这里插入图片描述

import torch
from torch.autograd import Variable
x = Variable(torch.ones(2, 2), requires_grad=True)
y = x + 2
z = y * y * 3
p = z.mean()
p.backward()
print(x.grad)

输出结果

tensor([[4.5000, 4.5000],
        [4.5000, 4.5000]])

但如果Varieble是一个向量,就需要指定一个和Variable中tensor的形状匹配的grad_output参数
如下:
这里,y.backward(weight1),weight1是对求导变量的一个权重,当y为标量的时候,该参数默认为1,就可以跟我们理解的一样,求y对x的导数。至于为什么有这个,参考知乎上的一文:PyTorch 的 backward 为什么有一个 grad_variables 参数?

import torch
from torch.autograd import Variable

x = Variable(torch.Tensor([1, 2, 3, 4, 5]), requires_grad=True)  # 需要求导数
y = x * x

weights1 = torch.Tensor([5, 5, 5, 5, 5])
y.backward(weights1, retain_graph=True)
print(x.grad)

输出结果:

tensor([10., 20., 30., 40., 50.])

backward函数中还有retain_graph参数,使用这个参数时,再次求导的时候,会对之前的导数进行累加,所以每次反向传播前需要把梯度清零,如下,这在神经网络代码中会用到。
如下图:

import torch
from torch.autograd import Variable

x = Variable(torch.Tensor([1, 2, 3, 4, 5]), requires_grad=True)  # 需要求导数
y = x * x

weights1 = torch.Tensor([5, 5, 5, 5, 5])
y.backward(weights1, retain_graph=True)
print(x.grad)

weights1 = torch.Tensor([5, 5, 5, 5, 5])
y.backward(weights1, retain_graph=True)
print(x.grad)

x.grad.data.zero_()#     清零

weights1 = torch.Tensor([5, 5, 5, 5, 5])
y.backward(weights1, retain_graph=True)
print(x.grad)

#输出结果
# tensor([10., 20., 30., 40., 50.])
# tensor([ 20.,  40.,  60.,  80., 100.])
# tensor([10., 20., 30., 40., 50.])

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

通信仿真爱好者

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值