一、基础知识
注:1、深度学习框架通过自动计算导数,即自动微分(automatic differentiation)来加快求导。实际中,根据设计好的模型,系统会构建一个计算图(computational graph),来跟踪计算是哪些数据通过哪些操作组合起来产生输出。自动微分使系统能够随后反向传播梯度。这里,反向传播(backpropagate)意味着跟踪整个计算图,填充关于每个参数的偏导数。
2、torch.mul()、torch.mm()、torch.dot()与torch.mv()区别
(1)torch.mul()是矩阵的点乘,即对应位的相乘,要求shape一样,返回的还是个矩阵
(2)torch.mm()是矩阵正常的矩阵相乘
(3)torch.dot()类似于mul(),它是向量(即只能是一维的张量)的对应位相乘再求和,返回一个tensor数值
(4)torch.mv()是矩阵和向量相乘,类似于torch.mm()
二、简单举例
1、例1:假设对函数y = 2x 关于列向量x求导
梯度应为4x
2、例2:
三、非标量变量的反向传播
例:
注:当y不是标量时,向量关于向量x的导数的最自然解释是一个矩阵。对于高阶和高维的y和x,求导的结果可以是一个高阶张量。然而,虽然这些更奇特的对象确实出现在高级机器学习中(包括深度学习中),但当调用向量的反向计算时,我们通常会试图计算一批训练样本中每个组成部分的损失函数的导数。这里,我们的目的不是计算微分矩阵,而是单独计算批量中每个样本的偏导数之和。
四、分离计算
有时,我们希望将某些计算移动到记录的计算图之外。
例:设y是作为x的函数计算的,而z则是作为y和x的函数计算的
假设计算z关于x的梯度,由于某种原因,希望将y视为一个常数,并且只考虑到x在y被计算后发挥的作用。这里可以分离y返回一个新变量u,该变量与y具有相同的值,但丢弃计算图中如何计算y的任何信息。换言之,梯度不会向后流经u到x。因此,下面的反向传播函数计算z = u * x关于x的偏导数,同时将u作为常数处理,而不是z=x*x*x关于x的偏导数
由于记录了y的计算结果,可以随后在y上调用反向传播,得到y=x*x关于的x的导数,即2*x
五、Python控制流的梯度计算
使用自动微分的一个好处是:即使构建函数的计算图需要通过Python控制流(eg:条件、循环或任意函数调用),我们仍然可以计算得到的变量的梯度。在下面的代码中,while循环的迭代次数和if语句的结果都取决于输入a的值.
注:对于任何a,存在某个常量标量k,使得f(a)=k*a,其中k的值取决于输入a,因此可以用d/a验证梯度是否正确