总说
由于pytorch 0.4版本更新实在太大了, 以前版本的代码必须有一定程度的更新. 主要的更新在于 Variable和Tensor的合并., 当然还有Windows的支持, 其他一些就是支持scalar tensor以及修复bug和提升性能吧. Variable和Tensor的合并导致以前的代码会出错, 所以需要迁移, 其实迁移代价并不大.
Tensor和Variable的合并
说是合并, 其实是按照以前(0.1-0.3版本)的观点是: Tensor现在默认requires_grad=False的Variable了. torch.Tensor
和torch.autograd.Variable
现在其实是同一个类! 没有本质的区别! 所以也就是说, 现在已经没有纯粹的Tensor了, 是个Tensor, 它就支持自动求导! 你现在要不要给Tensor
包一下Variable
, 都没有任何意义了.
##查看Tensor
的类型
使用.isinstance()
或是x.type()
, 用type()
不能看tensor的具体类型.
>>> x = torch.DoubleTensor([1, 1, 1])
>>> print(type(x)) # was torch.DoubleTensor
"<class 'torch.Tensor'>"
>>> print(x.type()) # OK: 'torch.DoubleTensor'
'torch.DoubleTensor'
>>> print(isinstance(x, torch.DoubleTensor)) # OK: True
True
##requires_grad 已经是Tensor的一个属性了
>>> x = torch.ones(1)
>>> x.requires_grad #默认是False
False
>>> y = torch.ones(1)
>>> z = x + y
>>> # 显然z的该属性也是False
>>> z.requires_grad
False
>>> # 所有变量都不需要grad, 所以会出错
>>> z.backward()
RuntimeError: element 0 of tensors does not require grad and does not have a grad_fn
>>>
>>> # 可以将`requires_grad`作为一个参数, 构造tensor
>>> w = torch.ones(1, requires_grad=True)
>>> w.requires_grad
True
>>> total = w + z
>>> total.requires_grad
True
>>> # 现在可以backward了
>>> total.backward()
>>> w.grad
tensor([ 1.])
>>> # x,y,z都是不需要梯度的,他们的grad也没有计算
>>> z.grad == x.grad == y.grad == None
True
通过.requires_grad()
来进行使得Tensor需要梯度.
##不要随便用.data
以前.data
是为了拿到Variable
中的Tensor
,但是后来, 两个都合并了. 所以 .data返回一个新的requires_grad=False的Tensor! 然而新的这个Tensor
与以前那个Tensor
是共享内存的. 所以不安全, 因为
y = x.data # x需要进行autograd
# y和x是共享内存的,但是这里y已经不需要grad了,
# 所以会导致本来需要计算梯度的x也没有梯度可以计算.从而x不会得到更新!
所以, 推荐用x.detach()
, 这个仍旧是共享内存的, 也是使得y
的requires_grad为False, 但是,如果x需要求导, 仍旧是可以自动求导的!
.clone().detach()创建新的tensor
To copy construct from a tensor, it is recommended to use sourceTensor.clone().detach() "
"or sourceTensor.clone().detach().requires_grad_(True), rather than torch.tensor(sourceTensor).
即
a = torch.randn(</