聊一聊梯度计算中很重要的Dynamic Gragh

本文介绍了PyTorch中动态计算图的工作原理,包括张量的属性如data、dtype、shape、device等,以及如何在动态图中创建可微分张量,进行梯度计算和反向传播的过程。特别强调了动态图的特性、梯度累计和保留中间节点梯度的方法。
摘要由CSDN通过智能技术生成

前言:最近越看代码越觉得自己要补的东西很多很多,我觉得了解pytorch框架中的梯度计算过程其实还是很重要的,于是打算码一篇关于动态计算图的文章。

首先明确一点:pytorch使用的是动态计算图,也就是计算图的创建过程是随着张量的运算式子而创建的,并且不断更新,直到张量的运算结束。这和tensorflow框架所使用的静态图产生了对比,静态图的创建过程是在张量的运算全部走完,然后直接创建的一张图。

一.Tensor

张量就是n维向量,数据类型就是tensor类型,tensor类型中的有8个很重要的属性:

data:张量的数据

dtype:张量的数据类型

shape:张量的形状

device:张量所在的设备位置,一般是CPU/GPU,是加速的关键

grad:梯度值

grad_fn:梯度反向传播过程中,告诉你某中间变量是通过哪种运算得来的

requires_grad:是否可微,一般默认为False

is_leaf:是否为也叶子节点

这八个属性前四个表示了该张量数据层面的属性,后四个表示了该张量的微分属性。

二.动态计算图

动态计算图的特点主要通过下面的例子来说明,可以通过例子仔细体会:

首先创建两个可微分的张量,这两个张量都是叶子节点:

x = torch.tensor([3.], requires_grad=True)
w = torch.tensor([2.], requires_grad=True)

然后创建两个中间变量:

y = x + w
z = y ** 2

注意,由于叶子节点张量x和w是可微分的,所以y和z都是可微的,我们可以通过以下打印结果看出:

print(y.requires_grad)
print(z.requires_grad)

'''
True
True
'''

接下来,通过对z的反向传播,我们可以求出此时x和w的梯度:

z.backward()
print(w.grad)
print(x.grad)

'''
tensor([10.])
tensor([10.])
'''

值得注意的是:

1.动态计算图在执行完backward()操作之后,计算图就会被销毁,如果再次使用z.backward(),会直接报错,可以在执行第一次反向传播操作时使用z.backward(retain_graph=True)来保存计算图。

2.叶子节点的梯度值会根据反向转播次数的增加不断地累计,这个小细节要注意!并且在反向传播之后,中间节点张量的梯度也会跟着销毁(省内存),所以遇到一些要保留中间节点梯度的情况,我们需要使用retain_grad()函数。

3.如果我们想在变量y之后的计算不加入计算图(说白了就是让z的requires_grad的值为False),有以下两种方法:

方法一:

with torch.no_grad():
    z = y ** 2

方法二(detach函数只复制了tensor的数值,而requires_grad=False):

y1 = y.detach()
z = y1 ** 2

这个时候z已经不是可微的了,并且也不能执行反向传播操作了,但我们仍然可以将y进行反向传播。

  • 4
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值