ICode9

精准搜索请尝试: 精确搜索
首页 > 其他分享> 文章详细

3. PyTorch主要组成模块(3)

2022-08-22 11:31:49  阅读:282  来源: 互联网

标签:weight float 默认 PyTorch lr 模块 1e 参数 组成


3.8 Pytorch优化器()

  优化器是根据网络反向传播的梯度信息来更新网络的参数,以起到降低loss函数计算值,使得模型输出更加接近真实标签。

3.9.1 Pytorch提供的优化器

  • torch.optim.ASGD(params, lr=0.01, lambd=0.0001, alpha=0.75, t0=1000000.0, weight_decay=0)

  • 功能:实现平均随机梯度下降算法。

     参数:

    • params (iterable) – 待优化参数的iterable或者是定义了参数组的dict
    • lr (float, 可选) – 学习率(默认:1e-2)
    • lambd (float, 可选) – 衰减项(默认:1e-4)
    • alpha (float, 可选) – eta更新的指数(默认:0.75)
    • t0 (float, 可选) – 指明在哪一次开始平均化(默认:1e6)
    • weight_decay (float, 可选) – 权重衰减(L2惩罚)(默认: 0) -- 预防过拟合(沐神)
  • torch.optim.Adagrad(params, lr=0.01, lr_decay=0, weight_decay=0)

  功能:实现Adagrad算法,Adagrad适用于数据稀疏或者分布不平衡的数据集

  参数:

    • params (iterable) – 待优化参数的iterable或者是定义了参数组的dict
    • lr (float, 可选) – 学习率(默认: 1e-2)
    • lr_decay (float, 可选) – 学习率衰减(默认: 0)
    • weight_decay (float, 可选) – 权重衰减(L2惩罚)(默认: 0)

  优点:它可以自动调节学习率,不需要人为调节.

  缺点:仍依赖于人工设置一个全局学习率,随着迭代次数增多,学习率会越来越小,最终会趋近于0

  • torch.optim.Adadelta(params, lr=1.0, rho=0.9, eps=1e-06, weight_decay=0)

  功能:实现Adadelta算法,是Adagard的改进版,对学习率进行自适应约束,但是进行了计算上的简化,加速效果不错,训练速度快

  参数:

    • params (iterable) – 待优化参数的iterable或者是定义了参数组的dict
    • rho (float, 可选) – 用于计算平方梯度的运行平均值的系数(默认:0.9)
    • eps (float, 可选) – 为了增加数值计算的稳定性而加到分母里的项(默认:1e-6)
    • lr (float, 可选) – 在delta被应用到参数更新之前对它缩放的系数(默认:1.0)
    • weight_decay (float, 可选) – 权重衰减(L2惩罚)(默认: 0)

  优点:避免在训练后期,学习率过小;初期和中期,加速效果不错,训练速度快

  缺点:还是需要自己手动指定初始学习率,初始梯度很大的话,会导致整个训练过程的学习率一直很小,在模型训练的后期,模型会反复地在局部最小值附近抖动,从而导致学习时间变长

  • torch.optim.Adam(params, lr=0.001, betas=(0.9, 0.999), eps=1e-08, weight_decay=0)

  功能:实现Adam算法。

  原理:将Momentum算法和RMSProp算法结合起来使用的一种算法,既用动量来累积梯度,又使得收敛速度更快同时使得波动的幅度更小,并进行了偏差修正

  参数:

    • params (iterable) – 待优化参数的iterable或者是定义了参数组的dict
    • lr (float, 可选) – 学习率(默认:1e-3)
    • betas (Tuple[floatfloat], 可选) – 用于计算梯度以及梯度平方的运行平均值的系数(默认:0.9,0.999)
    • eps (float, 可选) – 为了增加数值计算的稳定性而加到分母里的项(默认:1e-8)
    • weight_decay (float, 可选) – 权重衰减(L2惩罚)(默认: 0)

  优点:

    1、对目标函数没有平稳要求,即loss function可以随着时间变化

    2、参数的更新不受梯度的伸缩变换影响

    3、更新步长和梯度大小无关,只和alpha、beta_1、beta_2有关系。并且由它们决定步长的理论上限

    4、更新的步长能够被限制在大致的范围内(初始学习率)

    5、能较好的处理噪音样本,能天然地实现步长退火过程(自动调整学习率)

    6、很适合应用于大规模的数据及参数的场景、不稳定目标函数、梯度稀疏或梯度存在很大噪声的问题 

  • torch.optim.AdamW(paramslr=0.001betas=(0.9, 0.999)eps=1e-08weight_decay=0.01amsgrad=False*maximize=Falseforeach=Nonecapturable=False)

  功能:Adam的进化版,是目前训练神经网络最快的方式

  参数:

    • 参数(可迭代) – 可迭代参数以优化或指示定义参数组

    • lr(浮点数可选)– 学习速率(默认值:1e-3)

    • betas(元组[浮点数,浮点数]可选)–用于计算梯度及其平方的运行平均值的系数(默认值:(0.9,0.999))

    • eps(浮点数可选)– 添加到分母以提高数值稳定性的术语(默认值:1e-8)

    • weight_decay(浮点数可选)– 权重衰减系数(默认值:1e-2)

    • amsgrad(布尔值可选)–是否使用此算法的AMSGrad变体(默认:False)

    • 最大化(布尔值可选)–根据目标最大化参数,而不是最小化(默认值:False)

    • foreach(布尔值可选)– 是否使用优化器的 foreach 实现(默认值:无)

    • 可捕获(布尔值可选)– 此实例在 CUDA 图中捕获是否安全。传递 True 可能会损害未绘制的性能,因此,如果您不打算以图形捕获此实例,请将其保留为 False(默认值:False)

  优点:比Adam收敛得更快

  缺点:只有fastai使用,缺乏广泛的框架,而且也具有很大的争议性

  • torch.optim.Adamax(params, lr=0.002, betas=(0.9, 0.999), eps=1e-08, weight_decay=0)

  功能:实现Adamax算法,Adam的改进版,对Adam增加了一个学习率上限的概念,是Adam的一种基于无穷范数的变种。

  参数:

    • params (iterable) – 待优化参数的iterable或者是定义了参数组的dict
    • lr (float, 可选) – 学习率(默认:2e-3)
    • betas (Tuple[floatfloat], 可选) – 用于计算梯度以及梯度平方的运行平均值的系数
    • eps (float, 可选) – 为了增加数值计算的稳定性而加到分母里的项(默认:1e-8)
    • weight_decay (float, 可选) – 权重衰减(L2惩罚)(默认: 0)

  优点:对学习率的上限提供了一个更简单的范围

  • torch.optim.SparseAdam(params, lr=0.001, betas=(0.9, 0.999), eps=1e-08)

  功能:实现适用于稀疏张量的 Adam 算法的“阉割版”。

  参数:

    • 参数(可迭代) – 可迭代参数以优化或指示定义参数组
    • lr(浮点数可选)– 学习速率(默认值:1e-3)
    • betas(元组[浮点数,浮点数]可选)–用于计算梯度及其平方的运行平均值的系数(默认值:(0.9,0.999))
    • eps(浮点数可选)– 添加到分母以提高数值稳定性的术语(默认值:1e-8)

  优点:相当于Adam的稀疏张量专用版本

  • torch.optim.LBFGS(params, lr=1, max_iter=20, max_eval=None, tolerance_grad=1e-05, tolerance_change=1e-09, history_size=100, line_search_fn=None)

  功能:实现L-BFGS算法。是一种在牛顿法基础上提出的一种求解函数根的算法,简单来说,L-BFGS和梯度下降、SGD干的同样的事情,但大多数情况下收敛速度更快

     L-BFGS是对BFGS的改进,特点就是节省内存。是解无约束非线性规划问题最常用的方法

  参数:

    • lr (float) – 学习率(默认:1)
    • max_iter (int) – 每一步优化的最大迭代次数(默认:20))
    • max_eval (int) – 每一步优化的最大函数评价次数(默认:max * 1.25)
    • tolerance_grad (float) – 一阶最优的终止容忍度(默认:1e-5)
    • tolerance_change (float) – 在函数值/参数变化量上的终止容忍度(默认:1e-9)
    • history_size (int) – 更新历史的大小(默认:100)

  优点:收敛速度快、内存开销少,是解无约束非线性规划问题最常用的方法

  缺点:使用条件严苛 

  • torch.optim.Rprop(params, lr=0.01, etas=(0.5, 1.2), step_sizes=(1e-06, 50))

  原理:

    1、首先为各权重变化赋一个初始值,设定权重变化加速因子与减速因子。

    2、在网络前馈迭代中当连续误差梯度符号不变时,采用加速策略,加快训练速度;当连续误差梯度符号变化时,采用减速策略,以期稳定收敛。

    3、网络结合当前误差梯度符号与变化步长实现BP,同时,为了避免网络学习发生振荡或下溢,算法要求设定权重变化的上下限

  功能:实现弹性反向传播算法。

  参数:

    • params (iterable) – 待优化参数的iterable或者是定义了参数组的dict
    • lr (float, 可选) – 学习率(默认:1e-2)
    • etas (Tuple[floatfloat], 可选) – 一对(etaminus,etaplis), 它们分别是乘法的增加和减小的因子(默认:0.5,1.2)
    • step_sizes (Tuple[floatfloat], 可选) – 允许的一对最小和最大的步长(默认:1e-6,50)

  缺点:优化方法适用于full-batch,不适用于mini-batch,因此基本上没什么用

  • torch.optim.RMSprop(params, lr=0.01, alpha=0.99, eps=1e-08, weight_decay=0, momentum=0, centered=False)

  功能:实现RMSprop算法。RProp的改进版,也是Adagard的改进版

  思想:梯度震动较大的项,在下降时,减小其下降速度;对于震动幅度小的项,在下降时,加速其下降速度

  参数:

    • params (iterable) – 待优化参数的iterable或者是定义了参数组的dict
    • lr (float, 可选) – 学习率(默认:1e-2)
    • momentum (float, 可选) – 动量因子(默认:0)
    • alpha (float, 可选) – 平滑常数(默认:0.99)
    • eps (float, 可选) – 为了增加数值计算的稳定性而加到分母里的项(默认:1e-8)
    • centered (bool, 可选) – 如果为True,计算中心化的RMSProp,并且用它的方差预测值对梯度进行归一化
    • weight_decay (float, 可选) – 权重衰减(L2惩罚)(默认: 0)

  优点:可缓解Adagrad学习率下降较快的问题,并且引入均方根(分母),可以减少摆动,适合处理非平稳目标,对于RNN效果很好

  缺点:依然依赖于全局学习率 

  • torch.optim.SGD(params, lr=, momentum=0, dampening=0, weight_decay=0, nesterov=False)

  功能:实现随机梯度下降算法(momentum可选)。

  参数:

    • params (iterable) – 待优化参数的iterable或者是定义了参数组的dict
    • lr (float) – 学习率
    • momentum (float, 可选) – 动量因子(默认:0)
    • weight_decay (float, 可选) – 权重衰减(L2惩罚)(默认:0)
    • dampening (float, 可选) – 动量的抑制因子(默认:0)
    • nesterov (bool, 可选) – 使用Nesterov动量(默认:False)

  优点:①使用mini-batch的时候,可以收敛得很快

  缺点:①在随机选择梯度的同时会引入噪声,使得权值更新的方向不一定正确

             ②不能解决局部最优解的问题

  若使用动量( momentum不为0可加快收敛速度,有一定摆脱局部最优的能力,一定程度上缓解了没有动量的时候的问题)

 

  上述优化算法均继承于Optimizer:

