【深度学习】学习率与学习率衰减详解:torch.optim.lr_scheduler用法

news2024/10/6 22:34:13

【深度学习】学习率与学习率衰减详解:torch.optim.lr_scheduler用法

文章目录

  • 【深度学习】学习率与学习率衰减详解:torch.optim.lr_scheduler用法
    • 1. 介绍
      • 1.1 学习率与学习率衰减
    • 2. TensorFlow中的学习率衰减
    • 3. PyTorch中的学习率衰减
      • 2.1 optimizer 综述
      • 2.2 lr_scheduler调整策略:根据训练次数
        • 2.2.0 直接手动修改optimizer的lr参数
        • 2.2.1 自定义调整学习率(LambdaLR)
        • 2.2.2 每 s 个 epoch 更新一次参数(等步长调整学习率(StepLR))
        • 2.2.3 多步长调整学习率(MultiStepLR)
        • 2.2.4 指数衰减调整学习率(ExponentialLR)
        • 2.2.5 余弦退火调整学习率(CosineAnnealingLR)
        • 2.2.6 其他的一些 lr_scheduler
      • 2.3 lr_scheduler调整策略:根据训练中某些测量值
    • 参考

—————————————————————————————————————————————————————————————

1. 介绍

深度学习模型训练过程中,经过一定的epoch之后,模型的性能趋于饱和,此时降低学习率,在小范围内进一步调整模型的参数,可以进一步提升模型的性能。

  • 经过多年的发展,也出现了多种学习率衰减算法,比如线性衰减、指数衰减、cosine衰减等,下面将pyTorch中提供的学习率衰减算法进行整理。

1.1 学习率与学习率衰减

模型参数的学习主要是通过反向传播和梯度下降,

  • 而其中梯度下降的学习率设置方法是指数衰减:在训练神经网络时,需要设置学习率(learing rate)控制参数更新的速度,学习率决定了参数每次更新的幅度,
    • 如果幅度过大,则可能导致参数在极优值的两侧来回移动;
    • 若幅度过小,又会大大降低优化速度。

通过指数衰减的学习率既可以让模型在训练的前期快速接近较优解,又可以保证模型在训练后期不会有太大的波动,从而更加接近局部的最优解。

—————————————————————————————————————————————————————————————

2. TensorFlow中的学习率衰减

  • TensorFlow提供了一种更加灵活的学习率设置方法-指数衰减法,使用tf.train.exponential_decay实现。指数衰减法的核心思想是,先使用较大的学习率来快速得到一个比较优的解,然后随着迭代的继续逐步减小学习率,使得模型更加稳定。

tf.train.exponential_decay函数可以用以下代码实现的功能来展示:

decayed_learning_rate = learning_rate*decay_rate^(global_step/decay_steps)
# decayed_learning_rate为每一轮优化时使用的学习率,learning_rate为事先设定的初始学习率,
# decay_rate为衰减系数,global_step为迭代次数,decay_steps为衰减速度(即迭代多少次进行衰减)

由代码可见,

  • 使用此函数,随着迭代次数的增加,学习率逐步降低。tf.train.exponential_decay 可以通过设置参数staircase选择不同的衰减方式,其默认值为False,即每一次迭代都进行学习率的优化,不同的训练数据有不同的学习率,而当学习率减小时,对应的训练数据对模型训练结果的影响也会变小。若staircase的值为True时,global_step/decay_steps的值会被转化为整数,decay_steps通常代表了完整的使用一遍训练数据所需要的迭代次数,所以每完整的使用完一遍训练数据,学习率才会重新计算并减小一次,这可以使得训练数据集中的所有数据对模型有相等的作用。

1)具体的函数使用代码如下:

global_step = tf.Variable(0) #迭代次数初始值为0

# 通过exponential_decay生成学习率
learning_rate = tf.train.exponential_decay(0.1, global_step, 100, 0.96, staircase=True)
# 0.1为初始学习率,global_step为迭代次数,100为衰减速度,0.96为衰减率

# 使用指数衰减的学习率,在minimize函数中传入global_step,它将自动更新,learning_rate也随即被更新
learning_step = tf.train.GradientDescentOptimizer(learning_rate).minimize(loss, global_step=global_step)
# 神经网络反向传播算法,使用梯度下降算法GradientDescentOptimizer来优化权重值,learning_rate为学习率,
# minimize中参数loss是损失函数,global_step表明了当前迭代次数(会被自动更新)

2)一般来说,初始学习率、衰减系数和衰减速度都是根据经验设置的。为了更好理解学习率的详细设置,通过Tensorflow框架中学习率设置为例。

  • 在tensorflow中提供了一个灵活的学习率设置方法,tf.train.exponential_decay函数实现了指数衰减,其实现的原理如下:
decayed_learning_rate=learning_rate*decay_rate^(global_step/decay_steps)

其中:

  • decayed_learning_rate:每一轮优化时使用的学习率 (当前学习率)
  • learning_rate:事先设定的初始学习率
  • decay_rate:衰减系数 (学习率的衰减系数)
  • decay_steps:衰减速度 (相当于iteration ,总样本/batch-size)

tf.train.exponential_decay 函数还可以通过设置参数 staircase 选择不同的衰减方式。

  • staircase是false,这时的学习率会随迭代的轮数成平滑的衰减下降,这里的不同训练数据有不同的学习率。
  • staircase是true,(global_step/decay_steps)会被转化为整数,这时学习率会随着轮数成阶梯状下降,在这种设置下decay_steps指完整的使用一遍训练数据所需要的迭代轮数(总的训练样本数处以每一个batch中的训练样本数),这里的意思就是每完整的过完一遍训练数据,学习率就减少一次,这可以使得训练集中的所有数据对模型训练有相等的作用。

在这里插入图片描述

3)使用如下:

EARNING_RATE = tf.train.exponential_decay(0.1, global_step, 1, 0.96, staircase=True)
train_op = tf.train.GradientDescentOptimizer(LEARNING_RATE).minimize(y, global_step=global_step)

代码完整示例:

import tensorflow as tf
from numpy.random import RandomState

# 假设我们要最小化函数  y=x^2 , 选择初始点  x0=5 
TRAINING_STEPS = 100
LEARNING_RATE = 1
x = tf.Variable(tf.constant(5, dtype=tf.float32), name="x")
y = tf.square(x)

train_op = tf.train.GradientDescentOptimizer(LEARNING_RATE).minimize(y)

global_step = tf.Variable(0)
LEARNING_RATE = tf.train.exponential_decay(0.1, global_step, 1, 0.96, staircase=True)

x = tf.Variable(tf.constant(5, dtype=tf.float32), name="x")
y = tf.square(x)
train_op = tf.train.GradientDescentOptimizer(LEARNING_RATE).minimize(y, global_step=global_step)

with tf.Session() as sess:
    sess.run(tf.global_variables_initializer())
    for i in range(TRAINING_STEPS):
        sess.run(train_op)
        if i % 10 == 0:
            LEARNING_RATE_value = sess.run(LEARNING_RATE)
            x_value = sess.run(x)
            print ("After %s iteration(s): x%s is %f, learning rate is %f." \
                   % (i+1, i+1, x_value, LEARNING_RATE_value))

运行结果:

After 1 iteration(s): x1 is 4.000000, learning rate is 0.096000.
After 11 iteration(s): x11 is 0.690561, learning rate is 0.063824.
After 21 iteration(s): x21 is 0.222583, learning rate is 0.042432.
After 31 iteration(s): x31 is 0.106405, learning rate is 0.028210.
After 41 iteration(s): x41 is 0.065548, learning rate is 0.018755.
After 51 iteration(s): x51 is 0.047625, learning rate is 0.012469.
After 61 iteration(s): x61 is 0.038558, learning rate is 0.008290.
After 71 iteration(s): x71 is 0.033523, learning rate is 0.005511.
After 81 iteration(s): x81 is 0.030553, learning rate is 0.003664.
After 91 iteration(s): x91 is 0.028727, learning rate is 0.002436.

—————————————————————————————————————————————————————————————

3. PyTorch中的学习率衰减

  • pyTorch官方介绍:https://pytorch.org/docs/stable/optim.html

torch.optim.lr_scheduler模块提供了一些根据epoch训练次数来调整学习率(learning rate)的方法。\

  • 一般情况下我们会设置随着epoch的增大而逐渐减小学习率从而达到更好的训练效果。

而 torch.optim.lr_scheduler.ReduceLROnPlateau 则提供了基于训练中某些测量值使学习率动态下降的方法。

学习率的调整应该放在optimizer更新之后,下面是一个参考蓝本:

optimizer = ...
scheduler = ...
for epoch in range(100):
	loss = criterion(outputs, targets)
    loss.backward()
    optimizer.step()
	scheduler.step()
  • scheduler.step()执行学习率衰减操作。

pyTorch 1.1.0之前的版本,是在optimizer更新之前进行学习率衰减。

  • 之后的版本调整为先进行optimizer更新,再进行学习率衰减。
  • 如果在1.1.0之后的版本中,先调用了scheduler.step()再调用optimizer.step(),造成的后果是第一次的学习率衰减并未生效。
  • 如果pytorch升级到1.1.0之后的版本无法复现原始的训练结果,那么就需要检查是不是调用scheduler.step()的顺序出错了。

