一、visdom可视化工具

安装:pip install visdom

启动:命令行直接运行visdom

打开WEB:在浏览器使用http://localhost:8097打开visdom界面

二、使用visdom

  1. # 导入Visdom类
  2. from visdom import Visdom
  3. # 定义一个env叫Mnist的board,如果不指定,则默认归于main
  4. viz = Visdom(env='Mnist')
  5.  
  6. # 在window Accuracy中画train acc和test acc,x坐标都是epoch
  7. viz.line(Y=np.column_stack((acc, test_acc)),
  8. X=np.column_stack((epoch, epoch)),
  9. win='Accuracy',
  10. update='append',
  11. opts=dict(markers=False, legend=['Acc', 'Test Acc']))
  12. # 在window Loss中画train loss和test loss,x坐标都是epoch
  13. viz.line(Y=np.column_stack((loss.cpu().item(), test_loss.cpu().item())),
  14. X=np.column_stack((epoch, epoch)),
  15. win='Loss',
  16. update='append',
  17. opts=dict(markers=False, legend=['Loss', 'Test Loss']))

三、使用正则化

正则化也叫权重衰减(Weight Decay)

L1和L2正则化可以参考:https://blog.csdn.net/red_stone1/article/details/80755144

在代码中,我们只需要在优化器中使用weight_decay参数就可以启用L2正则化

  1. # 选择一个优化器,指定需要优化的参数,学习率,以及正则化参数
  2. optimizer = torch.optim.SGD(net.parameters(), lr=learning_rate, weight_decay=0.01)

由于在Pytorch中没有纳入L1正则化,我们可以通过手工实现:

  1. # 正则化超参数lambda
  2. lambd = 0.01
  3. # 所有参数的绝对值的和
  4. regularization_loss = 0
  5.  
  6. for param in model.parameters():
  7.   regularization_loss += torch.sum(torch.abs(param))
  8.  
  9. # 自己手动在loss函数后添加L1正则项 lambda * sum(abs)
  10. loss = F.cross_entropy(z, target) + lambd * regularization_loss
  11. optimizer.zero_grad()
  12. loss.backward()

四、使用Momentum动量

使用Momentum,即在使用SGD时指定momentum参数,如果不指定,默认为0,即不开启动量优化模式。

  1. # 选择一个优化器,指定需要优化的参数,学习率,以及正则化参数,是否使用momentum
  2. optimizer = torch.optim.SGD(net.parameters(), lr=learning_rate, momentum=0.9, weight_decay=0.01)

使用Adam时,由于Adam包含了Monmentum,所以他自己指定了Momentum参数的大小,无需我们指定。

五、学习率衰减 Learning rate decay

当学习率太小时,梯度下降很慢。当学习率太大时,可以在某个狭窄区间震荡,难以收敛。

学习率衰减就是为了解决学习率多大这种情况。

当我们在训练一个模型时,发现Loss在某个时间不发生变化(在一个平坦区),则我们要考虑是否是在一个狭窄区间震荡,导致的难以收敛。

我们在pytorch中可以使用ReducelROnPlateau(optimizer,'min')来监控loss的值:

  1. from torch.optim.lr_scheduler import ReduceLROnPlateau
  2.  
  3. # 选择一个优化器,指定需要优化的参数,学习率,以及正则化参数,是否使用momentum
  4. optimizer = torch.optim.SGD(net.parameters(), lr=learning_rate, momentum=0.9, weight_decay=0.01)
  5.  
  6. # 使用一个高原监控器,将optimizer交给他管理,LR衰减参数默认0.1即一次缩小10倍,patience是监控10次loss看是否变化
  7. scheduler = ReduceLROnPlateau(optimizer, mode='min', factor=0.1, patience=10)
  8.  
  9. # 后面的optimizer.step()使用scheduler.step(loss)来代替,每次step都会监控一下loss
  10. # 当loss在10次(可以设置)都未变化,则会使LR衰减一定的比例

