目录

写在前面

一、LambdaLR

二、PolynomialLR

三、CyclicLR

四、CosineAnnealingWarmRestarts

五、SequentialLR

六、ChainedScheduler


写在前面

        上一篇文章介绍了一些常用的学习率衰减策略,下面我们再来看看稍微冷门一点的,废话不多说,我们开始。

        图解Pytorch学习率衰减策略(一):

        

一、LambdaLR

        基于自定义 lambda 函数调整学习率,极为灵活。可以根据训练的需要,自由地设计学习率的变化规律。

示例:

import torch
import torch.optim as optim
from torch.optim.lr_scheduler import LambdaLR
import matplotlib.pyplot as plt


# 创建一个简单的模型
class SimpleModel(torch.nn.Module):
    def __init__(self):
        super(SimpleModel, self).__init__()
        self.fc = torch.nn.Linear(10, 1)

    def forward(self, x):
        return self.fc(x)


# 定义学习率调度的 Lambda 函数
def lambda_lr(epoch):
    # 返回每个 epoch 的学习率调整因子
    return 0.95 ** epoch  # 每个 epoch 将学习率乘以 0.95


# 初始化模型、优化器和学习率调度器
model = SimpleModel()
optimizer = optim.SGD(model.parameters(), lr=0.1)  # 初始学习率为 0.1

# LambdaLR 学习率调度器
scheduler = LambdaLR(optimizer, lr_lambda=lambda_lr)

# 模拟一个训练过程
num_epochs = 10
num_batches = 10  # 每轮训练的批次数
lr_history = []
for epoch in range(num_epochs):
    print(f"\nEpoch {epoch + 1}/{num_epochs}")

    for batch in range(num_batches):
        # 模拟前向传递
        inputs = torch.randn(64, 10)  # 批次大小 64,特征维度 10
        targets = torch.randn(64, 1)
        outputs = model(inputs)
        loss = torch.nn.functional.mse_loss(outputs, targets)

        # 反向传播和优化
        optimizer.zero_grad()
        loss.backward()
        optimizer.step()

    # 更新学习率
    scheduler.step()

    # 打印每轮的学习率
    current_lr = optimizer.param_groups[0]['lr']
    lr_history.append(current_lr)
    print(f"End of Epoch {epoch + 1}: Current Learning Rate: {current_lr:.6f}")

# 绘制学习率曲线
plt.figure(figsize=(10, 6))
plt.plot(range(num_epochs), lr_history, marker='o')
plt.xlabel('Epoch')
plt.ylabel('Learning Rate')
plt.title('Learning Rate Schedule')
plt.grid(True)
plt.show()
  • 1.
  • 2.
  • 3.
  • 4.
  • 5.
  • 6.
  • 7.
  • 8.
  • 9.
  • 10.
  • 11.
  • 12.
  • 13.
  • 14.
  • 15.
  • 16.
  • 17.
  • 18.
  • 19.
  • 20.
  • 21.
  • 22.
  • 23.
  • 24.
  • 25.
  • 26.
  • 27.
  • 28.
  • 29.
  • 30.
  • 31.
  • 32.
  • 33.
  • 34.
  • 35.
  • 36.
  • 37.
  • 38.
  • 39.
  • 40.
  • 41.
  • 42.
  • 43.
  • 44.
  • 45.
  • 46.
  • 47.
  • 48.
  • 49.
  • 50.
  • 51.
  • 52.
  • 53.
  • 54.
  • 55.
  • 56.
  • 57.
  • 58.
  • 59.
  • 60.
  • 61.
  • 62.
  • 63.
  • 64.

参数:
        lr_lambda: 一个函数或函数列表,决定每个 epoch 的学习率调整比例。

学习率变化曲线:

图解Pytorch学习率衰减策略(二)_深度学习

使用场景:
        适用于需要高度自定义学习率策略的场景,适合对训练过程有特殊要求的任务。

推荐程度:一般

二、PolynomialLR

        多项式衰减,通常在训练的最后阶段将学习率降至极低值,适合需要缓慢收敛的任务。它常常用于迭代次数已知的训练任务。