—————————————————————————————————————————————————————————————

2.1 optimizer 综述

为了了解lr_scheduler,我们先以Adam()为例了解一下优化器(所有 optimizers 都继承自torch.optim.Optimizer类):

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

1)参数:

  • params(iterable):需要优化的网络参数,传进来的网络参数必须是 Iterable(官网对这个参数用法讲的不太清楚,下面有例子清楚的说明param具体用法)。
    • 如果优化一个网络,网络的每一层看做一个parameter group,一整个网络就是parameter groups(一般给赋值为net.parameters()),补充一点,net.parameters()函数返回的parameter groups实际上是一个变成了generator的字典;
    • 如果同时优化多个网络,有两种方法:
      • 将多个网络的参数合并到一起,当成一个网络的参数来优化(一般赋值为[*net_1.parameters(), *net_2.parameters(), …, *net_n.parameters()]或itertools.chain(net_1.parameters(), net_2.parameters(), …, net_n.parameters()));
      • 当成多个网络优化,这样可以很容易的让多个网络的学习率各不相同(一般赋值为[{‘params’: net_1.parameters()}, {‘params’: net_2.parameters()}, …, {‘params’: net_n.parameters()})。
  • lr (float, optional):学习率;
  • betas (Tuple[float, float], optional) – coefficients used for computing running averages of gradient and its square (default: (0.9, 0.999));
  • eps (float, optional) – term added to the denominator to improve numerical stability (default: 1e-8);
  • weight_decay (float, optional) – weight decay (L2 penalty) (default: 0);
  • amsgrad (boolean, optional) – whether to use the AMSGrad variant of this algorithm from the paper On the Convergence of Adam and Beyond (default: False)。

2)属性:

  • optimizer.defaults: 字典,存放这个优化器的一些初始参数,有:‘lr’, ‘betas’, ‘eps’, ‘weight_decay’, ‘amsgrad’。事实上这个属性继承自torch.optim.Optimizer父类;
  • optimizer.param_groups:列表,每个元素都是一个字典,每个元素包含的关键字有:‘params’, ‘lr’, ‘betas’, ‘eps’, ‘weight_decay’, ‘amsgrad’,params类是各个网络的参数放在了一起。这个属性也继承自torch.optim.Optimizer父类。

由于上述两个属性都继承自所有优化器共同的基类,所以是所有优化器类都有的属性,并且两者字典中键名相同的元素值也相同(经过lr_scheduler后 lr 就不同了)。

3)用法示例:

import torch
import torch.nn as nn
from torch.optim.lr_scheduler import LambdaLR
import itertools

initial_lr = 0.1

class model(nn.Module):
    def __init__(self):
        super().__init__()
        self.conv1 = nn.Conv2d(in_channels=3, out_channels=3, kernel_size=3)
        self.conv2 = nn.Conv2d(in_channels=3, out_channels=3, kernel_size=3)

    def forward(self, x):
        pass

net_1 = model()
net_2 = model()

optimizer_1 = torch.optim.Adam(net_1.parameters(), lr = initial_lr)
print("******************optimizer_1*********************")
print("optimizer_1.defaults:", optimizer_1.defaults)
print("optimizer_1.param_groups长度:", len(optimizer_1.param_groups))
print("optimizer_1.param_groups一个元素包含的键:", optimizer_1.param_groups[0].keys())
print()

optimizer_2 = torch.optim.Adam([*net_1.parameters(), *net_2.parameters()], lr = initial_lr)
# optimizer_2 = torch.opotim.Adam(itertools.chain(net_1.parameters(), net_2.parameters())) # 和上一行作用相同
print("******************optimizer_2*********************")
print("optimizer_2.defaults:", optimizer_2.defaults)
print("optimizer_2.param_groups长度:", len(optimizer_2.param_groups))
print("optimizer_2.param_groups一个元素包含的键:", optimizer_2.param_groups[0].keys())
print()

optimizer_3 = torch.optim.Adam([{"params": net_1.parameters()}, {"params": net_2.parameters()}], lr = initial_lr)
print("******************optimizer_3*********************")
print("optimizer_3.defaults:", optimizer_3.defaults)
print("optimizer_3.param_groups长度:", len(optimizer_3.param_groups))
print("optimizer_3.param_groups一个元素包含的键:", optimizer_3.param_groups[0].keys())

对应输出为:

