pytorch深度学习实战lesson8

第八课 自动求导

理论部分

求导主要是有两种方式,第一种是符号求导,第二种是数值求导。

自动求导的内部其实是计算图,计算图是将代码分解成操作子,将计算表示成一个无环图。

计算图的显式构造:(mxnet)

计算图的隐式构造:(mxnet)

反向累计是比较常用的。

总结:

构造计算图

前向:执行图,存储中间结果(设置中间变量)

反向:从相反的方向执行图

去除不需要的枝

深度学习耗GPU资源体现在内存复杂度上面。因为求梯度时需要存储前面的结果。

实践部分

#自动求导
import torch
x=torch.arange(4.0)               #requires_grad=True'''
                                  #x=tensor([0., 1., 2., 3.])
x.requires_grad = True            #计算y关于x的梯度之前需要存储梯度,等价于上句话的最后一个参数.
#print(x.grad)                    #x.grad 默认值是none
########################################################################################
#计算y
y = 2 * torch.dot(x,x)            #结果是个标量
print('###################################################')
print('torch.dot(x,x):\t',torch.dot(x,x))
print('y:\t',y)
y.backward()                      #通过反向传播函数自动计算y关于x每个分量的梯度
print('x.grad:\t',x.grad)
print('x.grad==4*x?\t',x.grad==4*x)
print('###################################################')
#在默认情况下,torch会累积梯度,所以需要对之前的值进行清零
########################################################################################
x.grad.zero_()                    #下划线是指进行重写操作,也就是对x的梯度进行重写为0
#print('x.grad:\t',x.grad)
y=x.sum()                         #结果是个标量
#print(y)
y.backward()
print('x.grad:\t',x.grad)         #如果把16行注释,则结果是x.grad:tensor([ 1.,  5.,  9., 13.])
                                  #求和,梯度是1
print('###################################################')
########################################################################################
#在深度学习中,我们的目的不是计算微分矩阵,而是批量中每个样本单独计算的偏导数之和
x.grad.zero_()
y=x*x                             #结果是个向量
y.sum().backward()                #向量的求导转换成对标量求导(先求和再求导)
print('x.grad:\t',x.grad)
print('###################################################')
########################################################################################
#将某些计算移动到记录的计算图之外,用于固定某些网络参数
x.grad.zero_()
y=x*x                             #结果是个向量
u=y.detach()                      #把u做成常数,而非关于y的函数
z=u*x                             #结果是个向量
z.sum().backward()                #向量的求导转换成对标量求导(先求和再求导)
print('x.grad==u:\t',x.grad==u)
x.grad.zero_()
y.sum().backward()
print('x.grad==2*x?\t',x.grad==2*x)
print('###################################################')
########################################################################################
#即使构建函数的计算图需要通过Python控制流(例如条件、循环或任意函数调用),我们仍然可以计算得到的变量的梯度
def f(a):
    b = a * 2
    while b.norm() < 1000:
        b = b * 2
    if b.sum() > 0:
        c = b
    else:
        c = 100 * b
    return c

a = torch.randn(size=(),requires_grad=True)
d = f(a)
d.backward()
print('a.grad==d/a\t',a.grad==d/a)
print('###################################################')

###################################################
torch.dot(x,x):     tensor(14., grad_fn=<DotBackward0>)
y:     tensor(28., grad_fn=<MulBackward0>)
x.grad:     tensor([ 0.,  4.,  8., 12.])
x.grad==4*x?     tensor([True, True, True, True])
###################################################
x.grad:     tensor([1., 1., 1., 1.])
###################################################
x.grad:     tensor([0., 2., 4., 6.])
###################################################
x.grad==u:     tensor([True, True, True, True])
x.grad==2*x?     tensor([True, True, True, True])
###################################################
a.grad==d/a     tensor(True)
###################################################

进程已结束,退出代码0

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

wo~he!

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

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

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

打赏作者

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

抵扣说明:

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

余额充值