torch中关于张量是否是叶子结点,张量梯度是否会被计算,张量梯度是否会被保存的感悟

先上结论:

1、叶子结点定义:

(1)不依赖其它任何结点的张量

(2)依赖其它张量,但其依赖的所有张量的require_grad=False

判断方法:查看is_leaf属性

2、张量梯度是否会被计算:

require_grad=True,且依赖其的张量不全为require_grad=False,该张量梯度会被计算

判断方法:backward之后查看张量的.grad属性(中间变量满足上述要求的梯度肯定也会被计算,只是backward之后会被释放掉,无法查看。中间变量其下面的叶子结点梯度被计算,根据链式法则,侧面也可证明中间变量的梯度肯定被计算了,因此本文只采用叶子结点说明该规律)

3、张量梯度是否会被保存(前提: 张量梯度可以被计算):

(1)是叶子结点

(2)是非叶子结点,但retain_grad=True

判断方法: backward之后查看张量的.grad属性

然后看例子:

两个例子先证明第一条:叶子结点定义

python 复制代码
import torch

# 两个例子先证明第一条:叶子结点定义
a = torch.tensor(1.,requires_grad=True)
b = torch.tensor(1.,requires_grad=False)
d = a+b
d.backward()

print(a.is_leaf) # True  (不依赖其它任何张量的结点)
print(b.is_leaf) # True  (不依赖其它任何张量的结点)
print(d.is_leaf) # False (依赖其它张量a和b,但张量a的require_grad=True,所以d不是叶子结点)


c = torch.tensor(1., requires_grad=False)
e = b+c

print(b.is_leaf)    # True  (不依赖其它任何张量的结点)
print(c.is_leaf)    # True  (不依赖其它任何张量的结点)
print(e.is_leaf)    # True (依赖其它张量b和c,但张量a和c的require_grad=False,所以e仍然是叶子结点)
# e.backward()会报错,因为所有结点的require_grad=False,因此不需要求梯度

两个例子再证明第二条:张量梯度是否会被计算

python 复制代码
import torch

# 两个例子再证明第二条:张量梯度是否会被计算
# require_grad=True的张量,且依赖其的张量不全为require_grad=False梯度会被计算
a = torch.tensor(1.,requires_grad=True)   # a require_grad=True,因此a的梯度会被计算
b = torch.tensor(1.,requires_grad=False)  # b require_grad=False,因此b的梯度不会被计算
d = a+b                                   # d require_grad=True,因此d的梯度会被计算
c = torch.tensor(1., requires_grad=True)  # c require_grad=True,因此c的梯度会被计算
e = a+c                                   # e require_grad=True,因此e的梯度会被计算
d = d.detach()
print(d.requires_grad)                    # d require_grad=False,因此d的梯度不会被计算

f = d+e 
f.backward()
print(a.grad)                             # a有梯度

# require_grad=True的张量,但依赖其的张量全为require_grad=False,梯度不会被计算
a = torch.tensor(1.,requires_grad=True)   # a require_grad=True, 因此a的梯度会被计算
b = torch.tensor(1.,requires_grad=False)  # b require_grad=False, 因此b的梯度不会被计算
d = a+b                                   # d require_grad=True, 因此d的梯度会被计算
c = torch.tensor(1., requires_grad=True)  # c require_grad=True,因此c的梯度会被计算
d = d.detach()                            # d require_grad=False, 因此d的梯度不会被计算
f = d+c                                   # f require_grad=True,因此f的梯度会被计算
f.backward()
print(a.grad)                             # a没有梯度

再证明第三条: 张量梯度是否会被保存,前提是张量的梯度能被计算(既满足第二条)

python 复制代码
import torch

# 再证明第三条: 张量梯度是否会被保存,前提是张量的梯度能被计算(既满足第二条)
# (1)叶子结点的梯度会被保存
a = torch.tensor(1.,requires_grad=True)     # a的require_grad= True,且a是一个叶子结点(a.is_leaf=True),所以backward之后a的梯度会被保存。(满足条件3)
b = torch.tensor(1.,requires_grad=False)    # b是一个叶子结点(b.is_leaf=True),但b的require_grad= False,所以backward之后b的梯度不会被保存.(不满足条件3)
d = a+b                                     # d的require_grad= True, 但d不是一个叶子结点,所以backward之后b的梯度不会被保存。(不满足条件3)
d.backward()
print(a.is_leaf)
print(a.grad)                               # a的梯度被保存


# 感悟: 神经网络各层里面的参数require_grad=True(属于Parameter类型,其初始化的时候默认require_grad=True),并且如果上层不会被断开(满足梯度可以被计算条件)。且神经网络里面各层的参数都是叶子结点(从计算图可以得知满足1里面第一条),因此满足梯度保存条件第一条。因此其梯度一定会被保存。满足了以上两条,因此backward的时候其梯度一定会被计算并且保存,从而step的时候才能用于梯度更新)

# (2)非叶子结点,但retain_grad=True的张量梯度也会被保存。
a = torch.tensor(1.,requires_grad=True)     # a的require_grad= True,且a是一个叶子结点(a.is_leaf=True),所以backward之后a的梯度会被保存。(满足条件3)
b = torch.tensor(1.,requires_grad=False)    # b是一个叶子结点(b.is_leaf=True),但b的require_grad= False,所以backward之后b的梯度不会被保存.(不满足条件3)
d = a+b                                     # d的require_grad= True, 但d不是一个叶子结点,所以backward之后b的梯度不会被保存。(不满足条件3)
print(d.is_leaf)                            # False
d.retain_grad()                             # retain_grad=True
d.backward()
print(d.is_leaf)                            # False
print(d.grad)                               # d的梯度被保存
相关推荐
艾醒(AiXing-w)8 分钟前
探索大语言模型(LLM):Ollama快速安装部署及使用(含Linux环境下离线安装)
linux·人工智能·语言模型
mark-puls9 分钟前
C语言打印爱心
c语言·开发语言·算法
月小水长11 分钟前
大模型接入自定义 MCP Server,我开发了个免费使用的基金涨跌归纳和归因分析的 Agent
人工智能·后端
Python技术极客12 分钟前
将 Python 应用打包成 exe 软件,仅需一行代码搞定!
算法
睡不醒的kun24 分钟前
leetcode算法刷题的第三十四天
数据结构·c++·算法·leetcode·职场和发展·贪心算法·动态规划
吃着火锅x唱着歌27 分钟前
LeetCode 978.最长湍流子数组
数据结构·算法·leetcode
咏方舟【长江支流】31 分钟前
AI+华为HarmonyOS开发工具DevEco Studio详细安装指南
人工智能·华为·移动开发·harmonyos·arkts·deveco studio·长江支流
阿里云云原生1 小时前
Qoder 全新「上下文压缩」功能正式上线,省 Credits !
人工智能
我星期八休息1 小时前
深入理解跳表(Skip List):原理、实现与应用
开发语言·数据结构·人工智能·python·算法·list
lingran__1 小时前
速通ACM省铜第四天 赋源码(G-C-D, Unlucky!)
c++·算法