新开一篇记录我在学习pytorch过程中遇到的tricks
- 性能part
- 功能part
-
- 1.nn.ModuleList
- 2.PyTorch中 tensor.detach() 和 tensor.data 的区别
- 3.cpu tensor, gpu tensor, ndarray之间的转换
- 4.pytorch .contiguous().view()
- 5.Python 字符串排序
- 6.pytorch model 的保存
- 7.PyTorch参数初始化和Finetune
性能part
1. torch.from_numpy() vs. torch.tensor() vs. torch.as_tensor()
torch.from_numpy() vs. torch.tensor()
from_numpy() automatically inherits input array dtype. On the other hand, torch.Tensor is an alias for torch.FloatTensor.
Therefore, if you pass int64 array to torch.Tensor, output tensor is float tensor and they wouldn’t share the storage. torch.from_numpy gives you torch.LongTensor as expected.
torch.tensor() vs. torch.as_tensor()
torch.tensor always copies the data. For example, torch.tensor(x) is equivalent to x.clone().detach().
torch.as_tensor always tries to avoid copies of the data. One of the cases where as_tensor avoids copying the data is if the original data is a numpy array.
2. torch.backends.cudnn.benchmark=True
在网络结构固定(不是动态变化的),网络的输入形状(包括 batch size,图片大小,输入的通道)不变的场景下,在 PyTorch 程序开头设置torch.backends.cudnn.benchmark=True,就可以大大提升卷积神经网络的运行速度。原理是:在每一个卷积层中测试 cuDNN 提供的所有卷积实现算法,然后选择最快的那个。
一般加在开头,如:
if args.use_gpu and torch.cuda.is_available():
device = torch.device(‘cuda’)
torch.backends.cudnn.benchmark = True
else:
device = torch.device(‘cpu’)
功能part
1.nn.ModuleList
首先说说 nn.ModuleList 这个类,你可以把任意 nn.Module 的子类 (比如 nn.Conv2d, nn.Linear 之类的) 加到这个 list 里面,方法和 Python 自带的 list 一样,无非是 extend,append 等操作。但不同于一般的 list,加入到 nn.ModuleList 里面的 module 是会自动注册到整个网络上的,同时 module 的 parameters 也会自动添加到整个网络中:
class net1(nn.Module):
def __init__(self):
super(net1, self).__init__()
self.linears = nn.ModuleList([nn.Linear(10,10) for i in range(2)])
def forward(self, x):
for m in self.linears:
x = m(x)
return x
net = net1()
print(net)
# net1(
# (modules): ModuleList(
# (0): Linear(in_features=10, out_features=10, bias=True)
# (1): Linear(in_features=10, out_features=10, bias=True)
# )
# )
for param in net.parameters():
print(type(param.data), param.size())
# <class 'torch.Tensor'> torch.Size([10, 10])
# <class 'torch.Tensor'> torch.Size([10])
# <class 'torch.Tensor'> torch.Size([10, 10])
# <class 'torch.Tensor'> torch.Size([10])
2.PyTorch中 tensor.detach() 和 tensor.data 的区别
PyTorch0.4中,.data 仍保留,但建议使用 .detach(), 区别在于 .data 返回和 x 的相同数据 tensor, 但不会加入到x的计算历史里,且require s_grad = False, 这样有些时候是不安全的, 因为 x.data 不能被 autograd 追踪求微分 。 .detach() 返回相同数据的 tensor ,且 requires_grad=False ,但能通过 in-place 操作报告给 autograd 在进行反向传播的时候.
与一个Variable(Tensor)的梯度有关的参数有两个:
grad_fn
:把一个tensor的grad_fn设置为None,则该节点前面的节点将不会再接收来自该节点后面的节点的梯度的反向传播。requires_grad
:把一个tensor的requires_grad设置为False,则对该节点后面的节点进行反向传播时不会对该节点求梯度。
举例:变量之间的关系是x -> m -> y,这里的叶子variable是x,但是这个时候对m进行了.detach_()操作,其实就是进行了两个操作:
- 将m的
grad_fn
的值设置为None,这样m就不会再与前一个节点x关联,这里的关系就会变成x, m -> y,此时的m就变成了叶子结点 - 然后会将m的
requires_grad
设置为False,这样对y进行backward()时就不会求m的梯度
detach()
和detach_()
很像,两个的区别就是detach_()是对本身的更改,detach()则是生成了一个新的variable
tensor复制可以使用clone()函数和detach()函数即可实现各种需求。
clone
clone()函数可以返回一个完全相同的tensor,新的tensor开辟新的内存,但是仍然留在计算图中。
detach
detach()函数可以返回一个完全相同的tensor,新的tensor开辟与旧的tensor共享内存,新的tensor会脱离计算图,不会牵扯梯度计算。此外,一些原地操作(in-place, such as resize_ / resize_as_ / set_ / transpose_) 在两者任意一个执行都会引发错误。
Operation | New/Shared memory | Still in computation graph |
---|---|---|
tensor.clone() | New | Yes |
tensor.detach() | Shared | No |
tensor.clone().detach() | New | No |
3.cpu tensor, gpu tensor, ndarray之间的转换
- CPU tensor转GPU tensor: