• Pytorch框架学习---(7)常见的4大归一化、模型保存与加载、模型微调、多GPU的使用


    本节简单总结Pytorch中常见的4大归一化、模型如何保存并加载、以及模型如何实现微调,pytorch中多GPU的使用。【文中思维导图采用MindMaster软件,Latex公式采用在线编码器

    1.Pytorch中封装的4大归一化(BN、LN、IN、GN)

    (1)为什么要采用Normalization?

      都是为了解决Internal Covariate Shift(ICS)问题,即数据分布出现异常而导致的网络训练困难。ICS问题在《Batch Normalization: Accelerating Deep Network Training by Reducing Internal Covariate Shift》中提到。

    (2)这4大归一化之间的异同点

    ① 相同点

      都是类似 (gamma imes frac{x- mean }{sqrt{var^{2}+ varepsilon } } + eta) 这样的形式,即“加减乘除”。

    ② 不同点

      均值mean和方差variance的求取方式不同,具体以下图为例:

    • (a)BN:对一个batch下的样本数的同一channel下的特征做归一化;
    • (b)LN:由于BN不适合变长的网络,例如RNN,所以LN对单独一个样本计算均值和方差,注意:gamma和beta是逐元素计算
    • (c)IN:由于BN不适合图像生成领域,即每一个图像都有自身的风格,不能够将一个batch中的样本混为一谈,,故对每一个样本逐通道归一化;
    • (d)GN:对于某些情况,batch_size较小,此时易知归一化值不准(类似无法代替全局),故GN对通道数(很多的通道)进行分组,用通道数去弥补小数据量问题。注意:gamma和beta是逐通道计算

    (3)具体使用

    ① BatchNorm

    '''BatchNorm基类'''
    class _BatchNorm(Module):
        def __init__(self, num_features, eps=1e-5, momentum=0.1, affine=True,
                     track_running_stats=True):
    
    # 参数:
          # num_features:一个样本的特征数量(或者是通道数量)
          # eps:分母修正项
          # momentum:指数加权平均 估计当前的mean/var!!!!!!!
          # affine:是否进行affine transform,即gamma、beta的scale and shift
          # track_running_stats:是训练状态 or 测试状态
    

    注意:测试状态,mean和var只计算当前batch,而训练状态,当前时刻的mean和var会受之前的batch影响,即下面的公式(momentum):

    [running\_mean= left ( 1- momentum ight )ast pre\_running\_mean+ momentumast mean\_t ]

    [running\_var= left ( 1- momentum ight )ast pre\_running\_var+ momentumast var\_t ]

      上面的momentum在之前的博客中有提及。

    ② LayerNorm

    class LayerNorm(Module):
        def __init__(self, normalized_shape, eps=1e-5, elementwise_affine=True):
    
    # 参数:
          # normalized_shape:该样本的特征形状
          # eps:分母修正项
          # elementwise_affine:是否要对每个元素进行affine transform操作
    

    注意:实例化LN时,要注意normalized_shape这一项,必须从size末尾写,例如:

            >>> input = torch.randn(20, 5, 4, 10)
            >>> m = nn.LayerNorm(input.size()[1:])
            >>> m = nn.LayerNorm([4, 10])
            >>> m = nn.LayerNorm([5,4, 10])
            >>> m = nn.LayerNorm([10])
            # 但不可以是:
            >>> m = nn.LayerNorm([5, 4])
    

    ③ InstanceNorm

    '''InstanceNorm基类'''
    class _InstanceNorm(_BatchNorm):
        def __init__(self, num_features, eps=1e-5, momentum=0.1, affine=False,
                     track_running_stats=False):
    
    # 参数:
          # num_features:一个样本的特征数量(或者是通道数量)
          # eps:分母修正项
          # momentum:指数加权平均 估计当前的mean/var!!!!!!!
          # affine:是否进行affine transform,即gamma、beta的scale and shift
          # track_running_stats:是训练状态 or 测试状态
    

    ④ GroupNorm

    class GroupNorm(Module):
        def __init__(self, num_groups, num_channels, eps=1e-5, affine=True):
    
    # 参数:
          # num_groups:分组数(必须能将通道数整除!!!!!!!!)
          # num_channels:通道数
          # eps:分母修正项
          # affine:是否进行affine transform,这里是对每个通道进行!!!!
    

    2.模型的保存与加载

    (1)pytorch提供的方法

      主要参数如下:(torch.save(obj, f))

    • obj:要保存的对象(模型,张量,参数等);

    • f:保存的路径。

    (2)模型的加载 torch.load

      主要参数如下:(torch.load(f, map_location=None))

    • f:读取路径;

    • map_location:决定该文件放在GPU上还是cpu位置上,当想要加载的模型是GPU上的,此时机子没有GPU,则可以将map_location='cpu',将该模型放置在cpu上。

    (3)两种保存模型的方式

    # 保存整个网络
    torch.save(net, PATH) 
    # 保存网络中的参数
    torch.save(net.state_dict(),PATH)
    
    #对应上面的保存方式:
    model_dict=torch.load(PATH)
    
    model_dict=model.load_state_dict(torch.load(PATH))
    

    (4)端点续训练(其实就是把优化器、模型的参数,以及epoch保存下来,方便后续继续训练)

    '''保存'''
    checkpoint = {"model_state_dict": net.state_dict(),
                  "optimizer_state_dict": optimizer.state_dict(),
                  "epoch": epoch}
    
    torch.save(checkpoint, path_checkpoint)
    
    '''加载'''
    checkpoint = torch.load(path_checkpoint)
    
    net.load_state_dict(checkpoint['model_state_dict'])
    
    optimizer.load_state_dict(checkpoint['optimizer_state_dict'])
    
    start_epoch = checkpoint['epoch']
    
    scheduler.last_epoch = start_epoch  # 用于更新优化器的学习率
    

    3.模型微调

      模型finetune感觉这里对python编程较高 ( 咳咳。。。——>_——>。。。只怪本人python编程目前还比较low ),其实主要要对字典、列表等高级操作要熟悉!!

      在这里本人就不献丑了,等后续用到finetune再来补充。大家可以先参考知乎Pytorch自由载入部分模型参数并冻结

    4.GPU的使用

    (1)to函数 (用于转换类型/设备)

      to函数可以用于tensor和module:

    device = torch.device("cuda:0" if torch.cuda.is_available() else "cpu")
    
    '''对于张量tensor'''
    # 张量不执行原位inplace操作,即必须赋值
    a = torch.ones((5, 5))
    a = a.to(torch.float64)
    a = a.to(device)
    
    '''对于模型moudle'''
    # 模型执行inplace
    net.to(device)
    

    (2)torch.cuda常用方法

      上图中设置GPU对应的os.environ.setdefault操作,可以有效防止多人使用GPU冲突问题,或者多程序在不同的GPU上跑的冲突,可用可见的GPU(逻辑GPU)与物理GPU的对应关系可以理解为:(对应图3os.environ粉色方块的操作)

    (3)多GPU运算的分发并行机制

    ① 发并行机制的流程图

      这里一般利用torch.nn.DataParallel操作,例如batch_size=16,我们利用4个GPU并行运算,分配给每个GPU的batch_size=4该机制主要流程为:

    ② torch.nn.DataParallel

    class DataParallel(Module):
        def __init__(self, module, device_ids=None, output_device=None, dim=0):
    
    # 参数:
          # module:需要处理的模型;
          # device_ids:可分法的GPU,默认分发到所有可见可用的GPU;(通过设置上述os.environ.setdefault操作,即可默认)
          # output_device:最后结果输出设备,默认主GPU
    

    (4)在多GPU上运行的模型,其pkl文件加载时的问题

      当我们加载多GPU模型参数,print load后的pkl文件,会发现较原始模型linear.0,多了一个module,即module.linear.0,因而我们需要取出module之后的参数,可以参考github上的代码:

    '''state_dict_load为OrderedDict形式,无法直接操作'''
    
        state_dict_load = torch.load(path, map_location="cpu")
        from collections import OrderedDict
        new_state_dict = OrderedDict()
        for k, v in state_dict_load.items():
            namekey = k[7:] if k.startswith('module.') else k  # 重新取出module后层信息,作为新的key
            new_state_dict[namekey] = v
    
        net.load_state_dict(new_state_dict)
    
  • 相关阅读:
    使用S7netplus存取西门子PLC字符串数据
    学习使用Nginx配置服务器
    Bootstrap4设置footer固定在底部
    ASP.NET Core MVC项目Razor页面实时编译
    在Asp.NET Core MVC项目中通过Libman安装Bootstrap
    在Asp.Net Core Web项目中使用不同的环境
    C#简单使用System.Threading.Timer
    在ASP.Net Core Web API中使用Swagger进行版本控制
    ASP.Net Core Web API解决跨域问题
    LeetCode刷题-- 搜索插入位置
  • 原文地址:https://www.cnblogs.com/zpc1001/p/13344215.html
Copyright © 2020-2023  润新知