专栏推荐
正文
深度学习框架pytorch拥有自动求导的机制,自动求导是 PyTorch 中非常重要的特性,能够让我们避免手动去计算非常复杂的导数,这能够极大地减少了我们构建模型的时间。
导入的包
import torch
from torch.autograd import Variable
对标量进行自动求导
x = Variable(torch.Tensor([2]), requires_grad=True)
y = x + 2
z = y ** 2 + 3
print(z)
z.backward()
print(x.grad)
我们可以看到变量x在申明的时候,指定了requires_grad=True,这样和x进行运算的所有变量都相当于设置了requires_grad=True,比如y、z都相当于设置了requires_grad=True。这样我们就可以使用反向传播了,本例中z.backward()就是表示的执行反向传播,最后x.grad表示的是z对x的偏导数。
对矩阵求梯度
x = Variable(torch.randn(10, 20), requires_grad=True)
y = Variable(torch.randn(10, 5), requires_grad=True)
w = Variable(torch.randn(20, 5), requires_grad=True)
out = torch.mean(y - torch.matmul(x, w))
out.backward()
print(x.grad)
print(w.grad)
本例中我们申明了三个矩阵,分别是x、y、w,然后我们对其进行计算操作。torch.matmul 是做矩阵乘法,torch.mean是做均值化。然后执行反向传播就可以获取到矩阵x的梯度了。
在pytorch0.4之后Variable 正式合并入Tensor, Variable 本来实现的自动微分功能,Tensor就能支持,所以我们可以直接在创建tensor的时候,使用autograd功能,只需要设置tensor.requries_grad=True.
x = t.ones(2, 2, requires_grad=True)
这样这个x就可以自动求导了
y = w * x + b
x=torch.ones(1)
b=torch.rand(1,requires_grad=True)
w=torch.rand(2,requires_grad=True)
z=w*x
y=z+b
y.backward()#自动求导,它会对所有需要求梯度的变量进行求导,然后得到他们的梯度。y.backward()等价于y.backward(torch.FloatTensor([1])),因为我们上面求得梯度都是标量(维度是1,所以torch.FloatTensor([1])),backward中的参数就没有必要来写了。
求完梯度之后,我们就可以使用属性grad来求出每个变量的梯度
print (x.grad) #求变量x的梯度,梯度为w,也就是2
print(w.grad)#求变量w的梯度,梯度为x,也就是1
print (b. grad)#求变量b的梯度,梯度为常数1
我们前面是对我们的标量进行求导,我们也可以来对我们的矩阵进行求导
x = torch.randn(3) #创建一个随机矩阵,类型是tensor,x的结果为tensor([-0.2895, 0.7542, -1.3040])
x=Variable(x, requires_grad=True) #我们将tensor转成变量
y= x * 2 #构建计算图print (y)
y.backward(torch.FloatTensor( [1, 1,1])) #对变量进行求梯度,因为我们的矩阵是三维的,所以我们需要torch.FloatTensor( [1, 1,1])
print (x. grad) #输出变量x的梯度,结果为:tensor([2., 2., 2.]),因为我们的tensor为三行一列的向量,所以我们的梯度需要[1,1,1]表示对这个向量中的每一个进行求梯度。
我们也可以y.backward(torch.FloatTensor( [1, 0.1 , 0. 01] )) ,这样得到的梯度就是它们原本的梯度分别乘上 1 , 0.1 和 0.01,结果为:
tensor([2.0000, 0.2000, 0.0200])
可运行代码为:
import torch
from torch.autograd import Variable
x= torch.randn(3) #创建一个随机矩阵,1行3列,类型是tensor
print(x)
x=Variable(x, requires_grad=True)
print(x)
y=x*2
y.backward(torch.FloatTensor([1,1,1]))
print(x.grad)
结果为:
对矩阵求梯度
import torch
from torch.autograd import Variable
x= torch.randn(2,3) #创建一个随机矩阵,1行3列,类型是tensor
print(x)
x=Variable(x, requires_grad=True)
print(x)
y=x*2
y.backward(torch.FloatTensor([[1,0.1,0.01],[1,1,1]]))
print(x.grad)
如果我们要是将x= torch.randn(2,3),建立一个两行三列的,那么我们的这里y.backward(torch.FloatTensor([[1,0.1,0.01],[1,1,1]]))也要两行三列,这样才能一一对应,结果为:
多次自动求导
#调用 backward就会自动反向求导,但是求导完之后计算图就会被丢弃,以后就不能调用backward了,为了防止这种情况,我们可以在自动求导的时候,指定不丢弃计算图retain_graph=True。
x=torch.randn(3)
x=Variable(x,requires_grad=True)
y=x*3
y.backward(torch.FloatTensor([1,1,1]),retain_graph=True)#第一次求导
print(x.grad)
x.grad.data.zero_() # 归零之前求得的梯度
y.backward(torch.FloatTensor([1,1,1]))#第二次求导
print(x.grad)
閱讀更多 幻風的AI之路 的文章