关于Variable和Tensor
旧版本的Pytorch中,Variable是对Tensor的一个封装;在Pytorch大于v0.4的版本后,Varible和Tensor合并了,意味着Tensor可以像旧版本的Variable那样运行,当然新版本中Variable封装仍旧可以用,但是对Varieble操作返回的将是一个Tensor。
import torch as t from torch.autograd import Variable a = t.ones(3,requires_grad=True) print(type(a)) #输出:<class 'tor<b>本文来源gao@!dai!ma.com搞$$代^@码!网</b>ch.Tensor'> a=Variable(a) print(type(a)) #输出仍旧是:<class 'torch.Tensor'> print(a.volatile) #输出:__main__:1: UserWarning: volatile was removed (Variable.volatile is always False) a.volatile=True print(a.volatile) #输出:__main__:1: UserWarning: volatile was removed (Variable.volatile is always False) #现版本pytorch中移除了volatile这个属性,即volatile总是false
叶子节点leaf
对于那些不是任何函数(Function)的输出,由用户创建的节点称为叶子节点,叶子节点的grad_fn为None。
import torch as t a = t.ones(3,requires_grad=True) b = t.rand(3,requires_grad=True) a,a.is_leaf #输出:(tensor([1., 1., 1.], requires_grad=True), True) b #输出:(tensor([0.4254, 0.8763, 0.5901], requires_grad=True), True) c = a*b c.is_leaf #输出:False.说明c不是叶子节点 a.grad_fn #输出:None.叶子节点的grad_fn为None. c.grad_fn #输出:<MulBackward0 object at 0x7fa45c406278>
autograd操作
首先Tensor是默认不需要求导的,即requires_grad默认为False。
import torch as t a = t.ones(3) a.requires_grad #输出:False.Tensor默认不需要求导
如果某一个节点requires_grad被设置为True,那么所有依赖它的节点requires_grad都为True。
import torch as t a = t.ones(3) b = t.ones(3,requires_grad=True) b.requires_grad #输出:True c = a + b c.requires_grad #输出:True.虽然c没有指定需要求导,然是c依赖于b,而b需要求导,所以c.requires_grad=True
只有scalar才能进行反向backward()操作,并且backward对于叶节点的grad的是累加的。当只进行计算操作不做backward,叶节点的grad不发生变化。
更正一下,并不是只有scaler才能进行backward操作,矩阵和向量也可以,只不过backward()中要添加对应维度的参数。
import torch as t a = t.ones(3,requires_grad=True) b = t.rand(3,requires_grad=True) a,b #输出:(tensor([1., 1., 1.], requires_grad=True), #tensor([0.9373, 0.0556, 0.6426], requires_grad=True)) c = a*b c #输出:tensor([0.9373, 0.0556, 0.6426], grad_fn=<MulBackward0>) c.backward(retain_graph=True) #输出:RuntimeError: grad can be implicitly created only for scalar outputs #只有数值scalar才能进行backward操作 d = c.sum() d.backward(retain_graph=True) #retain_graph=True是为了保存中间缓存,否则再次backward的时候会报错 a.grad #输出:tensor([0.9373, 0.0556, 0.6426]) b.grad #输出:tensor([1., 1., 1.]) #backward后a和b的grad产生了数值 e = c.sum() e.backward(retain_graph=True) b.grad #输出:tensor([2., 2., 2.]).b的grad进行了两次backward后进行了累加. f = c.sum() b.grad #输出:tensor([2., 2., 2.]) #只进行计算不backward,梯度不更新
Tensor.data和Tensor.detach()
如过tensor的数值需要参与计算又不想参与到计算图的更新中,计算的时候可以用tensor.data,这样既能利用tensor的数值,又不会更新梯度。
import torch as t a = t.ones(3,4,requires_grad=True) b = t.rand(3,4,requires_grad=True) a.data.requires_grad #输出:False. a.data独立于计算图之外 c = a.data * b.data d = c.sum() d.backward() #输出:RuntimeError: element 0 of tensors does not require grad and does not have a grad_fn #因为独立于计算图之外,requires_grad = False所以不能backward()