从零开始机器学习(二)

跟着李沐学AI【07 自动求导】

记录和处理在跟着学习时产生的问题,难点有些多,需要好好消化。

自动求导的实现:

一、 函数y = 2*(xTx)

(1)设置一个列向量x,并对其求导
import torch

x = torch.arange(4.0)
x.requires_grad_(True) #另外需要一个地方来存储梯度
x.grad #默认值是None

显示出x张量如下所示:

(2)计算y = 2*torch.dot(x,x) 即2*x向量的内积
y = 2*torch.dot(x,x)

结果如图:

需要注意的是,此处应该修改一下代码,在后面加上‘.data’保留源数据,否则后期调用反向传播函数计算x分量的梯度时会报错!

改后如下所示:

y = 2*torch.dot(x,x).data
(3)通过调用反向传播函数来自动计算y关于x每个分量的梯度
y.backward() #调用反向传播函数,求导
x.grad #访问导数

结果如下:

y = 2*( xT x ) = 2* || x ||^2 ,当对x求偏导时便等于2* 2* x  = 4* x。

因此,当验证 x.grad == 4*x 时结果为True

 二、 另一些函数

(1)默认情况下pytorch会累积梯度,需要清除之前的值
x.grad.zero_() #将梯度清零
y = x.sum() # y = x1+x2+...+xn
y.backward() # y分别对x1、x2...xn分量求偏导,得到的结果为全1,并存入x.grad中
x.grad

x的梯度清零后,再对求和函数求偏导,结果为全1:

(2)求批量中每个样本单独计算的偏导数之和
x.grad.zero_() # 对x的梯度清零
y = x * x
y.sum().backward() #等价于y.backward(torch.ones(len(x)))
x.grad

先计算了y.sum()得到一个标量,然后再调用反向传播函数,得到x的梯度为

(3)将某些计算移动到记录的计算图之外
x.grad.zero_ #梯度清零
y = x * x
u = y.detach() #将y看做一个常数赋值于u
z = u * x #z相对于常数u乘x

z.sum().backward()
x.grad == u #z对x求偏导后得常数u

y是关于x 的函数,而u不是,它是常数。故z = u * x视为常数与变量x相乘,最后对x求偏导的值为常数u:

(4)可以计算得到的变量的梯度
#使用很复杂的python控制流,依然能求导
def f(a):  #f(a)是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) #给a的梯度分配存储空间
d = f(a)
d.backward() # d对a求偏导

a.grad == d/a

判断a的梯度是否等于函数f(a) / a :

完结撒花!❀

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

玲ling_

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

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

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

打赏作者

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

抵扣说明:

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

余额充值