另外,除了上述使用ReducelROnPlateau,还可以使用更为粗暴的StepLR函数,我们可以直接指定在多少step后下降一次LR的值:

  1. from torch.optim.lr_scheduler import StepLR
  2.  
  3. # 选择一个优化器,指定需要优化的参数,学习率,以及正则化参数,是否使用momentum
  4. optimizer = torch.optim.SGD(net.parameters(), lr=learning_rate, momentum=0.9, weight_decay=0.01)
  5.  
  6. # 使用StepLR,指定step_size即每多少步衰减一次,gamma为衰减率,0.1代表除以10
  7. scheduler = StepLR(optimizer, step_size = 10000, gamma=0.1)
  8.  
  9. # 后面的optimizer.step()使用scheduler.step()

六、在全连接层使用batchnorm

  1. # -*- coding:utf-8 -*-
  2. __author__ = 'Leo.Z'
  3.  
  4. import torch
  5. from visdom import Visdom
  6. import numpy as np
  7.  
  8. import torch.nn.functional as F
  9. from torch.nn import Module, Sequential, Linear, LeakyReLU, BatchNorm1d
  10. from torchvision import datasets, transforms
  11. from torch.utils.data import DataLoader
  12.  
  13. batch_size = 200
  14. learning_rate = 0.001
  15. epochs = 100
  16.  
  17. train_data = datasets.MNIST('../data', train=True, download=True,
  18. transform=transforms.Compose([
  19. transforms.ToTensor(),
  20. transforms.Normalize((0.1307,), (0.3081,))
  21. ]))
  22.  
  23. test_data = datasets.MNIST('../data', train=False,
  24. transform=transforms.Compose([
  25. transforms.ToTensor(),
  26. transforms.Normalize((0.1307,), (0.3081,))
  27. ]))
  28.  
  29. train_db, val_db = torch.utils.data.random_split(train_data, [50000, 10000])
  30.  
  31. train_loader = DataLoader(train_db,
  32. batch_size=100, shuffle=True)
  33. val_loader = DataLoader(val_db,
  34. batch_size=10000, shuffle=True)
  35. test_loader = DataLoader(test_data,
  36. batch_size=10000, shuffle=True)
  37.  
  38. # 网络结构
  39. class MLP(Module):
  40. def __init__(self):
  41. super(MLP, self).__init__()
  42.  
  43. self.model = Sequential(
  44. Linear(784, 200),
  45. #===================== BN-start ======================
  46. # 这里对第一层全连接层使用BN1d,在多个样本上对每一个神经元做归一化
  47. BatchNorm1d(200, eps=1e-8),
  48. # ===================== BN-end =======================
  49. LeakyReLU(inplace=True),
  50. Linear(200, 200),
  51. #===================== BN-start ======================
  52. # 这里对第二层全连接层使用BN1d,在多个样本上对每一个神经元做归一化
  53. BatchNorm1d(200, eps=1e-8),
  54. # ===================== BN-end =======================
  55. LeakyReLU(inplace=True),
  56. Linear(200, 10),
  57. LeakyReLU(inplace=True)
  58. )
  59.  
  60. def forward(self, x):
  61. x = self.model(x)
  62. return x
  63.  
  64. # 定义一个env叫Mnist的board,如果不指定,则默认归于main
  65. viz = Visdom(env='TestBN')
  66.  
  67. # 定义GPU设备
  68. device = torch.device('cuda')
  69. # model放到GPU
  70. net = MLP().to(device)
  71.  
  72. # 选择一个优化器,指定需要优化的参数,学习率,以及正则化参数,是否使用momentum
  73. optimizer = torch.optim.SGD(net.parameters(), lr=learning_rate, momentum=0.9, weight_decay=0.01)
  74.  
  75. for idx, (val_data, val_target) in enumerate(val_loader):
  76. val_data = val_data.view(-1, 28 * 28)
  77. val_data, val_target = val_data.to(device), val_target.to(device)
  78.  
  79. for epoch in range(epochs):
  80.  
  81. for batch_idx, (data, target) in enumerate(train_loader):
  82. # data转换维度为[200,784],target的维度为[200]
  83. data = data.view(-1, 28 * 28)
  84. # 将data和target放到GPU
  85. data, target = data.to(device), target.to(device)
  86. # data为输入,net()直接执行forward
  87. # 跑一次网络,得到z,维度为[200,10],200是batch_size,10是类别
  88. # 由于net在GPU,data也在GPU,计算出的z就在GPU
  89. # 调用net(data)的时候相当于调用Module类的__call__方法
  90. z = net(data).to(device)
  91.  
  92. # 将loss放到GPU
  93. loss = F.cross_entropy(z, target).to(device)
  94. # 每次迭代前将梯度置0
  95. optimizer.zero_grad()
  96. # 反向传播,计算梯度
  97. loss.backward()
  98. # 相当于执行w = w - dw,也就是更新权值
  99. optimizer.step()
  100.  
  101. ### 每一轮epoch,以下代码是使用分割出的val dataset来做测试
  102. # 先计算在train dataset上的准确率
  103. eq_mat = torch.eq(z.argmax(dim=1), target)
  104. acc = torch.sum(eq_mat).float().item() / eq_mat.size()[0]
  105. print('Loss:', loss)
  106. print('Accuracy:', acc)
  107.  
  108. # 用val跑一遍网络,并计算在val dataset上的准确率
  109. # ===================== BN-start =====================
  110. # 跑网络之前,先将BN层设置为validation模式
  111. # BN层会自动使用在训练时累计的running_mean和running_var
  112. net.eval()
  113. #net.model[1].eval()
  114. #net.model[4].eval()
  115. # ===================== BN-end =======================
  116.  
  117. val_z = net(val_data).to(device)
  118. val_loss = F.cross_entropy(val_z, val_target).to(device)
  119. val_eq_mat = torch.eq(val_z.argmax(dim=1), val_target)
  120. val_acc = torch.sum(val_eq_mat).float().item() / val_eq_mat.size()[0]
  121. print('Val Loss:', val_loss)
  122. print('Val Accuracy:', val_acc)
  123.  
  124. # 将loss和acc画到visdom中
  125. viz.line(Y=np.column_stack((acc, val_acc)),
  126. X=np.column_stack((epoch, epoch)),
  127. win='Accuracy',
  128. update='append',
  129. opts=dict(markers=False, legend=['Acc', 'Val Acc']))
  130. # 将val loss和val acc画到visdom中
  131. viz.line(Y=np.column_stack((loss.cpu().item(), val_loss.cpu().item())),
  132. X=np.column_stack((epoch, epoch)),
  133. win='Loss',
  134. update='append',
  135. opts=dict(markers=False, legend=['Loss', 'Val Loss']))

