【研究生随笔】Pytorch中的线性代数(微分)
在深度学习中,导数和微分是优化算法的关键步骤,对于每个参数,如果把这个参数增加或减少⼀个⽆穷小的量,就可以知道损失会以多快的速度变化。
-
求导
○ 下面构造一个Y = X^2 的求导过程
X = tensor(3.0,requires_grad=True)#让X的初始值为3.0,参数后面讲Y = torch.pow(X,2)#构建X^2Y.backward()Print(X.grad) #输出为tensor(6.)
上面就是求导的基本过程。
标量对向量或矩阵的求导,会比较复杂一点,但是基本是一样的,如下:
import torch as torch
# 创建一个多元函数,即Y=xw+b=Y=x1*w1+x2*w2+x3*w3+b,x不可求子,M,b设置可求子
X = torch.tensor([1.5,2.5,3.5], requires_grad = False)
W = torch.tensor([0.2,B,4,日.6], requires_grad = True)
b = torch,tensor(.1, requires_grad = True)
Y = torch.add(torch.dot(x,W), b)
# 判断每个tensor是否是可以求导的
print(X.requires_grad)
print(W.requires_grad)
print(b.requfres_grad)
print(Y.requires_grad)
# 求导,通过backward函数来实现
Y.backward()
# 查看导数,即所谓的梯度
print(W.grad)
print(b.grad)
'''
运行结果为:
False
True
True
Trua
ten5or([1.5000, 2.5000, 3.5000])
tensor(1.)
'''
○ 相关参数和函数:
requires_grad:构建一个tensor时的一个参数,默认为false即不可导,相反。可以通过X.requires_grad()的返回值来判断是否可导。
一个表达式中,只有当所有元素都不可导时,这个表达式才不可导(因为可以求偏导)
backward():直接调用的话只能求普通函数的求导,复合函数的话会复杂一点。
只能是【标量】对【标量】,或者【标量】对【向量/矩阵】求导!这个很关键,很重要!
• 向量对向量、矩阵对矩阵的求导:通过backword的一个参数gradient来实现(第六行)gradient参数的维度与最终的函数y保持一样的形状,每一个元素表示当前这个元素所对应的权重。
这就可以在之后的实验中,对特定的数据增加权重来进行对比实验,但正式实验中一般不这样做,权重是不可以随意修改的。
import torch as torch
x = torch.tensor([[1.,2.,3.],[4.,5.,6.]], requires_grad = True)
y = torch.add(torch.pow(x,2), x)
gradient = torch.tensor([[1.0,1.0,1.0], [1.0,1.0,1.0]])
y.backward(gradient)
print(x.grad)
'''
运行结果为:
tensor([[ 3.,5.,7.],
[9.,11.,13.]])
'''
• 一般求导所用到的参数解释(包括上面的gradient):
○ y.backward(grad_tensors=None, retain_graph=None, create_graph=False)
grad_tensors:同gradient
retain_graph:保留运算图,就是求导的顺序图,一般复合函数求导会用到,一个计算图在进行反向求导之后,为了节省内存,这个计算图就销毁了。 如果你想再次求导,就会报错。
create_graph:应该就是允许计算高阶导数吧,还不是很清楚,之后遇到再百度。
○ torch.autograd.backward(tensors,grad_tensors=None, retain_graph=None, create_graph=False)(反求导)
多了个tensors,这个就是要进行反求导的函数了。