矩阵梯度计算方法


动手学深度学习:Dive into deep learning,李沐

简单点说矩阵或者向量的梯度计算遵从一个规则;

对分子也就是被求梯度的张量,先竖后横,也就是先对第一列第一个元素到最后一列最后一个元素的路径,对分母也是按照这个规则。

标量对矩阵的梯度结果形状是分母的转置也就是下面示例的k,n。
向量(m,1)对矩阵(n,k)的梯度结果形状是(m,k,n)也就是高是m宽是k长是n
矩阵对标矩阵的梯度结果是(m,l,k,n)也就是l个mkn的三维矩阵,

这也叫做分子布局,求导的时候分子的shape不变,分母进行转置然后得到结果。

除了对于标量的计算不会改变维度数量

特殊的是向量的内积求导是另一个向量的转置

矩阵的梯度计算 - 图1的梯度是矩阵的梯度计算 - 图2


向量的链式求导规则

偏导的链式计算也遵从向量乘的维度变换。

自动求导是指计算一个函数在指定值上的导数,所以这个函数整体不可导也是可以自动求导的,区别于符号求导(导数也是一个函数式的形式),以及数值求导(微小增量极限来求导)。

pytorch的自动求导是建立在动态计算图上,前向计算时构建计算图,方向传播的时候根据计算图来计算梯度

这点就是计算图的概念抽象。

将代码分解为基本的操作单元,然后将计算表示为一个有向无环图。

计算图可以显式构造,

隐式构造就是使用动态图

使用自动求导


  • 创建张量
  • 张量启用requires_grad(True)使用梯度记录
  • 使用backward()反向计算
  • 使用grad来获取梯度

默认情况下pytorch会将梯度累计起来,需要清除前面的值

grad.zero_()

绝大多数的时候深度学习只对标量进行求导,很少对向量和矩阵进行求导,这个时候对向量做sum

对张量做.detach()做常量处理

经过python函数处理的计算图也可以得到变量的梯度。

显式构造和隐式构造


显式构造就是使用类python的方式实现计算之后,再来微分

反向传播过程中会利用计算图正向计算中存储的中间结果。

为什么pytorch会默认累计梯度计算?
对一个大批量数据计算的时候,切分数据将各个分块的梯度累加计算。

因为loss一般是一个标量,向量loss会使得模型计算量比较大

使用多个loss需要累积梯度

因为反向计算成本高,所以不启用backward的时候是不会执行梯度计算。

循环神经网络在逻辑上是一个有向环图。