class Optimizer(object):
    def __init__(self, params, defaults):        
        self.defaults = defaults
        self.state = defaultdict(dict)
        self.param_groups = []

  Optimizer有三个属性:

  • defaults:存储的是优化器的超参数
{'lr': 0.1, 'momentum': 0.9, 'dampening': 0, 'weight_decay': 0, 'nesterov': False}
  • state:参数的缓存
defaultdict(<class 'dict'>, {tensor([[ 0.3864, -0.0131],
        [-0.1911, -0.4511]], requires_grad=True): {'momentum_buffer': tensor([[0.0052, 0.0052],
        [0.0052, 0.0052]])}})
  • param_groups:管理的参数组,是一个list,其中每个元素是一个字典,顺序是params,lr,momentum,dampening,weight_decay,nesterov
[{'params': [tensor([[-0.1022, -1.6890],[-1.5116, -1.7846]], requires_grad=True)], 'lr': 1, 'momentum': 0, 'dampening': 0, 'weight_decay': 0, 'nesterov': False}]

  Optimizer其他方法:

  • zero_grad():清空所管理参数的梯度,PyTorch的特性是张量的梯度不自动清零,因此每次反向传播后都需要清空梯度。

  • step():执行一步梯度更新,参数更新
  • add_param_group():添加参数组

  • load_state_dict() :加载状态参数字典,可以用来进行模型的断点续训练,继续上次的参数进行训练

  • state_dict():获取优化器当前状态信息字典

