【deep learning with pytorch】Tensor
pytorch 与tensorflow一样为python的科学计算库,可以自动为神经网络进行反向梯度传播。在pytorch中最关键的库就是autograd,就是它起到了这个作用。
autograd这个库让变量类型为tensor的变量可以自动进行梯度运算,但是梯度运算需要基于运行的框架之中,也就是说,只有当网络在跑的时候才能够做反向传播,这样每次迭代变量的数值也才会不同。
Tensor
在pytorch中主要的类为torch.Tensor。一般的变量可以定义为这个类。在定义Tensor的时候,你可以选择是否要对该变量计算梯度。(让变量的参数 .require_grad 为True,默认为false)这时,对该变量的任何计算操作都会被记录下来,结束计算的时候再调用 .backward() 函数,这样就可以计算出变量的梯度,并会将梯度存入 .grad 之中。
为了停止记录对一个变量的所有操作可以调用 .detach() 函数,可以防止未来对该变量的操作被记录下来。
但有的时候可能想要让一整个神经网络不做反向梯度传播。如果对每一个变量都调用 .detach() 函数会非常麻烦,故而可以使用torch.no_grad() ,它可以对一整个神经网络进行操作,让这个代码块中的tensor(特别是 .require_grad 参数为True的变量)不再进行反向梯度计算。(这一点经常在test中用到)
在pytorch中还有一个非常重要的类是Function类。Function类和tensor类是相互影响、相互纠缠的。tensor中有一个参数为 .grad_fn 代表了这个tensor被建立的方式。比如说:
import torch
#建立一个张量x
x = torch.ones(2, 2, requires_grad=True)
print(x)
#结果为:tensor([[1., 1.],
#[1., 1.]], requires_grad=True)
#做加法预算:
y = x + 2
print(y)
#结果为:tensor([[3., 3.],
# [3., 3.]], grad_fn=<AddBackward0>)
print(y.grad_fn)
#out: <AddBackward0 object at 0x7f31024d1f98>
#这里显示的是y的创建方式
#对y做更多的操作:
z = y * y * 3
out = z.mean()
print(z, out)
#结果tensor([[27., 27.],
# [27., 27.]], grad_fn=<MulBackward0>) tensor(27., grad_fn=<MeanBackward0>):
#计算反向梯度:
out.backward();#进行反向梯度计算**注意这里用.backward()函数只能对一个scalar使用如果想要对非scalar使用,见下面的例子**
print(x.grad)#得到d(out)/dx
#结果为:tensor([[4.5000, 4.5000],
#[4.5000, 4.5000]])
具体计算过程如图:
上面说过如果.backward()针对非scalar变量使用的时候,需要乘上一个v矩阵,其中v矩阵应该是一个反向求导得到的结果。
x = torch.randn(3, requires_grad=True)
y = x * 2
while y.data.norm() < 1000:
y = y * 2
v = torch.tensor([0.1, 1.0, 0.0001], dtype=torch.float)
y.backward(v)#这里要乘以v
print(x.grad)
#结果:tensor([1.0240e+02, 1.0240e+03, 1.0240e-01])
print(x.requires_grad)#True
print((x ** 2).requires_grad)#True
with torch.no_grad():#注意这里torch.no_grad()的运用
print((x ** 2).requires_grad)#False