Pytorch 学习率衰减 之 余弦退火与余弦warmup 自定义学习率衰减scheduler

学习率衰减,通常我们英文也叫做scheduler。本文学习率衰减自定义,通过2种方法实现自定义,一是利用lambda,另外一个是继承pytorch的lr_scheduler

import math
import matplotlib.pyplot as plt
import numpy as np
import torch
import torch.nn as nn
from torch.optim import *
from torchvision import models
class Net(nn.Module):
    def __init__(self):
        super(Net,self).__init__()
        self.fc = nn.Linear(1, 10)
    def forward(self,x):
        return self.fc(x)

余弦退火

  1. 当T_max=20
lrs = []
model = Net()
LR = 0.01
epochs = 100
optimizer = Adam(model.parameters(),lr = LR)
scheduler = lr_scheduler.CosineAnnealingLR(optimizer, T_max=20, eta_min=1e-9)
for epoch in range(epochs):
    optimizer.step()
    lrs.append(optimizer.state_dict()['param_groups'][0]['lr'])
    scheduler.step()

plt.figure(figsize=(10, 6))
plt.plot(lrs, color='r')
plt.text(0, lrs[0], str(lrs[0]))
plt.text(epochs, lrs[-1], str(lrs[-1]))
plt.show()

Pytorch 学习率衰减 之 余弦退火与余弦warmup 自定义学习率衰减scheduler
  1. 当T_max = epochs,这就是我们经常用到的弦退火的 scheduler,下面再来看看带Warm-up的
lrs = []
model = Net()
LR = 0.01
epochs = 100
optimizer = Adam(model.parameters(),lr = LR)
scheduler = lr_scheduler.CosineAnnealingLR(optimizer, T_max=epochs, eta_min=1e-9)
for epoch in range(epochs):
    optimizer.step()
    lrs.append(optimizer.state_dict()['param_groups'][0]['lr'])
    scheduler.step()

plt.figure(figsize=(10, 6))
plt.plot(lrs, color='r')
plt.text(0, lrs[0], str(lrs[0]))
plt.text(epochs, lrs[-1], str(lrs[-1]))
plt.show()

Pytorch 学习率衰减 之 余弦退火与余弦warmup 自定义学习率衰减scheduler

WarmUp

下面来看看 Pytorch定义的余弦退货的公式如下
η t = η m i n + 1 2 ( η m a x − η m i n ) ( 1 + cos ⁡ ( T c u r T m a x π ) ) , T c u r ≠ ( 2 k + 1 ) T m a x ; η t + 1 = η t + 1 2 ( η m a x − η m i n ) ( 1 − cos ⁡ ( 1 T m a x π ) ) , T c u r = ( 2 k + 1 ) T m a x . \begin{aligned} \eta_t & = \eta_{min} + \frac{1}{2}(\eta_{max} – \eta_{min})\left(1 + \cos\left(\frac{T_{cur}}{T_{max}}\pi\right)\right), & T_{cur} \neq (2k+1)T_{max}; \ \eta_{t+1} & = \eta_{t} + \frac{1}{2}(\eta_{max} – \eta_{min}) \left(1 – \cos\left(\frac{1}{T_{max}}\pi\right)\right), & T_{cur} = (2k+1)T_{max}. \end{aligned}ηt ​ηt +1 ​​=ηm i n ​+2 1 ​(ηm a x ​−ηm i n ​)(1 +cos (T m a x ​T c u r ​​π)),=ηt ​+2 1 ​(ηm a x ​−ηm i n ​)(1 −cos (T m a x ​1 ​π)),​T c u r ​​=(2 k +1 )T m a x ​;T c u r ​=(2 k +1 )T m a x ​.​

实际上是用下面的公式做为更新的, 当T c u r = T m a x T_{cur} = T_{max}T c u r ​=T m a x ​是,c o s cos c o s部分为0,所以就等于η m i n \eta_{min}ηm i n ​

