【PyTorch】核心库autograd的理解

本文深入探讨PyTorch的autograd模块,介绍其作为define-by-run框架的特点,解析Tensor的requires_grad属性的作用,以及如何利用backward和grad函数进行求导。同时,文章还讨论了在非标量输出情况下求导的特殊处理方法,以及如何在求导过程中排除特定变量。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

1. 简介
autograd能对所有的张量的运算求导。是一种define-by-run的框架,也就是说,返向传播的过程是根据你的code的情况来确定的,每次迭代都可能不同(不太理解)
The autograd package provides automatic differentiation for all operations on Tensors. It is a define-by-run framework, which means that your backprop is defined by how your code is run, and that every single iteration can be different.

 

2. 关于Tensor
Tensor的重要属性

requires_grad: 这个属性决定了这个张量能不能求导, 如果这个属性为True,那接下来和它有关的张量的属性:
grad_fn 的值不为None,这个属性会记录下一个张量是如何由它运算得到的,例如:

a = torch.rand(3, 3, requires_grad=False)
b = a*a
print(b.grad_fn)
a = torch.rand(3, 3, requires_grad=True)
b = a*a
print(b.grad_fn)

两次的输出会不一样:

第一次,a的reqiures_grad为False,也就是说,以后我们不会对它求导,根据链式法则,就没有必要记录它的下家怎么计算的,grad_fn值为None。第二次则相反.
在训练完模型用来test的时候,一般会把参数的requires_grad属性都设为False

 


Tensor无意发现一个很好玩的,你可以任意给它添加属性:例如:

import torch

a = torch.rand(3, 3)
a.mom = "jpzhang"

然后你在它的属性里面可以发现它多了一个属性

 

3. 关于求导
3.1 如何得到导数:

根据前面说的,如果一个Tensor的requires_grad属性为True的话,就可以对它求导,主要通过调用两个函数:backward, grad.例如:

x = torch.ones((2, 2), requires_grad=True)
y = x+2
z = 3*y*y
out = z.mean()
print(out.backward())
print(x.grad)
print(z.backward())
print(x.grad)

得到的答案为4.5,计算过程如下:

需要注意一下的是,必须要先调用out.backward()求出所有的对于out的Tensor的导数(且这个Tensor的requires_grad属性要为True),然后才能通过x.grad()来查看求得的导数是多少,否则x.grad()的输出会是None.

 

3.2 对于输出不是标量的情况:
上面的out因为求了一个均值,输出是标量,所以可以直接调用函数out.backward(),括号里没有其他参数。但如果我们调用函数y.backward(),输出会报错:

需要改成y.backward(tensor.ones(2, 2))或者其他tensor,但shape要和y一样
比如:

import torch

x = torch.ones((2, 2), requires_grad=True)
y = x+2
y.detach()
z = 3*y*y
out = z.mean()
print(z.backward(2*torch.ones(2, 2)))
print(x.grad)
print(y.grad)

 


你会发现求得的导数乘了你在z.backward()函数中给的系数
至于为什么要这么做,不知道。。。。

和求导的机制有关吗?

这是因为在autograd在计算导数的时候是通过就算雅克比矩阵来实现的:

如果。。。

 

 3.3 如果某个变量不要求导:
对于叶子变量,也就是像上面定义的x,可以直接用x.requires_grad = True来设置,但对于非叶子变量,例如上面的y, 要用detach()函数. 
例如:
 

x = torch.ones((2, 2), requires_grad=True)
y = x+2
y.detach()
z = 3*y*y
out = z.mean()
print(out.backward())
print(x.grad)
print(y.grad)


 

### PyTorch Autograd 使用教程和工作原理 #### 一、Autograd简介 PyTorch中的`autograd`包是所有神经网络的核心组件之一,提供了自动求导的功能。这一机制使得开发者可以方便地实现神经网络的反向传播算法,从而简化了模型训练过程[^1]。 #### 二、Tensor与Autograd的关系 在PyTorch中,张量(tensor)不仅能够存储数据,还可以记录对其执行的操作以便后续计算梯度。通过设置`requires_grad=True`属性,可以让某个特定的张量参与到自动微分的过程中去。一旦设置了该标志位,在对该变量进行任何运算之后都会构建起动态图结构,允许系统追踪所有的操作并最终完成链式法则下的偏导数计算[^2]。 #### 三、前向传播与后向传播 对于每一个由用户定义的操作而言,都存在两个重要的阶段——前向传播(`forward`)以及对应的后向传播(`backward`)函数。前者负责接收输入并返回输出;后者则用来根据损失相对于当前节点输出的变化率来计算关于其输入变化率的信息。值得注意的是,在自定义算子时,除了要提供这两个基本组成部分外,还需要利用上下文对象(ctx)保存必要的中间状态供反向传播使用[^4]。 ```python import torch class MyReLU(torch.autograd.Function): @staticmethod def forward(ctx, input): ctx.save_for_backward(input) return input.clamp(min=0) @staticmethod def backward(ctx, grad_output): input, = ctx.saved_tensors grad_input = grad_output.clone() grad_input[input < 0] = 0 return grad_input ``` 上述代码展示了如何创建一个简单的ReLU激活函数,并实现了它的正向传播和反向传播逻辑。这里特别强调了`ctx`的作用:它被用来暂存来自前向路径的数据,这些信息将在稍后的梯度计算过程中发挥作用。 #### 四、实际应用案例 为了更好地理解autograd的工作流程,下面给出一段完整的例子: ```python x = torch.ones(2, 2, requires_grad=True) y = x + 2 z = y * y * 3 out = z.mean() print('Gradient function for z:', z.grad_fn) print('Gradient function for out:', out.grad_fn) out.backward() # 反向传播误差 print(x.grad) # 查看x的梯度 ``` 此段程序首先初始化了一个带有`requires_grad=True`标记的二维单位矩阵作为起点,接着依次进行了加法、乘方及平均化等一系列变换直至得到最终的目标值。最后一步调用了`.backward()`方法触发整个图形上的逆序遍历,完成了从末端到始端逐层累积梯度的过程[^3]。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值