多项式公式如下:

图解Pytorch学习率衰减策略(二)_python_02

示例:

import torch
import torch.optim as optim
from torch.optim.lr_scheduler import PolynomialLR
import matplotlib.pyplot as plt


# 创建一个简单的模型
class SimpleModel(torch.nn.Module):
    def __init__(self):
        super(SimpleModel, self).__init__()
        self.fc = torch.nn.Linear(10, 1)

    def forward(self, x):
        return self.fc(x)


# 初始化模型、优化器和学习率调度器
model = SimpleModel()
initial_lr = 0.1
optimizer = optim.SGD(model.parameters(), lr=initial_lr)  # 初始学习率为 0.1

# 将初始学习率保存到优化器的参数组中
for param_group in optimizer.param_groups:
    param_group['initial_lr'] = initial_lr

# PolynomialLR 学习率调度器
num_epochs = 20
lr_history = []
scheduler = PolynomialLR(optimizer,
                         total_iters=20,  # The number of steps that the scheduler decays the learning rate.
                         power=1)  # The power of the polynomial.

# 模拟一个训练过程
num_batches = 10  # 每轮训练的批次数
for epoch in range(num_epochs):
    print(f"\nEpoch {epoch + 1}/{num_epochs}")

    for batch in range(num_batches):
        # 模拟前向传递
        inputs = torch.randn(64, 10)  # 批次大小 64,特征维度 10
        targets = torch.randn(64, 1)
        outputs = model(inputs)
        loss = torch.nn.functional.mse_loss(outputs, targets)

        # 反向传播和优化
        optimizer.zero_grad()
        loss.backward()
        optimizer.step()

    # 更新学习率
    scheduler.step()

    # 打印每轮的学习率
    current_lr = optimizer.param_groups[0]['lr']
    lr_history.append(current_lr)
    print(f"End of Epoch {epoch + 1}: Current Learning Rate: {current_lr:.6f}")
# 绘制学习率曲线
plt.figure(figsize=(20, 6))
plt.plot(range(num_epochs), lr_history, marker='o')
plt.xlabel('Epoch')
plt.ylabel('Learning Rate')
plt.title('Learning Rate Schedule')
plt.grid(True)
plt.show()
  • 1.
  • 2.
  • 3.
  • 4.
  • 5.
  • 6.
  • 7.
  • 8.
  • 9.
  • 10.
  • 11.
  • 12.
  • 13.
  • 14.
  • 15.
  • 16.
  • 17.
  • 18.
  • 19.
  • 20.
  • 21.
  • 22.
  • 23.
  • 24.
  • 25.
  • 26.
  • 27.
  • 28.
  • 29.
  • 30.
  • 31.
  • 32.
  • 33.
  • 34.
  • 35.
  • 36.
  • 37.
  • 38.
  • 39.
  • 40.
  • 41.
  • 42.
  • 43.
  • 44.
  • 45.
  • 46.
  • 47.
  • 48.
  • 49.
  • 50.
  • 51.
  • 52.
  • 53.
  • 54.
  • 55.
  • 56.
  • 57.
  • 58.
  • 59.
  • 60.
  • 61.
  • 62.
  • 63.
  • 64.

参数:

        total_iters:学习率衰减的步数
        power:多项式的幂,这个数越大,曲线越向左下弯

学习率变化曲线:

图解Pytorch学习率衰减策略(二)_pytorch_03

使用场景:
        适用于需要在训练的最后阶段将学习率降得非常低的场景,通常在一些长时间训练的任务中使用。

推荐程度:很少用,不推荐

三、CyclicLR

        学习率在两个边界值之间循环变化,可以防止模型陷入局部最优,有助于早期训练探索。常用于防止模型陷入局部最优。

  示例:

import torch
import torch.optim as optim
import torch.nn as nn
import matplotlib.pyplot as plt


# 定义一个简单的模型
class SimpleModel(nn.Module):
    def __init__(self):
        super(SimpleModel, self).__init__()
        self.fc = nn.Linear(10, 1)

    def forward(self, x):
        return self.fc(x)