******************optimizer_1*********************
optimizer_1.defaults: {'lr': 0.1, 'betas': (0.9, 0.999), 'eps': 1e-08, 'weight_decay': 0, 'amsgrad': False}
optimizer_1.param_groups长度: 1
optimizer_1.param_groups一个元素包含的键: dict_keys(['params', 'lr', 'betas', 'eps', 'weight_decay', 'amsgrad'])

******************optimizer_2*********************
optimizer_2.defaults: {'lr': 0.1, 'betas': (0.9, 0.999), 'eps': 1e-08, 'weight_decay': 0, 'amsgrad': False}
optimizer_2.param_groups长度: 1
optimizer_2.param_groups一个元素包含的键: dict_keys(['params', 'lr', 'betas', 'eps', 'weight_decay', 'amsgrad'])

******************optimizer_3*********************
optimizer_3.defaults: {'lr': 0.1, 'betas': (0.9, 0.999), 'eps': 1e-08, 'weight_decay': 0, 'amsgrad': False}
optimizer_3.param_groups长度: 2
optimizer_3.param_groups一个元素包含的键: dict_keys(['params', 'lr', 'betas', 'eps', 'weight_decay', 'amsgrad'])
  • 注意:lr_scheduler更新 optimizer 的 lr,更新的是 optimizer.param_groups[n][‘lr’],而不是 optimizer.defaults[‘lr’]。

—————————————————————————————————————————————————————————————

2.2 lr_scheduler调整策略:根据训练次数

pyTorch官方介绍:https://pytorch.org/docs/stable/optim.html

torch.optim.lr_scheduler 中大部分调整学习率的方法都是根据 epoch训练次数,这里介绍常见的几种方法,其他方法以后用到再补充。

  • 要了解每个类的更新策略,可直接查看官网doc中的源码,每类都有个get_lr方法,定义了更新策略。

—————————————————————————————————————————————————————————————

2.2.0 直接手动修改optimizer的lr参数

optimizer 通过 param_group 来管理参数组,

  • 它里面保存了参数组及其对应的学习率、动量等;
    在这里插入图片描述
    因此可以通过更改 param_group[‘lr’] 的值来更改对应参数组的学习率。

代码示例:

import torch
import matplotlib.pyplot as plt
import torch.optim as optim
from torch.optim import lr_scheduler
from torchvision.models import AlexNet

model = AlexNet(num_classes=2)
LR = 0.1
optimizer = optim.SGD(params=model.parameters(),lr=LR)

plt.figure()
x = list(range(100))
y=[]
for epoch in range(100):
    if epoch % 5 == 0:
        for p in optimizer.param_groups:
            p['lr'] *= 0.9
    y.append(optimizer.state_dict()['param_groups'][0]['lr'])
plt.plot(x,y,color = 'r')
plt.show()

在这里插入图片描述

2.2.1 自定义调整学习率(LambdaLR)

torch.optim.lr_scheduler.LambdaLR(optimizer, lr_lambda, last_epoch=-1, verbose=False)

1)参数:

  1. optimizer (Optimizer):要更改学习率的优化器;
  2. lr_lambda(function or list):根据epoch计算 λ 的函数;或者是一个 list 的这样的function,分别计算各个parameter groups的学习率更新用到的 λ ;
  3. last_epoch (int):最后一个epoch的index,如果是训练了很多个epoch后中断了,继续训练,这个值就等于加载的模型的epoch。默认为 -1表示从头开始训练,即从epoch=1开始。

2)更新策略,公式表示:
在这里插入图片描述

  • 其中,new_lr是得到新的学习率, λ \lambda λ 是根据 epoch 计算λ 函数;或者是一个list的这样的 function,分别计算各个parameter groups的学习率更新用到的 λ;initial_lr 是初始的学习率。

3)注意:在将 optimizer 传给 scheduler 后,在shcduler类的__init__方法中会给optimizer.param_groups列表中的那个元素(字典)增加一个key = "initial_lr"的元素表示初始学习率,等于optimizer.defaults[‘lr’]。

4)举例说明:

import torch
import torch.nn as nn
from torch.optim.lr_scheduler import LambdaLR

initial_lr = 0.1

class model(nn.Module):
    def __init__(self):
        super().__init__()
        self.conv1 = nn.Conv2d(in_channels=3, out_channels=3, kernel_size=3)

    def forward(self, x):
        pass

net_1 = model()

optimizer_1 = torch.optim.Adam(net_1.parameters(), lr = initial_lr)
scheduler_1 = LambdaLR(optimizer_1, lr_lambda=lambda epoch: 1/(epoch+1))

print("初始化的学习率:", optimizer_1.defaults['lr'])

for epoch in range(1, 11):
    # train

    optimizer_1.zero_grad()
    optimizer_1.step()
    print("第%d个epoch的学习率:%f" % (epoch, optimizer_1.param_groups[0]['lr']))
    scheduler_1.step()

