深度学习——学习率衰减方法

一、学习率衰减的基本思想

学习率衰减(Learning Rate Scheduling)是在训练过程中逐步降低学习率的策略。训练初期使用较大学习率实现快速收敛,训练后期减小学习率使模型在最优解附近精细调整,避免震荡。


二、等间隔学习率衰减(StepLR)

策略说明

每隔固定数量的 epoch,学习率乘以一个衰减系数。衰减节奏均匀,简单直观。

公式

\[lr_{epoch} = lr_{initial} \times \gamma^{\lfloor \frac{epoch}{step\_size} \rfloor} \]

其中:

  • \(lr_{initial}\):初始学习率
  • \(\gamma\):衰减系数
  • \(step\_size\):衰减间隔(多少个 epoch 衰减一次)
  • \(\lfloor \cdot \rfloor\):向下取整

三、指定间隔学习率衰减(MultiStepLR)

策略说明

在预先指定的几个特定 epoch 节点进行学习率衰减,而非固定间隔。可根据任务难度灵活设置衰减时机。

公式

\[lr_{epoch} = lr_{initial} \times \gamma^{count} \]

其中 \(count\) 是当前 epoch 之前已经跨越的 milestone(指定节点)数量。


四、指数学习率衰减(ExponentialLR)

策略说明

每一个 epoch 都对学习率进行一次指数衰减,学习率呈平滑的指数下降曲线,没有阶梯式突变。

公式

\[lr_{epoch} = lr_{initial} \times \gamma^{epoch} \]

其中:

  • \(lr_{initial}\):初始学习率
  • \(\gamma\):每轮的衰减底数
  • \(epoch\):当前轮数

五、三种策略对比

对比维度 StepLR(等间隔) MultiStepLR(指定间隔) ExponentialLR(指数)
衰减时机 固定间隔 自定义节点 每轮都衰减
衰减曲线 阶梯式下降 阶梯式下降(不均匀) 平滑指数下降
灵活度 中等 最高 较低
调参难度 简单 较难 中等

六、代码实现

导包

import torch
from torch import optim
import matplotlib

1. 定义函数,演示:等间隔学习率衰减

def dm01():
    # 1. 定义变量,记录初始的学习率,训练轮数,每轮训练的批次数
    lr,epochs,iteration = 0.1,200,10
    # 2. 创建数据集,y_true,x,w
    # 真实值
    y_true = torch.tensor([0])
    # 输入特征
    x = torch.tensor(data=[1.0],dtype=torch.float32)
    # 权重参数w,需要自动微分
    w = torch.tensor([1.0],dtype=torch.float32,requires_grad=True)
    # 3. 创建优化器对象,动量法:加速模型收敛,减少震荡
    # 参1:待优化的参数;参2:学习率;参3:动量系数
    optimizer = torch.optim.SGD([w],lr=lr,momentum=0.9)
    # 4. 创建学习率衰减对象
    # 思路1:创建等间隔学习率衰减对象.
    # 参1:优化器对象,参2:间隔的轮数(多少轮衰减一次学习率);参3:学习率衰减对象
    scheduler = optim.lr_scheduler.StepLR(optimizer,step_size=50,gamma=0.5)

    # 5.创建两个列表,分别表示:训练的轮数,每轮训练用的学习率
    # epoch_list = [1,2,3,...,50,51,52,...,...,200]
    # lr_list = [0.1,0.1,0.1,...,0.05,.....,0.025,...,0.0125]
    lr_list,epoch_list = [],[]

    # 6. 循环遍历训练轮数,进行具体的训练
    for epoch in range(epochs):  # epoch: 0~199
        # 7. 获取当前轮数和学习率,并保存到列表中
        epoch_list.append(epoch)
        lr_list.append(scheduler.get_last_lr()) # 获取最后的lr

        # 8. 循环遍历,每轮每批次进行训练
        for batch in range(iteration):
            # 9. 先计算预测值,然后基于损失函数计算损失
            y_pred = w * x
            # 10. 计算损失
            loss = (y_pred - y_true).pow(2)
            # 11. 梯度清零 + 反向传播 + 优化器更新参数
            optimizer.zero_grad()
            loss.backward()
            optimizer.step()
        # 12.更新学习率.
        scheduler.step()
    # 13. 打印结果
    print(f'lr_list:{lr_list},epoch_list:{epoch_list}')
    # 14. 可视化
    # x轴:训练的轮数,y轴:每轮训练用的学习率
    plt.plot(epoch_list,lr_list)
    plt.xlabel('Epoch')
    plt.ylabel('Learning Rate')
    plt.legend(['lr'])
    plt.show()

2. 定义函数,演示:指定间隔学习率衰减