# 创建模型实例
model = SimpleModel()

# 定义优化器
optimizer = optim.SGD(model.parameters(), lr=0.1)

# 定义 CyclicLR 调度器
scheduler = optim.lr_scheduler.CyclicLR(
    optimizer,
    base_lr=0.001,
    max_lr=0.01,
    step_size_up=10,
    step_size_down=8,
    mode='triangular'
)

# 存储每轮的学习率
lr_list = []

# 模拟训练过程
num_epochs = 20
for epoch in range(num_epochs):
    # 模拟训练步骤
    optimizer.zero_grad()
    inputs = torch.randn(10)
    targets = torch.randn(1)
    outputs = model(inputs)
    loss = nn.MSELoss()(outputs, targets)
    loss.backward()
    optimizer.step()

    # 更新学习率
    scheduler.step()

    # 记录学习率
    lr = optimizer.param_groups[0]['lr']
    lr_list.append(lr)
    print(f'Epoch {epoch + 1}/{num_epochs}, Learning Rate: {lr:.6f}')

# 绘制学习率曲线
plt.plot(range(1, num_epochs + 1), lr_list, marker='o')
plt.xlabel('Epoch')
plt.ylabel('Learning Rate')
plt.title('CyclicLR Learning Rate Curve')
plt.grid()
plt.show()
  • 1.
  • 2.
  • 3.
  • 4.
  • 5.
  • 6.
  • 7.
  • 8.
  • 9.
  • 10.
  • 11.
  • 12.
  • 13.
  • 14.
  • 15.
  • 16.
  • 17.
  • 18.
  • 19.
  • 20.
  • 21.
  • 22.
  • 23.
  • 24.
  • 25.
  • 26.
  • 27.
  • 28.
  • 29.
  • 30.
  • 31.
  • 32.
  • 33.
  • 34.
  • 35.
  • 36.
  • 37.
  • 38.
  • 39.
  • 40.
  • 41.
  • 42.
  • 43.
  • 44.
  • 45.
  • 46.
  • 47.
  • 48.
  • 49.
  • 50.
  • 51.
  • 52.
  • 53.
  • 54.
  • 55.
  • 56.
  • 57.
  • 58.
  • 59.
  • 60.
  • 61.
  • 62.

参数:          

        base_lr: 学习率的下限。
        max_lr: 学习率的上限。
        step_size_up: 学习率上升step_size_up步。
        step_size_down: 学习率下降step_size_down步。
        mode :可选参数有三个,triangular、triangular2 和 exp_range ,代表了不同的学习率调整方式。
                "triangular"模式下,学习率在周期内按三角波形变化。在每个周期中,学习率从 base_lr 增加到 max_lr,然后再减少回 base_lr。 
                "triangular2"与 "triangular" 模式类似,但每个周期的学习率峰值逐渐减小。学习率在每个周期内以三角波形变化,但每个周期的 max_lr 会减半。                 
                "exp_range" 在每个周期内,学习率的变化按照指数衰减的方式进行。学习率从 base_lr 增加到 max_lr,然后按指数衰减回 base_lr。

使用场景:
        适合于需要避免局部最优且探索较大学习率范围的任务,如早期训练阶段或复杂优化问题。

学习率变化曲线:

图解Pytorch学习率衰减策略(二)_使用场景_04

使用场景:
        适用于训练过程中需要探索不同学习率,尤其在早期阶段有助于跳出局部最优解。

推荐程度:不常用,不推荐

四、CosineAnnealingWarmRestarts

        CosineAnnealingWarmRestarts 是余弦退火和周期性重新启动的结合。这种策略在每个周期内,学习率按照余弦函数曲线下降,然后在周期结束时重置为初始值并进入下一个周期。

示例:

import torch
import torch.optim as optim
import matplotlib.pyplot as plt

# 定义模型(这里只是一个占位符)
model = torch.nn.Linear(10, 1)  # 例如一个简单的线性模型

# 定义优化器
optimizer = optim.SGD(model.parameters(), lr=0.1)

