Pytorch Tricks

1. In-place Operate

会改变 tensor 的函数操作会用一个下划线后缀来标示。比如,torch.FloatTensor.abs_() 会在原地计算绝对值,并返回改变后的tensor,而 tensor.FloatTensor.abs() 将会在一个新的 tensor 中计算结果。

2. Dynamic Graphs

PyTorch 采用动态计算图,而 TensorFlow 采用静态计算图

3. net.zero_grad()

再利用 loss.backward() 计算梯度之前,需要先清空已经存在的梯度缓存(因为PyTorch是基于动态图的,每迭代一次就会留下计算缓存,到一下次循环时需要手动清楚缓存),如果不清除的话,梯度就会累加(注意不是覆盖)。

net.zero_grad()  # 清除缓存
print(net.conv1.bias.grad) # tensor([0., 0., 0., 0., 0., 0.])

loss.backward()

print(net.conv1.bias.grad) # tensor([ 0.0181, -0.0048, -0.0229, -0.0138, -0.0088, -0.0107])

4. reshape & view

view 可以看成,先按行展开成一维 tensor 再转换成所需维度的 tensor。只能作用在连续的内存空间上. 并且不会对 tensor 进行复制。当它作用在非连续内存空间的 tensor 上时,会报错。 reshape 可以作用在任何空间上,并且会在需要的时候创建 tenosr 的副本。

5. tensor.detach() & tensor.data

PyTorch 0.4中,.data 仍保留,但建议使用 .detach(),区别在于 .data 返回和 x 的相同数据 tensor,但不会加入到 x 的计算历史里,且 require s_grad = False,这样有些时候是不安全的,因为 x.data 不能被 autograd 追踪求微分。.detach() 返回相同数据的 tensor,且 requires_grad=False,但在进行反向传播的时候,能通过 in-place 操作报告给 autograd。

tensor.data

>>> a = torch.tensor([1,2,3.], requires_grad =True)
>>> out = a.sigmoid()
>>> c = out.data
>>> c.zero_()
tensor([ 0., 0., 0.])

>>> out                   #  out的数值被c.zero_()修改
tensor([ 0., 0., 0.])

>>> out.sum().backward()  #  反向传播
>>> a.grad                #  这个结果很严重的错误,因为out已经改变了
tensor([ 0., 0., 0.])

tensor.detach()

>>> a = torch.tensor([1,2,3.], requires_grad =True)
>>> out = a.sigmoid()
>>> c = out.detach()
>>> c.zero_()
tensor([ 0., 0., 0.])

>>> out                   #  out的值被c.zero_()修改 !!
tensor([ 0., 0., 0.])

>>> out.sum().backward()  #  需要原来out得值,但是已经被c.zero_()覆盖了,结果报错
RuntimeError: one of the variables needed for gradient
computation has been modified by an

6. 指定 GPU

终端

CUDA_VISIBLE_DEVICES=1 python my_script.py

代码文件

import os
os.environ["CUDA_VISIBLE_DEVICES"] = "2"
Table of Contents