3.9.2 实际操作

import os
import torch

# 设置权重,服从正态分布  --> 2 x 2
weight = torch.randn((2, 2), requires_grad=True)
# 设置梯度为全1矩阵  --> 2 x 2
weight.grad=torch.ones((2, 2))
# 输出现有的weight和data
print("The data of weight before step:\n{}".format(weight.data))
print("The grad of weight before step:\n{}".format(weight.grad))
# 实例化优化器
optimizer = torch.optim.SGD([weight], lr=0.1, momentum=0.9)
# 进行一步梯度更新
optimizer.step()
# 查看进行一步后的值,梯度
print("The data of weight after step:\n{}".format(weight.data))
print("The grad of weight after step:\n{}".format(weight.grad))
# 梯度清零
optimizer.zero_grad()
# 检验权重是否为0
print("The grad of weight after optimizer.zero_grad():\n{}".format(weight.grad))
# 输出参数
print("optimizer.params_group is \n{}".format(optimizer.param_groups))
# 查看参数位置,optimizer和weight的位置一样,我觉得这里可以参考Python是基于值管理
print("weight in optimizer:{}\nweight in weight:{}\n".format(id(optimizer.param_groups[0]['params'][0]), id(weight)))
# 添加参数:weight2 weight2 = torch.randn((3, 3), requires_grad=True) optimizer.add_param_group({"params": weight2, 'lr': 0.0001, 'nesterov': True})# 添加参数组 # 查看现有的参数 print("optimizer.param_groups is\n{}".format(optimizer.param_groups)) # 查看当前状态信息 opt_state_dict = optimizer.state_dict() print("state_dict before step:\n", opt_state_dict) # 进行5次step操作 for _ in range(50): optimizer.step() # 输出现有状态信息 print("state_dict after step:\n", optimizer.state_dict()) # 保存参数信息 torch.save(optimizer.state_dict(),os.path.join(r"SavePath", "optimizer_state_dict.pkl")) print("----------done-----------") # 加载参数信息 state_dict = torch.load(r"SavePath + \optimizer_state_dict.pkl") # 需要修改为你自己的路径
optimizer.load_state_dict(state_dict)
print("load state_dict successfully\n{}".format(state_dict))
# 输出最后属性信息 print("\n{}".format(optimizer.defaults)) print("\n{}".format(optimizer.state)) print("\n{}".format(optimizer.param_groups))

  注:

  1. 每个优化器都是一个类,我们一定要进行实例化才能使用:

class Net(nn.Moduel):
    ...
net = Net()
optim = torch.optim.SGD(net.parameters(), lr=lr)
optim.step()

 

  2.optimizer在一个神经网络的epoch中需要实现下面两个步骤:

 

    • 梯度置零

    • 梯度更新

optimizer = torch.optim.SGD(net.parameters(), lr = 1e-3)
for epoch in range(epochs):
    ...
    optimizer.zero_grad() # 梯度清零
    loss = ... # 计算loss
    loss.backward() # loss反向传播
    optimizer.step() # 梯度更新

  3.给网络不同的层赋予不同的优化器参数。

from torch import optim
from torchvision.models import resnet18

net = resnet18()

optimizer = optim.SGD([
    {'params':net.fc.parameters()},#fc的lr使用默认的1e-5
    {'params':net.layer4[0].conv1.parameters(),'lr':1e-2}],lr=1e-5)
# 可以使用param_groups查看属性

标签:weight,float,默认,PyTorch,lr,模块,1e,参数,组成
来源: https://www.cnblogs.com/5466a/p/16611186.html

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有