08_14_自动求导

自动求导

一、什么是梯度?
在深度学习中,梯度可以看作是一个指引我们如何调整模型参数(如权重和偏置)以最小化误差的指南针。梯度告诉我们,在当前参数值的情况下,误差朝哪个方向增大或减小,以及应该调整参数多少。

想象你在爬一座大山,你的目标是找到山的最低点(误差最小的地方)。你戴着眼罩,所以看不到周围的环境。你只能通过脚下的感觉来判断是否在下坡。

山顶:你现在所在的位置,误差比较大。
山谷:你要去的地方,误差最小。
梯度:地面的斜度和方向,告诉你应该朝哪个方向走,才能更快地到达山谷。
每次你感受到脚下的斜度(计算梯度),你就根据这个斜度调整方向,朝着下坡的方向走一步(更新模型参数)。不断重复这个过程,直到你感觉走到了最低点。

二、梯度计算
在深度学习中,我们通常使用反向传播算法来计算梯度。反向传播通过链式法则,从输出层开始,逐层向回计算每个参数对误差的影响。

Pytorch提供了autograd包来自动根据输入和前向传播构建计算图,其中backward()函数可以轻易地计算出梯度。

import torch
 
x=torch.tensor([1,2,3],requires_grad=True,dtype=torch.double)
y=x**2
z=y.mean()
z.backward()
print(x.grad)
  • 结果:tensor([0.6667, 1.3333, 2.0000], dtype=torch.float64)

具体求解过程如下:
在这里插入图片描述
z是一个标量(1*1矩阵)分别对x1,x2,x3求偏导, 再代入x1,x2,x3的数值,就是如上程序输出的结果

Tensor在Pytorch中用来表示张量,如果我们想使用autograd包让他们参与梯度计算,则需要在创建他们的时候,将.require_grad属性指定为True。

  • 在Pytorch中,只有浮点类型的数才有梯度,因此在定义张量是一定要将类型指定为float型。
  • 对于没有指定.require_grad,也可在后续的计算过程中指定,或者使用.requires_grad_(True)指定。

三、解释各属性的含义
1、data:存储的Tensor的值
2、require_grad: 该节点是否参与反向传播的计算,如果为True,则参与计算;如果为False则不参与。
3、grad:存储梯度值。require_grad为False时,属性为None;require_grad为True且在调用过其他节点的backward后,grad保存对这个节点的梯度值,否则为None
4、grad_fn:表示用于计算梯度的函数,即创建该Tensor的Function。如果该Tensor不是通过计算得到的,则grad_fn为None;如果是通过计算得到的,则返回该运算相关的对象。

代码

import torch

x = torch.arange(4,dtype = torch.float32)#生成一个张量
x
tensor([0., 1., 2., 3.])

在计算y关于x的梯度之前,需要有一个地方存储梯度

x.requires_grad_(True) #等价于x = torch.arange(4.0,requires_grad=True)
x.grad #默认值是None
y = 2 * torch.dot(x,x) #等价于y = 2x^2,将x的值带入后求内积
y
tensor(28., grad_fn=<MulBackward0>)

调用反向传播函数来自动计算y关于x每个梯度的分量

y.backward()
x.grad
tensor([ 0.,  4.,  8., 12.])
x.grad == 4 * x
tensor([True, True, True, True])
x
tensor([0., 1., 2., 3.], requires_grad=True)
#默认情况下,pytorch会积累梯度,我们需要清除之前的值
x.grad.zero_()#梯度清零
y = x.sum()
y.backward()
x.grad
tensor([1., 1., 1., 1.])

在深度学习当中,我们的目的不是计算微分矩阵,而是批量中每个样本单独计算的偏导数之和。

#对非标量调用'backward'需要传入一个'gradient'参数,该参数指定微分
x.grad.zero_()
y = x * x#此时y为非标量
#等价于y.backward(torch.ones(len(x)))
y.sum().backward()
x.grad
tensor([0., 2., 4., 6.])

将某些计算移动到记录的计算图之外

x.grad.zero_()
y = x * x
u = y.detach()
#.detach()方法用于从计算图中分离一个张量,这意味着它创建了一个新的张量,与原始张量共享数据,但不再参与任何计算图。这意味着这个新的张量不依赖于过去的计算值。
#此时的u与x已经没有任何关系
z = u * x

z.sum().backward()
x.grad == u
tensor([True, True, True, True])
x.grad.zero_()
y.sum().backward()
x.grad == 2 * x
tensor([True, True, True, True])
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()

a.grad == d / a
tensor(True)
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值