# 定义学习率调度器
scheduler = optim.lr_scheduler.CosineAnnealingWarmRestarts(optimizer, T_0=10, T_mult=2)

# 记录学习率的变化
lr_list = []

# 训练过程
for epoch in range(200):  # 迭代20轮
    # 模拟一次前向和反向传播(这里只是占位符)
    optimizer.zero_grad()
    outputs = model(torch.randn(10))  # 模拟输入
    loss = outputs.sum()  # 假设损失是输出的总和
    loss.backward()
    optimizer.step()

    # 更新学习率
    scheduler.step()

    # 记录当前学习率
    current_lr = optimizer.param_groups[0]['lr']
    lr_list.append(current_lr)

    # 打印当前学习率
    print(f'Epoch {epoch + 1}: Learning Rate = {current_lr}')

# 绘制学习率曲线
plt.figure(figsize=(10, 5))
plt.plot(range(1, 201), lr_list, marker='o')
plt.title('Learning Rate Schedule')
plt.xlabel('Epoch')
plt.ylabel('Learning Rate')
plt.grid(True)
plt.show()
  • 1.
  • 2.
  • 3.
  • 4.
  • 5.
  • 6.
  • 7.
  • 8.
  • 9.
  • 10.
  • 11.
  • 12.
  • 13.
  • 14.
  • 15.
  • 16.
  • 17.
  • 18.
  • 19.
  • 20.
  • 21.
  • 22.
  • 23.
  • 24.
  • 25.
  • 26.
  • 27.
  • 28.
  • 29.
  • 30.
  • 31.
  • 32.
  • 33.
  • 34.
  • 35.
  • 36.
  • 37.
  • 38.
  • 39.
  • 40.
  • 41.
  • 42.
  • 43.

参数:
        T_0: 初始周期的步数。
        T_mult: 每次重启后周期步数的倍增因子。
        eta_min: 最小学习率。

学习率变化曲线:

图解Pytorch学习率衰减策略(二)_反向传播_05

使用场景:
        适用于各种类型的模型和任务,尤其是那些训练周期较长、训练过程复杂的情况。因此,不论是图像分类、自然语言处理、生成模型还是强化学习任务,都可以考虑使用这种调度策略。

推荐程度:推荐

五、SequentialLR

        组合多个学习率调度器,按顺序执行不同策略,提供了更高的灵活性。例如,你可以先使用 StepLR,然后在后期切换到 ExponentialLR。

示例:

import torch
import torch.optim as optim
import torch.nn as nn
import matplotlib.pyplot as plt


# 定义一个简单的模型
class SimpleModel(nn.Module):
    def __init__(self):
        super(SimpleModel, self).__init__()
        self.fc = nn.Linear(10, 1)

    def forward(self, x):
        return self.fc(x)


# 创建模型实例
model = SimpleModel()

# 定义一个简单的优化器
optimizer = optim.SGD(model.parameters(), lr=0.1)

# 定义学习率调度器的两个阶段
scheduler = torch.optim.lr_scheduler.SequentialLR(
    optimizer,
    schedulers=[
        optim.lr_scheduler.StepLR(optimizer, step_size=2, gamma=0.5),
        optim.lr_scheduler.ExponentialLR(optimizer, gamma=0.9)
    ],
    milestones=[10]
)

# 记录学习率
lrs = []

# 模拟训练过程
num_epochs = 20
for epoch in range(num_epochs):
    # 训练步骤(省略)
    optimizer.step()

    # 更新学习率调度器
    scheduler.step()

    # 记录当前学习率
    current_lr = optimizer.param_groups[0]['lr']
    lrs.append(current_lr)

    # 打印当前学习率
    print(f'Epoch {epoch + 1}/{num_epochs}, Learning Rate: {current_lr:.6f}')