输出:

初始化的学习率: 0.11个epoch的学习率:0.1000002个epoch的学习率:0.0500003个epoch的学习率:0.0333334个epoch的学习率:0.0250005个epoch的学习率:0.0200006个epoch的学习率:0.0166677个epoch的学习率:0.0142868个epoch的学习率:0.0125009个epoch的学习率:0.01111110个epoch的学习率:0.010000

关键行解析:

1~3: import一些包。
第7~13: 简单定义一个网络类,并没有实现网络应有的功能,只是用来定义optimizer的。
第15: 实例化一个网络。
第17: 实例化一个Adam对象。
第18: 实例化一个LambdaLR对象。lr_lambda是根据epoch更新lr的函数。
第20: 打印出初始的lr。optimizer_1.defaults保存的是初始的参数。
第22~28: 模仿训练的epoch。
第2526: 更新网络参数(这里省略了loss.backward())。
第27: 打印这一个epoch更新参数所用的学习率,由于我们只给optimizer_1传了一个net.parameters(),所以optimizer_1.param_groups长度为1。
第28: 更新学习率。

5)补充:cycleGAN中使用torch.optim.lr_scheduler.LambdaLR实现了前niter个epoch用initial_lr为学习率,之后的niter_decay个epoch线性衰减lr,直到最后一个epoch衰减为0。参考:知乎

—————————————————————————————————————————————————————————————

2.2.2 每 s 个 epoch 更新一次参数(等步长调整学习率(StepLR))

class torch.optim.lr_scheduler.StepLR(optimizer, step_size, gamma=0.1, last_epoch=-1)

1)参数:

  • optimizer (Optimizer):要更改学习率的优化器;
  • step_size(int):每训练step_size个epoch,更新一次参数;
  • gamma(float):更新lr的乘法因子;
  • last_epoch (int):最后一个epoch的index,如果是训练了很多个epoch后中断了,继续训练,这个值就等于加载的模型的epoch。默认为-1表示从头开始训练,即从epoch=1开始。

2)更新策略:
在这里插入图片描述
3)举例说明:

import torch
import torch.nn as nn
from torch.optim.lr_scheduler import StepLR
import itertools

initial_lr = 0.1

class model(nn.Module):
    def __init__(self):
        super().__init__()
        self.conv1 = nn.Conv2d(in_channels=3, out_channels=3, kernel_size=3)

    def forward(self, x):
        pass

net_1 = model()

optimizer_1 = torch.optim.Adam(net_1.parameters(), lr = initial_lr)
scheduler_1 = StepLR(optimizer_1, step_size=3, gamma=0.1)

print("初始化的学习率:", optimizer_1.defaults['lr'])

for epoch in range(1, 11):
    # train

    optimizer_1.zero_grad()
    optimizer_1.step()
    print("第%d个epoch的学习率:%f" % (epoch, optimizer_1.param_groups[0]['lr']))
    scheduler_1.step()

输出:

初始化的学习率: 0.11个epoch的学习率:0.1000002个epoch的学习率:0.1000003个epoch的学习率:0.1000004个epoch的学习率:0.0100005个epoch的学习率:0.0100006个epoch的学习率:0.0100007个epoch的学习率:0.0010008个epoch的学习率:0.0010009个epoch的学习率:0.00100010个epoch的学习率:0.000100

—————————————————————————————————————————————————————————————

2.2.3 多步长调整学习率(MultiStepLR)

class torch.optim.lr_scheduler.MultiStepLR(optimizer, milestones, gamma=0.1, last_epoch=-1)

1)

  • 参数:
    在这里插入图片描述

2)更新策略:
在这里插入图片描述
3)举例说明:

import torch
import torch.nn as nn
from torch.optim.lr_scheduler import MultiStepLR
import itertools


initial_lr = 0.1

class model(nn.Module):
    def __init__(self):
        super().__init__()
        self.conv1 = nn.Conv2d(in_channels=3, out_channels=3, kernel_size=3)

    def forward(self, x):
        pass

net_1 = model()

optimizer_1 = torch.optim.Adam(net_1.parameters(), lr = initial_lr)
scheduler_1 = MultiStepLR(optimizer_1, milestones=[3, 7], gamma=0.1)

print("初始化的学习率:", optimizer_1.defaults['lr'])

for epoch in range(1, 11):
    # train

    optimizer_1.zero_grad()
    optimizer_1.step()
    print("第%d个epoch的学习率:%f" % (epoch, optimizer_1.param_groups[0]['lr']))
    scheduler_1.step()

输出:

