李沐 自动求导实现【动手学深度学习v2】

:label:sec_autograd

正如 :numref:sec_calculus中所说,求导是几乎所有深度学习优化算法的关键步骤。 虽然求导的计算很简单,只需要一些基本的微积分。 但对于复杂的模型,手工进行更新是一件很痛苦的事情(而且经常容易出错)。

深度学习框架通过自动计算导数,即自动微分(automatic differentiation)来加快求导。

实际中,根据设计好的模型,系统会构建一个计算图(computational graph), 来跟踪计算是哪些数据通过哪些操作组合起来产生输出。 自动微分使系统能够随后反向传播梯度。

这里,反向传播(backpropagate)意味着跟踪整个计算图,填充关于每个参数的偏导数。

一个简单的例子

作为一个演示例子,(假设我们想对函数𝑦=2𝑥⊤𝑥关于列向量𝑥求导)。

首先,我们创建变量x并为其分配一个初始值

[在我们计算𝑦关于𝑥的梯度之前,需要一个地方来存储梯度]

重要的是,我们不会在每次对一个参数求导时都分配新的内存。 因为我们经常会成千上万次地更新相同的参数,每次都分配新的内存可能很快就会将内存耗尽。

注意,一个标量函数关于向量𝑥的梯度是向量,并且与𝑥具有相同的形状。

现在计算𝑦

x是一个长度为4的向量,计算xx的点积,得到了我们赋值给y的标量输出。

接下来,[通过调用反向传播函数来自动计算y关于x每个分量的梯度],并打印这些梯度。

函数𝑦=2𝑥⊤𝑥关于𝑥的梯度应为4𝑥。 让我们快速验证这个梯度是否计算正确。

[现在计算x的另一个函数。]

非标量变量的反向传播

y不是标量时,向量y关于向量x的导数的最自然解释是一个矩阵

对于高阶和高维的yx,求导的结果可以是一个高阶张量。

然而,虽然这些更奇特的对象确实出现在高级机器学习中(包括[深度学习中]), 但当调用向量的反向计算时,我们通常会试图计算一批训练样本中每个组成部分的损失函数的导数。

这里,我们的目的不是计算微分矩阵,而是单独计算批量中每个样本的偏导数之和。

分离计算

有时,我们希望[将某些计算移动到记录的计算图之外]。

例如,假设y是作为x的函数计算的,而z则是作为yx的函数计算的。 想象一下,我们想计算z关于x的梯度,但由于某种原因,希望将y视为一个常数, 并且只考虑到xy被计算后发挥的作用。

这里可以分离y来返回一个新变量u(.detach()),该变量与y具有相同的值, 但丢弃计算图中如何计算y的任何信息。 换句话说,梯度不会向后流经ux

因此,下面的反向传播函数计算z=u*x关于x的偏导数,同时u作为常数处理, 而不是z=x*x*x关于x的偏导数

由于记录了y的计算结果,我们可以随后在y上调用反向传播, 得到y=x*x关于的x的导数,即2*x

y依然是关于x的函数

Python控制流的梯度计算

使用自动微分的一个好处是: [即使构建函数的计算图需要通过Python控制流(例如,条件、循环或任意函数调用),我们仍然可以计算得到的变量的梯度]。

在下面的代码中,while循环的迭代次数和if语句的结果都取决于输入a的值。

让我们计算梯度。

我们现在可以分析上面定义的f函数。 请注意,它在其输入a中是分段线性的。 换言之,对于任何a,存在某个常量标量k,使得f(a)=k*a,其中k的值取决于输入a,因此可以用d/a验证梯度是否正确。

小结

  • 深度学习框架可以自动计算导数:我们首先将梯度附加到想要对其计算偏导数的变量上,然后记录目标值的计算,执行它的反向传播函数,并访问得到的梯度。

练习

1.为什么计算二阶导数比一阶导数的开销要更大?

  • 计算复杂度:二阶导数的计算需要在一阶导数的基础上再次进行求导,这意味着需要对已经求导过的函数再次应用求导规则。这个过程涉及到更多的数学运算,因此计算量更大。
  • 多次函数求值:在某些数值方法中,如中心差分法,计算二阶导数可能需要在同一个点附近计算多个函数值。
  • 数值稳定性:在数值计算中,二阶导数的计算可能会引入更多的舍入误差,因为涉及到更多的浮点运算。此外,当分母变得很小时,如在中心差分法中的 ( h^2 ),可能会导致数值不稳定。
  • 反向传播的复杂性:在机器学习中,尤其是在使用神经网络时,计算二阶导数通常涉及到反向传播算法的二次运行。这不仅增加了计算量,还可能导致更复杂的控制流和数据依赖关系。

2.在运行反向传播函数之后,立即再次运行它,看看会发生什么。

在计算梯度时,试图对已经释放的图进行第二次反向传播。

3.在控制流的例子中,我们计算d关于a的导数,如果将变量a更改为随机向量或矩阵,会发生什么?

会报错

错误原因是在计算梯度时,输出值不是一个标量。

解决方法为尝试将输出值转换为标量,例如通过取平均值或求和

  • 13
    点赞
  • 11
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值