【读书笔记】PyTorch

复习了下pytorch。


 

自动求导机制

从后向排除子图

  • 每个变量有两个标志:requires_gradvolatile
  • requires_grad
    • 如果有一个单一的输入操作需要梯度,它的输出也需要梯度,反之亦然。
    • 如果其中所有的变量都不需要梯度进行,后向计算不会执行
    • 如果想冻结部分模型,或者不会使用某些参数的梯度。
  • volatile
    • 纯粹的inference模式下推荐使用
    • 一个操作甚至只有有一个 volatile的输入,输出就是volatile
    • 使用volatile不需要更改模型参数的任何设置来用于inference

自动求导如何编码历史信息

  • 每个变量都有一个.creator属性,指向把它作为输出的函数。
  • 由Function对象作为节点组成的DAG的入口点,它们之间的引用是图的边
  • 每执行一个操作,它的forward()方法被调用,它的Variable的创建者被设置为这个Function。

Variable上的In-place操作

  • 大多数情况下不使用它们。原因如下:
    • 覆盖梯度计算所需的值
    • 每个in-place操作实际上需要实现重写计算图

In-place正确性检查

  • 每个变量保留有version counter,每次在操作中使用时会递增。
  • 一旦访问self.saved_tensors,它将被检查,大于保存值则错误

 

CUDA语义

 cuda

  • torch.cuda会记录当前选择的GPU,并且分配所有的CUDA张量将在上面创建。
  • 张量一旦被分配,可以对其进行操作,而不考虑所选择的设备。结果存在设备上。
  • 默认情况下不支持跨GPU操作。除非启用对等存储器访问,否则对分布不同设备上的张量任何启动操作的尝试都会引发错误

最佳实践

  • 使用固定的内存缓冲区
    • CPU张量和存储开放了一个pin_memory()方法,它返回该对象的副本,而它的数据放在固定区域中
    • 一旦固定了张量或存储,就可以使用异步的GPU副本。只需要传递一个额外的async = True到cuda()的调用。p.s 数据传输和计算重叠
    • 通过将pin_memory=True传递给构造函数,可以使DataLoader将batch返回到固定内存中
  • 使用 nn.DataParallel 替代 multiprocessing
    • 大多数涉及批量输入和多个GPU的情况应默认使用DataParallel来使用多个GPU
    • 调用multiprocessing来利用CUDA模型存在重要的注意事项

       

扩展PyTorch

扩展torch.autograd 

  • 想要添加一个新的operation到autograd的话,需要继承class function
  • 每个新的operation(function)需要实现三个方法:
    • init(optional):如果operation包含非Variable参数,就传入。
    • forward():在里面编写执行此operation的代码。forward()的参数只能是variable
    • backward():梯度计算公式。参数的个数和forward返回值个数一样,每个参数代表传回到此operation的梯度。

扩展 torch.nn

  • nn有两种接口-modules和他们的functional版本。在扩展layer的时候,使用modules。如果不需要参数的话,那么建议使用functional
  • 增加一个operation的funtional版本
  • 增加一个module。添加一个新的module需要实现一个function的两个方法:
    • init(optional):输入参数。同时初始化parameters和buffers
    • forward():实例化一个执行operation的function.

 

多进程最佳实践

多进程

  • torch.multiprocessing 是Pythonmultiprocessing 的替代品。
  • 当Variable发送到另一个进程时,Variable.dataVariable.grad.data都将被共享。

共享CUDA张量

  • 仅在Python 3中使用spawn或forkserver启动方法才支持在进程之间共享CUDA张量。

最佳实践

  • 避免死锁和抵制死锁
    • 最常见的死锁原因是后台线程。如果有任何线程持有锁或导入模块,并且fork被调用,会死锁和失败
    • multiprocessing.Queue可能也会引起上述问题。出现问题时尝试使用multiprocessing.queues.SimpleQueue
  • 重用经过队列的缓冲区
    • 每次将Tensor放入multiprocessing.Queue必须将它移动到共享内存中
  • 异步多进程训练
    • 使用torch.multiprocessing,可以异步地训练模型,参数可以一直共享,也可以定期同步。
    • 我们建议使用multiprocessing.Queue来在进程之间传递各种PyTorch对象。

 

序列化语义

保存模型的推荐方法

  • 只保存和加载模型参数(推荐)
torch.save(the_model.state_dict().PATH)

 

the_model = TheModelClass(*args,**kwargs)

the_model.load_state_dict(torch.load(PATH))
  • 保存和加载整个模型
torch.save(the_model, PATH)

 

the_model = torch.load(PATH)
  • 但是这种情况,序列化的数据被绑定到特定类和固定目录结构,所以可能造成break

 


CODE

 

 1 import torchvision
 2 from torch.autograd import Variable
 3 import torch
 4 
 5 #requires_grad
 6 x = Variable(torch.randn(5, 5))
 7 y = Variable(torch.randn(5, 5))
 8 z = Variable(torch.randn(5, 5),requires_grad=True)
 9 a = x + y
10 print(a.requires_grad)  #False
11 b = a + z
12 print(b.requires_grad)  #True
13 
14 
15 #volatile
16 regular_input = Variable(torch.randn(5,5))
17 volaile_input = Variable(torch.randn(5,5),volatile = True)
18 model = torchvision.models.resnet18(pretrained = True)
19 print(model(regular_input).requires_grad)       #True
20 print(model(volaile_input).requires_grad)       #False
21 print(model(volaile_input).volatile)            #True
22 print(model(volaile_input).requires_grad)       #False
23 
24 #cuda
25 x = torch.cuda.FloatTensor(1)
26 # x.get_device() == 0
27 y = torch.FloatTensor(1).cuda()
28 # y.get_device() == 0
29 
30 with torch.cuda.device(1):
31     #当前分配给GPU1
32     a = torch.cuda.FloatTensor(1)
33 
34     b = torch.FloatTensor(1).cuda()
35 
36     c = a + b
37     # c.get_device() == 1
38     z = x + y
39     # z.get_device() == 0
40     d = torch.randn(2).cuda(2)
41     #d.get_device() == 2

 


 

常用包

torch

torch:张量相关的运算,包括创建,索引,切片,连接,换位,随机抽样,序列化,并行化,数学操作等

torch.nn:包含搭建网络层的模块和一系列的损失函数(卷积,池化,BN批处理,Linear , Dropout等)

torch.nn.functional:激活函数(线性,Dropout,,relu,leaky_relu,sigmoid等)

torch.autograd:提供了类和函数用来对任意标量函数进行求导

torch.optim:各种优化算法(SGD,Adam,Adagrad等)

torch.nn.init:更改模块参数初始化方式

torch.utils.data:加载数据

torch.Tensor:一种包含单一数据类型元素的多维矩阵

torch.Storage:一个单一数据类型的连续一维数组

 

torchvision

torchvision.datasets: 中包含了以下数据集

  • MNIST
  • COCO
  • LSUN Classification
  • ImageFolder
  • Imagenet-12
  • CIFAR10 and CIFAR100
  • STL10

torchvision.models:包含以下模型结构

  • AlexNet
  • VGG
  • ResNet
  • SqueezeNet
  • DenseNet


torchvision.transforms:PIL.Image相关
torchvision.utils:将给定的Tensor保存成image文件

posted @ 2020-03-11 23:51  甜酒果。  阅读(395)  评论(0编辑  收藏  举报