初始化的学习率: 0.11个epoch的学习率:0.1000002个epoch的学习率:0.1000003个epoch的学习率:0.1000004个epoch的学习率:0.0100005个epoch的学习率:0.0100006个epoch的学习率:0.0100007个epoch的学习率:0.0100008个epoch的学习率:0.0010009个epoch的学习率:0.00100010个epoch的学习率:0.001000

—————————————————————————————————————————————————————————————

2.2.4 指数衰减调整学习率(ExponentialLR)

class torch.optim.lr_scheduler.ExponentialLR(optimizer, gamma, last_epoch=-1)

1)

  • 参数:
    在这里插入图片描述

2)更新策略:
在这里插入图片描述

3)举例说明:

import torch
import torch.nn as nn
from torch.optim.lr_scheduler import ExponentialLR
import itertools


initial_lr = 0.1

class model(nn.Module):
    def __init__(self):
        super().__init__()
        self.conv1 = nn.Conv2d(in_channels=3, out_channels=3, kernel_size=3)

    def forward(self, x):
        pass

net_1 = model()

optimizer_1 = torch.optim.Adam(net_1.parameters(), lr = initial_lr)
scheduler_1 = ExponentialLR(optimizer_1, gamma=0.1)

print("初始化的学习率:", optimizer_1.defaults['lr'])

for epoch in range(1, 11):
    # train

    optimizer_1.zero_grad()
    optimizer_1.step()
    print("第%d个epoch的学习率:%f" % (epoch, optimizer_1.param_groups[0]['lr']))
    scheduler_1.step()

输出:

初始化的学习率: 0.11个epoch的学习率:0.1000002个epoch的学习率:0.0100003个epoch的学习率:0.0010004个epoch的学习率:0.0001005个epoch的学习率:0.0000106个epoch的学习率:0.0000017个epoch的学习率:0.0000008个epoch的学习率:0.0000009个epoch的学习率:0.00000010个epoch的学习率:0.000000

—————————————————————————————————————————————————————————————

2.2.5 余弦退火调整学习率(CosineAnnealingLR)

class torch.optim.lr_scheduler.CosineAnnealingLR(optimizer, T_max, eta_min=0, last_epoch=-1)

1)

  • 参数:
    在这里插入图片描述
    2)更新策略:
    在这里插入图片描述

3)举例说明:

import torch
import torch.nn as nn
from torch.optim.lr_scheduler import CosineAnnealingLR
import itertools

import matplotlib.pyplot as plt


initial_lr = 0.1

class model(nn.Module):
    def __init__(self):
        super().__init__()
        self.conv1 = nn.Conv2d(in_channels=3, out_channels=3, kernel_size=3)

    def forward(self, x):
        pass

net_1 = model()

optimizer_1 = torch.optim.Adam(net_1.parameters(), lr = initial_lr)
scheduler_1 = CosineAnnealingLR(optimizer_1, T_max=20)

print("初始化的学习率:", optimizer_1.defaults['lr'])

lr_list = [] # 把使用过的lr都保存下来,之后画出它的变化

for epoch in range(1, 101):
    # train

    optimizer_1.zero_grad()
    optimizer_1.step()
    print("第%d个epoch的学习率:%f" % (epoch, optimizer_1.param_groups[0]['lr']))
    lr_list.append(optimizer_1.param_groups[0]['lr'])
    scheduler_1.step()

# 画出lr的变化
plt.plot(list(range(1, 101)), lr_list)
plt.xlabel("epoch")
plt.ylabel("lr")
plt.title("learning rate's curve changes as epoch goes on!")
plt.show()

输出结果过长不再展示,下面展示lr的变化图:
在这里插入图片描述

  • 可以看到 lr 的变化类似于cos函数的变化图。

—————————————————————————————————————————————————————————————

2.2.6 其他的一些 lr_scheduler

  • torch.optim.lr_scheduler.CyclicLR
  • torch.optim.lr_scheduler.OneCycleLR
  • torch.optim.lr_scheduler.CosineAnnealingWarmRestarts

—————————————————————————————————————————————————————————————

2.3 lr_scheduler调整策略:根据训练中某些测量值

  • 不依赖 epoch 更新 lr 的只有这个:torch.optim.lr_scheduler.ReduceLROnPlateau。
class torch.optim.lr_scheduler.ReduceLROnPlateau(optimizer, mode='min', factor=0.1, patience=10, verbose=False, threshold=0.0001, threshold_mode='rel', cooldown=0, min_lr=0, eps=1e-08)

1)

  • 参数:
    在这里插入图片描述
    2)更新策略:
    在这里插入图片描述

3)举例说明:

import torch
import torch.nn as nn
from torch.optim.lr_scheduler import ReduceLROnPlateau
import itertools


initial_lr = 0.1

class model(nn.Module):
    def __init__(self):
        super().__init__()
        self.conv1 = nn.Conv2d(in_channels=3, out_channels=3, kernel_size=3)

    def forward(self, x):
        pass

net_1 = model()

optimizer_1 = torch.optim.Adam(net_1.parameters(), lr = initial_lr)
scheduler_1 = ReduceLROnPlateau(optimizer_1, mode='min', factor=0.1, patience=2)

print("初始化的学习率:", optimizer_1.defaults['lr'])

for epoch in range(1, 15):
    # train

    test = 2
    optimizer_1.zero_grad()
    optimizer_1.step()
    print("第%d个epoch的学习率:%f" % (epoch, optimizer_1.param_groups[0]['lr']))
    scheduler_1.step(test)

输出:

初始化的学习率: 0.11个epoch的学习率:0.1000002个epoch的学习率:0.1000003个epoch的学习率:0.1000004个epoch的学习率:0.1000005个epoch的学习率:0.0100006个epoch的学习率:0.0100007个epoch的学习率:0.0100008个epoch的学习率:0.0010009个epoch的学习率:0.00100010个epoch的学习率:0.00100011个epoch的学习率:0.00010012个epoch的学习率:0.00010013个epoch的学习率:0.00010014个epoch的学习率:0.000010

—————————————————————————————————————————————————————————————

参考

【1】torch.optim.lr_scheduler:调整学习率_qyhaill的博客-CSDN博客_lr_scheduler
【2】decay_rate, decay_steps ,batchsize,iteration,epoch
【3】https://zhuanlan.zhihu.com/p/494010639
【4】https://blog.csdn.net/cdknight_happy/article/details/109379102
【5】https://zhuanlan.zhihu.com/p/475824165

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/457512.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

md/分类/信号领域/数字信号处理及MATLAB实现/频率调制(FM).md

文章目录 本文链接https://zh.wikipedia.org/wiki/频率调制用Python模拟FM/PM调制解调过程波形变化频率调制我的 本文链接 打死他 调频(英语:Frequency Modulation,缩写:FM)是一种以载波的瞬时频率变化来表示信息的方…

Java文件操作必备技能,10个小技巧让你快速掌握!

前言 在我们日常的开发中,文件操作是一个非常重要的主题。文件读写、文件复制、任意位置读写、缓存等技巧都是我们必须要掌握的。在这篇文章中,我将给你们介绍 10 个实用的文件操作技巧。 使用 try-with-resources 语句处理文件 IO 流,确保在…

C++Vector类详解

目录 1.Vector介绍 2.Vector的常见使用 2.1 vector构造函数 2.2 vector iterator使用 2.3 vector空间增长问题 2.4 vector增删改查 2.5 vector迭代器失效问题 3.Vector深度剖析及模拟实现 3.1 模拟实现(可跳过) 3.2 不使用memcpy剖析 1.Vector介绍 ve…

【LeetCode】106. 从中序与后序遍历序列构造二叉树

1.问题 给定两个整数数组 inorder 和 postorder ,其中 inorder 是二叉树的中序遍历, postorder 是同一棵树的后序遍历,请你构造并返回这颗 二叉树 。 示例 1 输入:inorder [9,3,15,20,7], postorder [9,15,7,20,3] 输出&#…

世优科技AI数字人产品“世优BOTA”发布!全面提升AI虚拟员工能力

2023年4月20日,“世优BOTA”产品发布会在北京圆满落幕。此次发布会上,世优(北京)科技有限公司(以下简称“世优科技”)正式发布了新一代AI数字人现象级产品——“世优BOTA”。来自现实世界的LiveVideoStack创始人包研与来自数字世界的世优虚拟主持人「阿央」通过新颖的互动开场方…

JDK多版本配置及切换版本不生效问题解决

一、准备工作 首先你要有多个版本的jdk,如果没有请移至 https://www.oracle.com/java/technologies/downloads/ 下载,具体下载方法可参考:Java同学入职环境安装全讲解 二、配置环境变量 在环境变量中配置多个JAVA_HOME,我这里…

Java中TCP通信的实现

0、TCP通信 传输控制协议(TCP,Transmission Control Protocol)是一种面向连接的、可靠的、基于字节流的传输层通信协议, 如果使用了 WireShark 工具,可以看到一次TCP连接建立时的整个过程。 1、单向通信 单向通信中&…

案例01-tlias智能学习辅助系统01-增删改查+参数传递

