pytorch 自动求导/更新loss等 原理集合

requires_grad

pytorch新建一个tensor,其默认requires_grad=False;但神经网络的权重参数(即net.parameters)默认requires_grad=True

例子,比如x的requires_grad=True,y的requires_grad=False,而z=x+3y,则z的requires_grad也等于true,因为z由两条路径组成,其中x的那条是True。

计算图

计算图记录了各个参数之间的运算关系,根据这个计算图来计算各参数的梯度:根据参数之间的关系路径(即黑色箭头),以及相加相乘等操作(由grad_fn属性来记录),进行链式求导

此外,pytorch的计算图是动态的,几乎每进行一次运算都会拓展原先的计算图。

loss.backward()

backward的意思是反向传播。执行backward()函数后,pytorch会根据在运算过程中(即前向传播过程中)搭建好的计算图,计算所有requires_grad=True的参数的梯度。以loss.backward()为例,通过loss.backward()进行反向传播计算时,整张计算图将对loss进行求导,所有requires_grad=True的参数都将参与梯度求导的运算,并将梯度累加到.grad属性中。

当反向传播完成,计算图默认会被清除,即进行前向传播时记录的计算过程会被释放掉,即计算图中的非叶子结点(图中的f、g、y)都会被释放掉。所以默认情况下,进行一次前向传播后最多只能用生成的计算图进行一次反向传播。可以用backward(retain_graph=True)让计算图不被立即释放,但这样容易显存溢出

optimizer.step()

求完梯度之后,就可以用优化器optimizer对参数的值进行更新了,更新的效果依赖于梯度和学习率。

with torch.no_grad()

如果不需要进行参数更新,则要把该参数的requires_grad设成False,这样pytorch将关闭自动求导功能(上述所说的计算图、backward这个过程就是“自动求导过程”),不再追踪所有对于该参数的操作。

在with torch.no_grad()下计算出来的张量requires_grad都等于False,grad_fn属性都等于None。这意味着,所有计算操作都不会被记录在计算图中,从而减少了计算图的大小,也避免了不必要的内存消耗。

当然,也可以自己把所有无需求导的参数的requires_grad都改成False,效果跟with torch.no_grad()一样。

至于哪些参数可以避免求导,可根据计算图来看,从需要求导的参数到loss经过了哪些分支,这些分支上的所有参数都需要求导,其它分支上的参数都可以torch.no_grad。

detach()

datach的作用是将变量从计算图中剥离出来。

例子,stable diffusion的50步去噪过程,如果不加torch.no_grad,则由于网络的权重参数requires_grad都等于True,所以每经过一个step循环,计算图就不断拓展,没到50步就显存溢出了。此时除了使用torch.no_grad,或把网络所有参数requires_grad都改False,还可以对每步去噪得到的latent进行detach操作,即 latent = latent.clone().detach(),通过detach把latent从原来的计算图中剥离了,新的计算图计算的梯度就不会传到原来的计算图中,也就避免了显存溢出。

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值