def dm02():
    # 1. 定义变量,记录初始的学习率,训练轮数,每轮训练的批次数
    lr,epochs,iteration = 0.1,200,10
    # 2. 创建数据集,y_true,x,w
    # 真实值
    y_true = torch.tensor([0])
    # 输入特征
    x = torch.tensor(data=[1.0],dtype=torch.float32)
    # 权重参数w,需要自动微分
    w = torch.tensor([1.0],dtype=torch.float32,requires_grad=True)
    # 3. 创建优化器对象,动量法:加速模型收敛,减少震荡
    # 参1:待优化的参数;参2:学习率;参3:动量系数
    optimizer = torch.optim.SGD([w],lr=lr,momentum=0.9)
    # 4. 创建学习率衰减对象
    # 思路1:创建等间隔学习率衰减对象.
    # 参1:优化器对象,参2:间隔的轮数(多少轮衰减一次学习率);参3:学习率衰减对象
    # scheduler = optim.lr_scheduler.StepLR(optimizer,step_size=50,gamma=0.5)
    # 思路2:创建指定间隔学习率衰减对象.
    # 定义变量,记录要修改学习率的轮数
    milestones = [50,125,160]
    # 参1:优化器对象,参2:间隔的轮数(多少轮衰减一次学习率);参3:学习率衰减对象
    scheduler = optim.lr_scheduler.MultiStepLR(optimizer,milestones = milestones,gamma=0.5)
    # 5.创建两个列表,分别表示:训练的轮数,每轮训练用的学习率
    # epoch_list = [1,2,3,...,50,51,52,...,...,200]
    # lr_list = [0.1,0.1,0.1,...,0.05,.....,0.025,...,0.0125]
    lr_list,epoch_list = [],[]

    # 6. 循环遍历训练轮数,进行具体的训练
    for epoch in range(epochs):  # epoch: 0~199
        # 7. 获取当前轮数和学习率,并保存到列表中
        epoch_list.append(epoch)
        lr_list.append(scheduler.get_last_lr()) # 获取最后的lr

        # 8. 循环遍历,每轮每批次进行训练
        for batch in range(iteration):
            # 9. 先计算预测值,然后基于损失函数计算损失
            y_pred = w * x
            # 10. 计算损失
            loss = (y_pred - y_true).pow(2)
            # 11. 梯度清零 + 反向传播 + 优化器更新参数
            optimizer.zero_grad()
            loss.backward()
            optimizer.step()
        # 12.更新学习率.
        scheduler.step()
    # 13. 打印结果
    print(f'lr_list:{lr_list},epoch_list:{epoch_list}')
    # 14. 可视化
    # x轴:训练的轮数,y轴:每轮训练用的学习率
    plt.plot(epoch_list,lr_list)
    plt.xlabel('Epoch')
    plt.ylabel('Learning Rate')
    plt.legend(['lr'])
    plt.show()

3.定义函数,演示:创建指数间隔衰减

def dm03():
    # 1. 定义变量,记录初始的学习率,训练轮数,每轮训练的批次数
    lr,epochs,iteration = 0.1,200,10
    # 2. 创建数据集,y_true,x,w
    # 真实值
    y_true = torch.tensor([0])
    # 输入特征
    x = torch.tensor(data=[1.0],dtype=torch.float32)
    # 权重参数w,需要自动微分
    w = torch.tensor([1.0],dtype=torch.float32,requires_grad=True)
    # 3. 创建优化器对象,动量法:加速模型收敛,减少震荡
    # 参1:待优化的参数;参2:学习率;参3:动量系数
    optimizer = torch.optim.SGD([w],lr=lr,momentum=0.9)
    # 4. 创建学习率衰减对象
    # 思路3:创建指数间隔衰减对象
    scheduler = optim.lr_scheduler.ExponentialLR(optimizer,gamma=0.95)
    # 5.创建两个列表,分别表示:训练的轮数,每轮训练用的学习率
    # epoch_list = [1,2,3,...,50,51,52,...,...,200]
    # lr_list = [0.1,0.1,0.1,...,0.05,.....,0.025,...,0.0125]
    lr_list,epoch_list = [],[]

    # 6. 循环遍历训练轮数,进行具体的训练
    for epoch in range(epochs):  # epoch: 0~199
        # 7. 获取当前轮数和学习率,并保存到列表中
        epoch_list.append(epoch)
        lr_list.append(scheduler.get_last_lr()) # 获取最后的lr

        # 8. 循环遍历,每轮每批次进行训练
        for batch in range(iteration):
            # 9. 先计算预测值,然后基于损失函数计算损失
            y_pred = w * x
            # 10. 计算损失
            loss = (y_pred - y_true).pow(2)
            # 11. 梯度清零 + 反向传播 + 优化器更新参数
            optimizer.zero_grad()
            loss.backward()
            optimizer.step()
        # 12.更新学习率.
        scheduler.step()
    # 13. 打印结果
    print(f'lr_list:{lr_list},epoch_list:{epoch_list}')
    # 14. 可视化
    # x轴:训练的轮数,y轴:每轮训练用的学习率
    plt.plot(epoch_list,lr_list)
    plt.xlabel('Epoch')
    plt.ylabel('Learning Rate')
    plt.legend(['lr'])
    plt.show()

4.测试

dm01()
dm02()
dm03()
posted @ 2026-07-17 17:31  王新文  阅读(3)  评论(0)    收藏  举报