使用BN时的ACC和LOSS:

未使用BN时的ACC和LOSS:

从上述结果可以看出,使用BN后,收敛速度变快。

[深度学习] pytorch学习笔记(3)(visdom可视化、正则化、动量、学习率衰减、BN)的更多相关文章

  1. [深度学习] Pytorch学习(一)—— torch tensor

    [深度学习] Pytorch学习(一)-- torch tensor 学习笔记 . 记录 分享 . 学习的代码环境:python3.6 torch1.3 vscode+jupyter扩展 #%% im ...

  2. [深度学习] pytorch学习笔记(2)(梯度、梯度下降、凸函数、鞍点、激活函数、Loss函数、交叉熵、Mnist分类实现、GPU)

    一.梯度 导数是对某个自变量求导,得到一个标量. 偏微分是在多元函数中对某一个自变量求偏导(将其他自变量看成常数). 梯度指对所有自变量分别求偏导,然后组合成一个向量,所以梯度是向量,有方向和大小. ...

  3. [深度学习] pytorch学习笔记(4)(Module类、实现Flatten类、Module类作用、数据增强)

    一.继承nn.Module类并自定义层 我们要利用pytorch提供的很多便利的方法,则需要将很多自定义操作封装成nn.Module类. 首先,简单实现一个Mylinear类: from torch ...

  4. [深度学习] pytorch学习笔记(1)(数据类型、基础使用、自动求导、矩阵操作、维度变换、广播、拼接拆分、基本运算、范数、argmax、矩阵比较、where、gather)

    一.Pytorch安装 安装cuda和cudnn,例如cuda10,cudnn7.5 官网下载torch:https://pytorch.org/ 选择下载相应版本的torch 和torchvisio ...

  5. [深度学习] Pytorch学习(二)—— torch.nn 实践:训练分类器(含多GPU训练CPU加载预测的使用方法)

    Learn From: Pytroch 官方Tutorials Pytorch 官方文档 环境:python3.6 CUDA10 pytorch1.3 vscode+jupyter扩展 #%% #%% ...

  6. 【PyTorch深度学习】学习笔记之PyTorch与深度学习

    第1章 PyTorch与深度学习 深度学习的应用 接近人类水平的图像分类 接近人类水平的语音识别 机器翻译 自动驾驶汽车 Siri.Google语音和Alexa在最近几年更加准确 日本农民的黄瓜智能分 ...

  7. pytorch visdom可视化工具学习—1—详细使用-1—基本使用函数

    使用教程,参考: https://github.com/facebookresearch/visdom https://www.pytorchtutorial.com/using-visdom-for ...

  8. Deep Learning(深度学习)学习笔记整理系列之(三)

    Deep Learning(深度学习)学习笔记整理系列 zouxy09@qq.com http://blog.csdn.net/zouxy09 作者:Zouxy version 1.0 2013-04 ...

  9. CS231n 斯坦福深度视觉识别课 学习笔记(完结)

    课程地址 第1章 CS231n课程介绍 ---1.1 计算机视觉概述 这门课的主要内容是计算机视觉.它是一门需要涉及很多其他科目知识的学科. 视觉数据占据了互联网的绝大多数,但是它们很难利用. --- ...

