• 【读书笔记】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文件

  • 相关阅读:
    jsp——java服务页面
    会话管理——cookie和session技术
    [Java]如何为一个自定义类型的List排序。
    silverlight——获取控件相对位置
    C#操作xml文件
    [转载]Unicode中对中文字符的编码
    silverlight——多次异步调用的顺序执行
    内心需要跟我一起长大
    生活总是问题叠着问题,而任务就是一件问题一件问题的解决~
    真的该学点新的东西了。
  • 原文地址:https://www.cnblogs.com/Asumi/p/12466556.html
Copyright © 2020-2023  润新知