η t = η m i n + 1 2 ( η m a x − η m i n ) ( 1 + cos ⁡ ( T c u r T m a x π ) ) \eta_t = \eta_{min} + \frac{1}{2}(\eta_{max} – \eta_{min})\left(1 + \cos\left(\frac{T_{cur}}{T_{max}}\pi\right)\right)ηt ​=ηm i n ​+2 1 ​(ηm a x ​−ηm i n ​)(1 +cos (T m a x ​T c u r ​​π))

这里直接根据公式的定义来画个图看看

etas = []
epochs = 100
eta_max = 1e-4
eta_min = 1e-9
t_max = epochs / 1
for i in range(epoch):
    t_cur = i
    eta = eta_min + 0.5 * (eta_max - eta_min) * (1 + np.cos(np.pi * t_cur / t_max))
    etas.append(eta)

plt.figure(figsize=(10, 6))
plt.plot(range(len(etas)), etas, color='r')
plt.text(epochs, lrs[-1], str(lrs[-1]))
plt.show()

Pytorch 学习率衰减 之 余弦退火与余弦warmup 自定义学习率衰减scheduler
从图上来看,跟上面的余弦退化是一样的,眼尖的都会发现lr_min 不等于eta_min=1e-9

利用Lambda来定义的

有个较小的bug(也不算,在description里有指出)

def warm_up_cosine_lr_scheduler(optimizer, epochs=100, warm_up_epochs=5, eta_min=1e-9):
"""
    Description:
        - Warm up cosin learning rate scheduler, first epoch lr is too small

    Arguments:
        - optimizer: input optimizer for the training
        - epochs: int, total epochs for your training, default is 100. NOTE: you should pass correct epochs for your training
        - warm_up_epochs: int, default is 5, which mean the lr will be warm up for 5 epochs. if warm_up_epochs=0, means no need
          to warn up, will be as cosine lr scheduler
        - eta_min: float, setup ConsinAnnealingLR eta_min while warm_up_epochs = 0

    Returns:
        - scheduler
"""

    if warm_up_epochs  0:
        scheduler = torch.optim.lr_scheduler.CosineAnnealingLR(optimizer, T_max=epochs, eta_min=eta_min)

    else:
        warm_up_with_cosine_lr = lambda epoch: eta_min + (epoch / warm_up_epochs) if epoch  warm_up_epochs else 0.5 * (
            np.cos((epoch - warm_up_epochs) / (epochs - warm_up_epochs) * np.pi) + 1)
        scheduler = torch.optim.lr_scheduler.LambdaLR(optimizer, lr_lambda=warm_up_with_cosine_lr)

    return scheduler

lrs = []
model = Net()
LR = 1e-4
warm_up_epochs = 30
epochs = 100
optimizer = SGD(model.parameters(), lr=LR)

scheduler = warm_up_cosine_lr_scheduler(optimizer, warm_up_epochs=warm_up_epochs, eta_min=1e-9)

for epoch in range(epochs):
    optimizer.step()
    lrs.append(optimizer.state_dict()['param_groups'][0]['lr'])
    scheduler.step()