# 绘制学习率曲线
plt.plot(range(num_epochs), lrs, marker='o')
plt.xlabel('Epoch')
plt.ylabel('Learning Rate')
plt.title('Learning Rate Schedule')
plt.grid()
plt.show()
  • 1.
  • 2.
  • 3.
  • 4.
  • 5.
  • 6.
  • 7.
  • 8.
  • 9.
  • 10.
  • 11.
  • 12.
  • 13.
  • 14.
  • 15.
  • 16.
  • 17.
  • 18.
  • 19.
  • 20.
  • 21.
  • 22.
  • 23.
  • 24.
  • 25.
  • 26.
  • 27.
  • 28.
  • 29.
  • 30.
  • 31.
  • 32.
  • 33.
  • 34.
  • 35.
  • 36.
  • 37.
  • 38.
  • 39.
  • 40.
  • 41.
  • 42.
  • 43.
  • 44.
  • 45.
  • 46.
  • 47.
  • 48.
  • 49.
  • 50.
  • 51.
  • 52.
  • 53.
  • 54.
  • 55.
  • 56.
  • 57.
  • 58.

参数:
        schedulers: 包含多个调度器的列表。
        milestones: 一个列表,定义每个调度器的切换点。

学习率变化曲线:

图解Pytorch学习率衰减策略(二)_使用场景_06

使用场景:
        适用于需要在训练的不同阶段使用不同学习率策略的复杂训练任务,如从预训练到微调的过程。

推荐程度:不推荐,用的不多。

六、ChainedScheduler

        多个调度器链在一起同时执行,适用于需要结合多种学习率调整策略的任务。

示例:

import torch
import torch.optim as optim
import torch.nn as nn
import matplotlib.pyplot as plt
from torch.optim.lr_scheduler import ChainedScheduler, StepLR, ExponentialLR


# 定义一个简单的模型
class SimpleModel(nn.Module):
    def __init__(self):
        super(SimpleModel, self).__init__()
        self.fc = nn.Linear(10, 1)

    def forward(self, x):
        return self.fc(x)


# 创建模型实例
model = SimpleModel()

# 定义一个简单的优化器
optimizer = optim.SGD(model.parameters(), lr=0.1)

# 定义两个需要结合的学习率调度器
scheduler = ChainedScheduler([StepLR(optimizer, step_size=2, gamma=0.9),
                              ExponentialLR(optimizer, gamma=0.9)])

# 记录学习率
lrs = []

# 模拟训练过程
num_epochs = 20
for epoch in range(num_epochs):
    # 训练步骤(省略)
    optimizer.step()

    # 更新学习率调度器
    scheduler.step()

    # 记录当前学习率
    current_lr = optimizer.param_groups[0]['lr']
    lrs.append(current_lr)

    # 打印当前学习率
    print(f'Epoch {epoch + 1}/{num_epochs}, Learning Rate: {current_lr:.6f}')

# 绘制学习率曲线
plt.plot(range(num_epochs), lrs, marker='o')
plt.xlabel('Epoch')
plt.ylabel('Learning Rate')
plt.title('Learning Rate Schedule')
plt.grid()
plt.show()
  • 1.
  • 2.
  • 3.
  • 4.
  • 5.
  • 6.
  • 7.
  • 8.
  • 9.
  • 10.
  • 11.
  • 12.
  • 13.
  • 14.
  • 15.
  • 16.
  • 17.
  • 18.
  • 19.
  • 20.
  • 21.
  • 22.
  • 23.
  • 24.
  • 25.
  • 26.
  • 27.
  • 28.
  • 29.
  • 30.
  • 31.
  • 32.
  • 33.
  • 34.
  • 35.
  • 36.
  • 37.
  • 38.
  • 39.
  • 40.
  • 41.
  • 42.
  • 43.
  • 44.
  • 45.
  • 46.
  • 47.
  • 48.
  • 49.
  • 50.
  • 51.
  • 52.
  • 53.

参数:
        schedulers: 需要链在一起的调度器列表。

学习率变化曲线:

图解Pytorch学习率衰减策略(二)_使用场景_07

使用场景:
        适用于希望结合多种学习率调整策略的复杂任务。

推荐程度:不推荐,这个功能比较抽象,从没见谁用过。

        学习率衰减策略就到这里,关注不迷路(*^▽^*)

关注订阅号了解更多精品文章

图解Pytorch学习率衰减策略(二)_反向传播_08