目录 1、需求说明:实现对部门表和员工表的增删改查 2、环境搭建 3、部门管理 3.1 查询部门 3.2 前后端联调 3.3 删除部门 3.4 新增部门 3.5 根据ID查询数据 3.5 修改部门 总结(Controller层参数接收): 4、员工管理 4.…

CMIP6:WRF模式动力降尺度、单点降尺度、统计方法区域降尺度

气候变化关系到农业、生态系统、社会经济和人类生存与发展,是当今世界关注的重点问题之一。IPCC(Intergovernmental Panel on Climate Change)第6次评估报告指出,自 20 世纪 50 年代以来,从全球平均气温和海温升高…

一个关于Mybatis和spring的公共组件starter

utils-springboot-starter 介绍使用说明 介绍 一个关于Mybatis和spring的公共组件starter,目前包含以下功能: 接口请求日志SQL执行日志数据自动加解密数据自动脱敏服务治理方面: 接口限流接口熔断降级:CPU、内存、异常数、异常率…

51.网页设计规则#1_字体设计

一些概念 字体排版 排版是安排字体的艺术和技术,以使书面语言在显示时清晰、可读和吸引人。(来自维基百科翻译) serif字体和sans-serif字体 serif字体 ● 创造一个传统/经典的外观和感觉 ● 体现出可信度 ● 适合长文本 sans-serif字体 …

【JavaScript】7.DOM的操作元素

DOM 的操作元素 JavaScript 的 DOM 操作可以改变网页内容、结构和样式,我们可以利用 DOM 操作元素来改变元素里面的内容 、属性等 1. 改变元素内容 element.innerText:从起始位置到终止位置的内容, 但它去除 html 标签, 同时空格和换行也会…

Pytorch深度学习笔记(十)多分类问题

课程推荐:09.多分类问题_哔哩哔哩_bilibili 目录 1. 多分类模型 2. softmax函数模型 3. Loss损失函数 4.实战MNIST Dataset 之前,在逻辑斯蒂回归中我们提到了二分类任务,现在我们讨论多分类问题。 1. 多分类模型 与二分类不同的是多分…

基于C#asp.net心里咨询服务网站系统

功能模块: 主要分为管理员和注册用户,注册用户可以查看所有人发布的心里文章,情感在线问答,查询相似问题,以及进入论坛进行交流(发帖跟帖评论收藏等)后台管理主要是针对个人信息修改 管理员对注…

SpringBoot自动装配机制的原理

自动装配 简单来说,就是自动去把第三方组件的Bean装载到IOC容器里面。不需要开发人员再去写Bean相关的一个配置。 在SpringBoot应用里面,只需要在启动类上去加上SpringBootApplication注解就可以实现自动配置,SpringBootApplication注解它是…

DSPC174 3BSE005461R1码垛工业机器人安装调试的13个步骤

​ DSPC174 3BSE005461R1码垛工业机器人安装调试的13个步骤 ABB码垛工业机器人安装调试的13个步骤 最近工业机器人市场上,调试工作比较火爆,单个项目动辄几十台机器人同时调试,开出的日薪达到1500-2000元。拥有如此庞大的市场需求和丰厚收入…

Hudi数据湖技术之核心概念

目录 1 基本概念1.1 时间轴Timeline1.2 文件管理1.3 索引Index 2 存储类型2.1 计算模型2.1.1 批式模型(Batch)2.1.2 流式模型(Stream)2.1.3 增量模型(Incremental) 2.2 查询类型(Query Type&…

力扣:通过《84.柱状图中最大的矩形》求解《85. 最大矩形》

84. 柱状图中最大的矩形 85. 最大矩形 84.柱状图中最大的矩形&#xff1a; 单调栈求解问题范围&#xff1a; 输出每个数左边第一个比它小的数 单调栈例题&#xff1a; Acwing 830. 单调栈 #include <iostream>using namespace std;const int N 100010; int stk[N],tt …

再多猜一次就爆炸(小黑子误入)

目录 猜数字游戏 游戏设计思路 1.电脑随机生成一个数 2.猜数字 3.输入我是ikun&#xff0c;泰裤辣! 否则电脑将在一分钟后关机 游戏运行效果 源码 代码分析 代码实现关键语句 strcmp() rand()与srand() 时间戳time() 寄语 猜数字游戏 游戏设计思路 1.电脑随机生…

C语言_Printf函数返回值

目录 1. 嵌套结构 2. Printf 函数返回值 在了解Printf 函数的返回值之前&#xff0c;先来了解下什么叫嵌套结构。 1. 嵌套结构 这里直接举个例子进行介绍&#xff1a; strlen 函数计算字符串长度&#xff0c;显然打印的结果是 3 但是如果采用嵌套结构&#xff08;简单来说就…