其他分享
首页 > 其他分享> > 3. PyTorch主要组成模块(3)

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

作者:互联网

3.8 Pytorch优化器()

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

3.9.1 Pytorch提供的优化器

     参数:

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

  参数:

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

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

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

  参数:

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

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

  功能:实现Adam算法。

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

  参数:

  优点:

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

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

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

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

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

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

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

  参数:

  优点:比Adam收敛得更快

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

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

  参数:

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

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

  参数:

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

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

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

  参数:

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

  缺点:使用条件严苛 

  原理:

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

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

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

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

  参数:

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

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

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

  参数:

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

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

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

  参数:

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

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

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

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

 

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

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

  Optimizer有三个属性:

{'lr': 0.1, 'momentum': 0.9, 'dampening': 0, 'weight_decay': 0, 'nesterov': False}
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]])}})
[{'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其他方法:

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