plt.figure(figsize=(10, 6))  ![请添加图片描述](https://img-blog.csdnimg.cn/566b2c036b4a44598ae2a5a0548f2550.png?x-oss-process=image/watermark,type_d3F5LXplbmhlaQ,shadow_50,text_Q1NETiBAamFzbmVpaw==,size_20,color_FFFFFF,t_70,g_se,x_16)

plt.plot(lrs, color='r')
plt.text(0, lrs[0], str(lrs[0]))
plt.text(epochs, lrs[-1], str(lrs[-1]))
plt.show()

Pytorch 学习率衰减 之 余弦退火与余弦warmup 自定义学习率衰减scheduler
从图上看,第一个lr非常非常小,导致训练时的,第一个epoch基本上不更新

继承lr_scheduler的类

class WarmupCosineLR(lr_scheduler._LRScheduler):
    def __init__(self, optimizer, lr_min, lr_max, warm_up=0, T_max=10, start_ratio=0.1):
"""
        Description:
            - get warmup consine lr scheduler

        Arguments:
            - optimizer: (torch.optim.*), torch optimizer
            - lr_min: (float), minimum learning rate
            - lr_max: (float), maximum learning rate
            - warm_up: (int),  warm_up epoch or iteration
            - T_max: (int), maximum epoch or iteration
            - start_ratio: (float), to control epoch 0 lr, if ratio=0, then epoch 0 lr is lr_min

        Example:
            <<< epochs = 100
            <<< warm_up = 5
            <<< cosine_lr = WarmupCosineLR(optimizer, 1e-9, 1e-3, warm_up, epochs)
            <<< lrs = []
            <<< for epoch in range(epochs):
            <<<     optimizer.step()
            <<<     lrs.append(optimizer.state_dict()['param_groups'][0]['lr'])
            <<<     cosine_lr.step()
            <<< plt.plot(lrs, color='r')
            <<< plt.show()

"""
        self.lr_min = lr_min
        self.lr_max = lr_max
        self.warm_up = warm_up
        self.T_max = T_max
        self.start_ratio = start_ratio
        self.cur = 0

        super().__init__(optimizer, -1)

    def get_lr(self):
        if (self.warm_up == 0) & (self.cur == 0):
            lr = self.lr_max
        elif (self.warm_up != 0) & (self.cur  self.warm_up):
            if self.cur == 0:
                lr = self.lr_min + (self.lr_max - self.lr_min) * (self.cur + self.start_ratio) / self.warm_up
            else:
                lr = self.lr_min + (self.lr_max - self.lr_min) * (self.cur) / self.warm_up

        else:

            lr = self.lr_min + (self.lr_max - self.lr_min) * 0.5 *\
                            (np.cos((self.cur - self.warm_up) / (self.T_max - self.warm_up) * np.pi) + 1)

        self.cur += 1

        return [lr for base_lr in self.base_lrs]

epochs = 100
warm_up = 5
cosine_lr = WarmupCosineLR(optimizer, 1e-9, 1e-3, warm_up, epochs, 0.1)
lrs = []
for epoch in range(epochs):
    optimizer.step()
    lrs.append(optimizer.state_dict()['param_groups'][0]['lr'])
    cosine_lr.step()

plt.figure(figsize=(10, 6))
plt.plot(lrs, color='r')
plt.text(0, lrs[0], str(lrs[0]))
plt.text(epochs, lrs[-1], str(lrs[-1]))
plt.show()

Pytorch 学习率衰减 之 余弦退火与余弦warmup 自定义学习率衰减scheduler
从图上看出,第一个epoch的lr也不至于非常非常小了,达到了所需预期,当然,如果你说first epoch的lr,你也需要非常非常小(

Original: https://blog.csdn.net/jasneik/article/details/123759399
Author: jasneik
Title: Pytorch 学习率衰减 之 余弦退火与余弦warmup 自定义学习率衰减scheduler

原创文章受到原创版权保护。转载请注明出处:https://www.johngo689.com/708132/

转载文章受原作者版权保护。转载请注明原作者出处!

(0)

大家都在看

  • 【AI教程】AI科研绘图

    AI科研绘图 文章目录 AI科研绘图 * 0. 初识AI – ==常用快捷键(英文输入)==: 1. 绘制基本图形、设置渐变、对齐分布 2. 铅笔工具、偏移路径、扩展、…

    人工智能 2023年7月28日
    055
  • YOLOX论文解读

    文章目录 创新点 算法 * Decoupled head Strong data augmentation Anchor-free Multi positives SimOTA E…

    人工智能 2023年7月10日
    063
  • 朴素贝叶斯分类(python实现)

    算法优劣 参考刘建平老师的博客:朴素贝叶斯算法原理小结 优点: 朴素贝叶斯模型发源于古典数学理论,有稳定的分类效率。 对小规模的数据表现很好,能个处理多分类任务,适合增量式训练,尤…

    人工智能 2023年7月5日
    080
  • VS2022配置OpenCV操作步骤

    1、下载并安装好OpenCV; 2、设置环境变量; 在”电脑(右击)-属性-高级系统设置-环境变量”-“系统变量”,找到path,双…

    人工智能 2023年6月18日
    054
  • halcon 条形码识别(持续更新)

    达到识别目的的最简化结构 *&#x521B;&#x5EFA;&#x6761;&#x7801;&#x8BC6;&#x522B;&amp…

    人工智能 2023年5月28日
    081
  • 快速进行OneHot编码——get_dummies()函数

    data:array-like, Series, or DataFrame 用来获得虚拟指标的数据。 prefix:str, list of str, or dict of str…

    人工智能 2023年7月15日
    062
  • 多目标跟踪

    文章目录 1. 目标跟踪分类 2. 多目标跟踪目前的主要问题 3. 多目标跟踪概述 4. 多目标跟踪方法分类 5. 行人多目标跟踪方法研究进展 * 5.1 基于目标检测的多目标跟踪…

    人工智能 2023年6月16日
    0106
  • 通过prompt方法增强开放领域问答模型

    前言 开放领域问答任务最常见的两个难点就是保证回答的答案具有事实性和时效性,但是模型通常在训练好后就是固定的即权重固定好了,尤其是时效性基本上很难保证。 今天要给大家介绍的这篇pa…

    人工智能 2023年5月28日
    099
  • 两张独立显卡连接两个显示器如何配置

    Applet钢琴模拟程序java源码 2个目标文件,提供基本的音乐编辑功能。编辑音乐软件的朋友,这款实例会对你有所帮助。 Calendar万年历 1个目标文件 EJB 模拟银行AT…

    人工智能 2023年6月10日
    084
  • python利用opencv简单识别红绿灯

    #先装包和环境 import cv2 from PIL import Image import numpy as np #导入视频并自定义 cor_x, cor_y = -1, -…

    人工智能 2023年7月19日
    048
  • 逻辑斯谛(Logistic)回归、参数估计教程

    ### 回答1: 逻辑_斯 _谛 回归( logistic regression)是一种用于分类问题的统计学习方法,属于监督学习中的一种。它的基本思想是通过建立模型去学习不同特征之…

    人工智能 2023年6月17日
    063
  • 蓝牙5.0对比4.2的主要优势

    随着这二年蓝牙模块及各种蓝牙高清无线传输协议的发展,蓝牙无线数传的整体效率有了明显提升,在初期都是优先选择Wi-Fi作为唯一的无线数据传输技术,毕竟在蓝牙5.0标准面世之前,老规格…

    人工智能 2023年6月4日
    083
  • 编程思想与算法leetcode_二分算法详解

    二分算法通常用于有序序列中查找元素: 思路很简单,细节是魔鬼。 一.有序序列中是否存在满足某条件的元素 首先,二分查找的框架: 其次,最基本的查找有序序列中的一个元素 循环的条件为…

    人工智能 2023年6月4日
    069
  • Python pyautogui 图像识别

    本文主要介绍 pyautogui 的 screenshot 和 locateCenterOnScreen 方法 本文仍有问题未解决 screenshot——截取图像,并且可以保存 …

    人工智能 2023年6月19日
    0126
  • 时间序列分析 | Python时间序列预测理论一览

    ; 时间序列分析 | Python时间序列预测理论一览 目录 * – 时间序列分析 | Python时间序列预测理论一览 – + 基本介绍 + 特性描述 +…

    人工智能 2023年7月15日
    043
  • 讯飞AIUI智能机器人5—–让器理解你(语音技术综合应用)

    🍖🍖🍖🍖🍖🍖🍖🍖🍖 🍖🍖🍖🍖🍖🍖🍖🍖 🍖🍖🍖🍖🍖🍖🍖🍖 🍖🍖🍖🍖🍖🍖🍖🍖 🍖🍖🍖🍖🍖🍖🍖🍖 🍖🍖🍖🍖🍖🍖🍖🍖 🍖🍖🍖🍖🍖🍖🍖🍖 🍖🍖🍖🍖🍖🍖🍖🍖 🍖🍖🍖🍖🍖🍖🍖🍖 🍖🍖🍖🍖🍖🍖🍖🍖…

    人工智能 2023年6月23日
    084
亲爱的 Coder【最近整理,可免费获取】👉 最新必读书单  | 👏 面试题下载  | 🌎 免费的AI知识星球