• Pytorch框架学习---(5)调整学习率、可视化操作


    本节简单总结Pytorch中用于学习率调整的函数,如何使用tensorboard可视化曲线、梯度、权重、特征图、卷积核,以及如何使用torchvision.utils.make_grid()制作网格图。【文中思维导图采用MindMaster软件

    1.学习率的调整

      Pytorch中封装了调整LR的函数,如下:

      它们都继承父类class _LRScheduler,需要复写函数def get_lr(self),该函数用于计算学习率并返回:

    class _LRScheduler(object):
        def __init__(self, optimizer, last_epoch=-1):
        ······
        def get_lr(self):
            raise NotImplementedError
    

      参数:

    • optimizer:优化器类实例

    • last_epoch:记录epoch数

    • base_lrs:记录初始学习率,该参数用于后续的学习率计算

      方法:

    • step():更新下一个epoch的学习率

    • get_lr():虚函数,计算下一个epoch学习率

    节省精力, 由于网上已经有人对这六个函数总结的很好,故在此引用,不再复写。

    2.tensorboard可视化工具

    (1)流程

    (2)如何记录可视化的数据?

      调用SummaryWriter类,代码如下:

    '''SummaryWriter类'''
    class SummaryWriter(object):
        def __init__(self, log_dir=None, comment='', purge_step=None, max_queue=10,
                     flush_secs=120, filename_suffix=''):
    
    # 参数如下:
          # log_dir:eventfile输出文件夹地址
          # comment:当不指定log_dir时,该参数为文件夹的后缀
          # filename_suffix:eventfile文件名的后缀
    
    '''实际运用时'''
    from torch.utils.tensorboard import SummaryWriter
    writer = SummaryWriter(log_dir='./a',comment="handw_exp",filename_suffix="test1")
    

    若不指定log_dir,则直接该项目下创建runs文件夹,可对照下图进行理解:

    各种记录数据的方法如下:

    ①scalar绘制曲线(单条、多条)

    '''一张图中,只能单条曲线'''
    def add_scalar(self, tag, scalar_value, global_step=None, walltime=None):
    
    # 参数:
          # tag:图像的标签名
          # scalar_value:要记录的标量,例如loss
          # global_step:x轴
    
    '''一张图中,可以多条曲线'''
    def add_scalars(self, main_tag, tag_scalar_dict, global_step=None, walltime=None):
    
    # 参数:
          # main_tag:总的标签名,用于曲线索引放置
          # tag_scalar_dict:要记录的标量,例如loss
          # global_step:x轴
    

    实战中,以 def add_scalars 为例

    iter_count = 0
    for epoch in range(Max_Epoch):
        ······
        for i, (inputs, labels) in enumerate(train_loader):
            iter_count += 1
            ······
            writer.add_scalars(main_tag="Loss", tag_scalar_dict={"Train": loss.item()}, global_step=iter_count)
            writer.add_scalars("Accuracy", {"Train": correct/total}, global_step=iter_count)
    
        if (epoch+1) % print_info_valid == 0:
            ······
            with torch.no_grad():
                for j,(inputs_valid,labels_valid) in enumerate(test_loader):
                ······
                writer.add_scalars("Loss", {"Valid": loss_info_valid/len(test_loader)}, iter_count)
                writer.add_scalars("Accuracy", {"Valid": correct_valid / total_valid}, iter_count)
                writer.flush()  # 及时刷新,否则无法同时观看到训练和验证
    writer.close()
    

     此时通过pycharm终端,输入 tensorboard --logdir=./a(event的地址),就会得到tensorboard的可视化网址,打开可以得到如下图:

    ②histogram直方图,查看权重、梯度,判断是否梯度消失或发散

    def add_histogram(self, tag, values, global_step=None, bins='tensorflow', walltime=None, max_bins=None):
    
    # 参数:
          # tag:图像的标签名
          # values:要统计的参数
          # global_step:y轴!!!!!!!!!!!!!(结合下图理解)
    

    实战中,代码参考如下:

        # 每一个epoch,记录各层权重、梯度
        for name, param in net.named_parameters():  # 返回网络的
            writer.add_histogram(name + '_grad', param.grad, epoch)
            writer.add_histogram(name + '_data', param, epoch)
    

    貌似横轴是大小,高度代表该数值下的个数???:

    ③记录图像(利用torchvision.utils中make_grid制作网格)

    torchvision.utils.make_grid()函数定义:

    def make_grid(tensor, nrow=8, padding=2,
                  normalize=False, range=None, scale_each=False, pad_value=0):
    
    # 参数:
          # tensor:必须是B*C*H*W形式
          # nrow:指定行数
          # padding:图像与图像之间的间隔多少个像素单位pad_value
          # normalize:是否将像素值标准化到(0~255)
          # range:指定标准化范围,先将像素值规范到该range,然后再进行(0~255)转换
          # scale_each:是否对单张图像进行range
          # pad_value:指定padding的大小(黑色0、白色255等等)
    

    实战中,代码参考如下:

    '''调用torchvision中make_grid 网格可视化图像'''
    import torchvision.utils as vutils
    img_batch,label_batch = next(iter(train_loader))  # 调用一个批次的图片
    img_grid = vutils.make_grid(img_batch, nrow=10,normalize=True)  # 变为 C*H*W 
    
    writer.add_image("make_grid",img_grid, global_step=0)
    writer.flush()
    

    '''当然也可以直接调用add_image或add_images'''
        def add_image(self, tag, img_tensor, global_step=None, walltime=None, dataformats='CHW'):
    # 参数:
          # 非常不方便,只能查看一个图像!!!!
          # 当像素值为【0,1】,则乘以255,缩放回【0,255】;若像素值不在【0,1】之间,默认是0~255范围内。
          # tag:图像的标签名
          # img_tensor:注意shape,可以是3HW、HW3、HW、1HW,但不能是四维的,即有batch!!!!!!!(可以通过add_images解决或torchvision.utils.make_grid())
          # global_step:x轴
    
        def add_images(self, tag, img_tensor, global_step=None, walltime=None, dataformats='NCHW'):  
    # 参数:
          # 无法指定行数!!!!!
          # tag:图像的标签名
          # img_tensor:注意shape,可以是NCHW or NHWC,但是,这里Channel在后续处理的时候只能为1或者3!!!!!
          # global_step:x轴
    
    

    ④利用make_grid可视化特征图

    (每次都要调出对应层,一个个输入,一个个输出,有点麻烦,即便调用for循环,代码也有点冗余性,下一节介绍的hook函数就可以在网络运行过程中,直接保存特征图)

    vlaid_img,_ = next(iter(test_loader))
    conv1 = net.cpu().feature[0]
    fmap1 = conv1(vlaid_img)  # 100*16*72*72
    fmap1_first = fmap1[0,:,:,:]
    fmap1_first.unsqueeze_(0).transpose_(0,1)  # 16*1*72*72
    
    fmap1_grid = vutils.make_grid(fmap1_first,4,normalize=True)
    writer.add_image("fmap", fmap1,global_step=0)
    

    从下面的特征图可以看出: 经过卷积核操作后,得到的各种特征图(提取边缘后、锐化后等等)。

    ⑤graph可视化模型计算图

        def add_graph(self, model, input_to_model=None, verbose=False):
    # 参数:
          # model:模型,必须是继承torch.nn.Module
          # input_to_model:模型的输入
          # verbose:是否打印计算图结构信息
    
    '''可视化模型计算图'''
    input_v = torch.rand((1,3,75,75))
    writer.add_graph(net, input_v)
    writer.flush()
    
  • 相关阅读:
    最佳路径搜索算法1
    积分方程的程序化解决方案
    lcov
    nvidia driver
    dependency
    scp ssh-server
    boost 安装 latest
    ubuntu 快捷键
    nvidia drive
    查询优化器 postgres
  • 原文地址:https://www.cnblogs.com/zpc1001/p/13322902.html
Copyright © 2020-2023  润新知