随机推荐

  1. shell作业01

    1.判断/etc/inittab文件是否大于100行,如果大于,则显示”/etc/inittab is a big file.”否者显示”/etc/inittab is a small file.” ...

  2. [转帖]看完这篇文章,我奶奶都懂了https的原理

    看完这篇文章,我奶奶都懂了https的原理 http://www.17coding.info/article/22 非对称算法 以及 CA证书 公钥 核心是 大的质数不一分解 还有 就是 椭圆曲线算法 ...

  3. Spring 最常用的 7 大类注解,史上最强整理!

    随着技术的更新迭代,Java5.0开始支持注解.而作为java中的领军框架spring,自从更新了2.5版本之后也开始慢慢舍弃xml配置,更多使用注解来控制spring框架. 而spring的的注解那 ...

  4. Intellij IDEA中使用Debug调试

    转自:https://blog.csdn.net/zj420964597/article/details/78662299只是为了方便学习技术,少走弯路,如果有异议,请留言,及时处理!!!

  5. [Nest] 05.nest之数据库

    数据库 Nest 与数据库无关,允许您轻松地与任何 SQL 或 NoSQL 数据库集成.根据您的偏好,您有许多可用的选项.一般来说,将 Nest 连接到数据库只需为数据库加载一个适当的 Node.js ...

  6. python:split()函数

    描述 Python 内置函数 指定分隔符对字符串进行切片 如果参数 num 有指定值,则仅分隔 num 个子字符串 返回分割后的字符串列表. 语法 str.split(str="" ...

  7. STM32F10xxx_启动模式

    目录 STM32F10xxx_启动模式 更新记录 启动配置 参考: STM32F10xxx_启动模式 更新记录 version status description date author V1.0 ...

  8. python 安装时,为何pip install不是内部或者外部命令错误解决办法

    新安装的python 环境,第一次pip  install 却报不是内部或者外部命令错误 首先检查一下环境变量,可能时你没有设置环境变量 再说一遍,安装python环境时,记得出了python.exe ...

  9. kubeDNS workflow(service registration and discovery)

    Service discovery In k8s, we usually will more than make an application instance, and also the corre ...

  10. python-装饰(高阶函数)

    python-装饰(高阶函数) 高阶函数 1.把一个函数名当做实参传给另外一个函数(在不修改被装饰函数源代码) 2.返回值 中包含函数名 高阶函数实现1的功能 def bar(): print(&qu ...