矩阵梯度计算方法
动手学深度学习:Dive into deep learning,李沐
简单点说矩阵或者向量的梯度计算遵从一个规则;
对分子也就是被求梯度的张量,先竖后横,也就是先对第一列第一个元素到最后一列最后一个元素的路径,对分母也是按照这个规则。
标量对矩阵的梯度结果形状是分母的转置也就是下面示例的k,n。
向量(m,1)对矩阵(n,k)的梯度结果形状是(m,k,n)也就是高是m宽是k长是n
矩阵对标矩阵的梯度结果是(m,l,k,n)也就是l个mkn的三维矩阵,
这也叫做分子布局,求导的时候分子的shape不变,分母进行转置然后得到结果。
除了对于标量的计算不会改变维度数量
特殊的是向量的内积求导是另一个向量的转置
的梯度是
向量的链式求导规则
偏导的链式计算也遵从向量乘的维度变换。
自动求导是指计算一个函数在指定值上的导数,所以这个函数整体不可导也是可以自动求导的,区别于符号求导(导数也是一个函数式的形式),以及数值求导(微小增量极限来求导)。
pytorch的自动求导是建立在动态计算图上,前向计算时构建计算图,方向传播的时候根据计算图来计算梯度
这点就是计算图的概念抽象。
将代码分解为基本的操作单元,然后将计算表示为一个有向无环图。
计算图可以显式构造,
隐式构造就是使用动态图
使用自动求导
- 创建张量
- 张量启用
requires_grad(True)
使用梯度记录 - 使用
backward()
反向计算 - 使用
grad
来获取梯度
默认情况下pytorch会将梯度累计起来,需要清除前面的值
grad.zero_()
绝大多数的时候深度学习只对标量进行求导,很少对向量和矩阵进行求导,这个时候对向量做sum
对张量做.detach()
做常量处理
经过python函数处理的计算图也可以得到变量的梯度。
显式构造和隐式构造
显式构造就是使用类python的方式实现计算之后,再来微分
反向传播过程中会利用计算图正向计算中存储的中间结果。
为什么pytorch会默认累计梯度计算?
对一个大批量数据计算的时候,切分数据将各个分块的梯度累加计算。
因为loss一般是一个标量,向量loss会使得模型计算量比较大
使用多个loss需要累积梯度
因为反向计算成本高,所以不启用backward的时候是不会执行梯度计算。
循环神经网络在逻辑上是一个有向环图。