Tensor
tensor.size()返回torch.Size对象,它是tuple的子类,但其使用方式与tuple略有区别。
tensor.shape等价于tensor.size()
需要注意的是,t.Tensor(*sizes)创建时,系统不会马上分配空间,只会计算剩余的内存是否足够使用,使用到tensor时才会分配,而其他操作都是在创建完tensor后马上进行空间分配。
tensor.view:可以调整tensor的形状,但必须保证总数一致。不会修改自身的数据,共享内存,即更改其中一个,另外一个也会跟着改变。
squeeze和unsqueeze:添加或减少某一维度。
resize:也可用来调整size,但可修改尺寸,如b.resize_(1, 3)
CPU tensor与GPU tensor之间的互相转换通过tensor.cuda和tensor.cpu的方法实现。
pytorch的线性函数主要封装了Blas和Lapack,其用法和接口都与之类似。
当遇到Tensor不支持的操作时,可先转成Numpy数组,处理后再转回tensor,其转换开销很小。
tensor分为头信息区(Tensor)和存储区(Storage)
在科学计算中应当避免使用Python原生的for循环,尽量使用向量化的数值计算,有近10倍的速度差。
因此在平时写代码时,就应养成向量化的思维习惯。
Variable
torch.autograd:自动求导引擎,它能够根据输入和前向传播过程自动构建计算图,并执行反向传播。
其核心数据结构是Variable。它封装了tensor,并记录对tensor的操作记录用来构建计算图。主要包含三个属性:
- data:保存variable所包含的tensor
- grad:对应的梯度,grad也是variable,而非tensor
- grad_fn:指向一个Function,记录variable的操作历史,用来构建计算图。如果某个变量是由用户创建的,则它为叶子节点,对应grad_fn等于None。
Variable的构造函数需要传入tensor,同时有两个可选参数。
- requires_grad:是否需要对该variable进行求导。
- volatile:为True时,构建在该variable之上的图都不会求导,专为推理阶段设计。
Variable支持大部分tensor支持的函数,但其不支持部分inplace函数,因为这些函数会修改tensor自身,而在反向传播中,variable需要缓存原来的tensor来计算梯度。
variable.backward(grad_variables=None, retain_graph=None, create_graph=None)主要有如下参数:
- grad_variables:形状与variable一致,相对于链式法则Zx = Zy * Yz中的Zy
- retain_graph:缓存中间结果
- create_graph:对反向传播过程再次构建计算图
神经网络工具箱nn
torch.nn的核心数据结构是Module,它是一个抽象的概念,既可以表示神经网络中的某个层(layer),也可以表示一个包含很多层的神经网络。在实际使用中,最常见的做法是继承nn.Module,撰写自己的网络层。如y = Wx + b
import torch as t
from torch import nn
from torch.autograd import Variable as V
class Linear(nn.Module):
def __init__(self, in_features, out_features):
super(Linear, self).__init__() # 等价于nn.Module.__init__
self.w = nn.Parameter(t.randn(in_features, out_features)) # 定义参数,为一种Variable
self.b = nn.Parameter(t.randn(out_features))
def forward(self, x):
x = x.mm(self.w)
return x + self.b.expand_as(x)
layer = Linear(4, 3)
input = V(t.randn(2, 4))
output = layer(input) # 会调用forward
print(output)
官方文档有图像相关层、激活函数、循环神经网络层、Embedding层、损失函数、
优化器:所有方法都继承基类optim.Optimizer,并实现了自己的优化步骤。
nn.functional:nn.Module实现的layers是一个特殊的类,都是由class Layer(n.Module)定义,会自动提取可学习的参数;而nn.functional中的函数更像是纯函数,由def function(input)定义。
如果模型有可学习的参数,最好用nn.Module,否则既可以使用nn.functional也可以使用nn.Module,二者在性能上没有太大差异,具体的使用方式取决于个人喜好。由于激活函数、池化等层没有可学习参数,可以使用对应的functional函数替代,而卷积、全连接等具有可学习参数的网络建议使用nn.Module。
from torch.nn import functional as F
class Net(nn.Module):
def __init__(self):
super(Net, self).__init__()
self.conv1 = nn.Conv2d(3, 6, 5)
self.conv2 = nn.Conv2d(6, 16, 5)
self.fc1 = nn.Linear(16*5*5, 120)
self.fc2 = nn.Linear(120, 84)
self.fc3 = nn.Linear(84, 10)
def forward(self, x):
x = F.pool(F.relu(self.conv1(x)), 2)
x = F.pool(F.relu(self.conv2(x)), 2)
x = x.view(-1, 16*5*5)
x = F.relu(self.fc1(x))
x = F.relu(self.fc2(x))
x = self.fc3(x)
return x
初始化策略
nn.Module的模块参数都采取了较合理的初始化 策略,因此一般不用我们考虑。当然,我们也可以用自定义初始化代替系统的默认初始化。当我们使用Parameter时,自定义初始化尤为重要。nn.init模块专门为初始化设计。
在PyTorch中保存模型十分简单,所有的Module对象都具有state_dict()函数,返回当前Module所有的状态数据。将这些状态数据保存后,下次使用模型时即可利用model.load_state_dict()函数将状态加载进来。优化器(optimizer)也有类似的机制,不过一般并不需要保存优化器的运行状态。
t.save(net.state_dict(), 'net.pth')
net2 = Net()
net2.load_state_dict(t.load('net.pth'))
将Module放在GPU上运行也十分简单,只需以下两步:
- model = model.cuda():将模型的所有参数转存到GPU
- input.cuda():将输入数据放置到GPU上
至于如何在多个GPU上并行计算,PyTorch也提供了两个函数,可实现简单高效的并行GPU计算。
# 方法 1
new_net = nn.DataParallel(net, device_ids=[0,1])
output = new_net(input)
# 方法 2
output = nn.parallel.data_parallel(net, input, device_ids=[0,1])
DataParallel并行的方式,是将输入一个batch的数据均分成多份,分布送到对应的GPU进行计算,然后将各个GPU得到的梯度相加。与Module相关的所有数据也会以浅复制的方式复制多份。
可视化工具
使用tensorboard_logger进行训练损失的可视化。
$ pip install tensorboard_logger
使用visdom,是facebook专门为PyTorch开发的一款可视化工具。
$ pip install visdom
来源:https://blog.csdn.net/QFire/article/details/99302617