标量求导
导数就是切线斜率,链式求导
亚导数:不可微的函数
注意[ -1,1]取值
梯度
关于梯度的理解参考链接https://www.bilibili.com/video/BV1i54y1B7Tk?from=search&seid=17023495418368110257&spm_id_from=333.788.b_636f6d6d656e74.35
此处采用分子布局符号
把看成z=f(x,y)函数,对每个z值做等高线,梯度就是值变化最大的方向
向量对向量的求导->矩阵
矩阵求导
向量的链式法则
例子
I就是单位矩阵,主对角线全1,其余元素全0
自动求导:计算一个函数在指定值上的导数
与符号求导和数值求导不同
计算图:无环图
显式构造
隐式构造/pytorch,一开始就给值了
自动求导的两种模式:
正向累积
反向累积(反向传递)
反向传递
例子
步骤:
复杂度:
计算复杂度:O(n),n是操作子的个数
正向和反向的代价类似
内存复杂度:O(n),需要存储正向的所有中间结果
跟正向累积对比:
O(n)计算复杂度用来计算一个变量的梯度
O(1)内存复杂度
但是对于对个变量的梯度时,反向更好
自动求导
y=2xTx(x转置乘x)
import torch
x = torch.arange(4.0)
#在计算y关于x的梯度之前,需要一个地方来存储梯度
x.requires_grad_(True)#等价于torch.arange(4.0,requires_grad=True)
y = 2*torch.dot(x,x)#tensor(28.,grad_fn=<MulBackward0>)
#调用反向传播函数自动计算y关于每个x分量的梯度
y.backward()
x.grad
#默认情况下,pytorch会累积梯度,在计算下一个函数时,需要清楚之前的值
x.grad.zero_()#_表示重写内容
y = x.sum()
y.backward()
x.grad
#通常情况下,不会对非标量求梯度
x.grad.zeros_()
y = x*x
#等价y.backward(torch.ones(len(x)))
y.sum().backward()
x.grad
#将某些计算移动到计算图之外
x.grad.zero_()
y=x*x
u=y.detach()
z = u*x
z.sum().backward()
x.grad == u
x.grad.zero_()
y.sum().backward()
x.grad == 2*x
正向算出函数值,反向求导
累积梯度:批量一次算不完
对标量求导,比如loss
多个loss分别反向时需要累积梯度
获取grad前需要backward,性能考虑,是否必须