Gradual Warmup Scheduler

Gradual Warmup Scheduler

1、介绍

从最开始的小学习率开始,每个iteration增大一点,直到最初设置的比较大的学习率。

在这里插入图片描述

其学习率如上图变化所示。

2、实现

这将使用到torch.optim.lr_scheduler中的类,比如torch.optim.lr_scheduler.LambdaLR()

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

它具有一下几个参数:

  • optimizer ,需要调节的优化器
  • lr_lambda ,lambda系数的获取函数或列表
  • last_epoch ,上一个epoch的索引
  • verbose ,如果为True ,则为每次更新打印一条消息

参数更新:

n e w _ l r = λ × i n i t i a l _ l r new\_lr=\lambda×initial\_lr new_lr=λ×initial_lr

而lr_lambda参数传入一个函数,或是列表。

例如

total_epoch = 5
total_step = total_epoch * len(mnist_data_loader_train)
scheduler = LambdaLR(optimizer=optimizer,
                     lr_lambda=lambda step: (step + 1) / total_step if step < total_step else 1)

例如计划在第5个epoch使得学习率达到给定的初始值,那么 λ \lambda λ则可以从一个小数开始,增加至1即可。

则这里的

lambda step: (step + 1) / total_step if step < total_step else 1

就是
{ s t e p + 1 t o t a l _ s t e p , s t e p < t o t a l _ s t e p 1 , s t e p > t o t a l _ s t e p \left\{\begin{matrix}\frac{step+1}{total\_step} ,step<total\_step \\1,step>total\_step \end{matrix}\right. {total_stepstep+1,step<total_step1,step>total_step
而学习率的更新,可以在每一个step更新,也可以每一个epoch更新一次

每一epoch更新一次:

for epoch in range(100):
     train(...)
     validate(...)
     scheduler.step()

或是每一个step更新:

for epoch in range(100):
     '''train(...)'''
     for step in data_loader:
        train()
        scheduler.step()
     validate(...)

3、完整的一个训练mnist实例:

import torchvision.transforms
from torch import nn
import torch
from torch.utils.data import DataLoader
from torchvision.datasets import MNIST
from torch.optim.lr_scheduler import LambdaLR
from tqdm import tqdm


class Model(nn.Module):  # 定义网络

    def __init__(self):
        super(Model, self).__init__()
        self.layer = nn.Sequential(
            nn.Conv2d(1, 32, 3, 2),
            nn.BatchNorm2d(32),
            nn.ReLU(),
            nn.Conv2d(32, 64, 3, 2),
            nn.BatchNorm2d(64),
            nn.ReLU(),
            nn.Conv2d(64, 128, 3, 2),
            nn.BatchNorm2d(128),
            nn.ReLU(),
            nn.Flatten(),
            nn.Linear(512, 10)
        )

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


if __name__ == '__main__':
    """参数"""
    batch_size = 256
    lr = 0.01  # 学习率
    epochs = 100  # 迭代次数
    total_epoch = 5  # 总共经过total_epoch到达最终的学习率

    model = Model()  # 实例化模型
    mnist_train = MNIST('data', download=True, train=True, transform=torchvision.transforms.ToTensor())  # 训练集
    mnist_val = MNIST('data', download=True, train=False, transform=torchvision.transforms.ToTensor())  # 验证集
    mnist_data_loader_train = DataLoader(mnist_train, batch_size, True, drop_last=True)  # 训练集加载器
    mnist_data_loader_val = DataLoader(mnist_val, batch_size, True, drop_last=False)  # 验证集加载器

    optimizer = torch.optim.Adam(model.parameters(), lr)  # 优化器
    total_step = total_epoch * len(mnist_data_loader_train)
    scheduler = LambdaLR(optimizer=optimizer,
                         lr_lambda=lambda step: (step + 1) / total_step if step < total_step else 1)  # 学习速率调度器
    loss_function = nn.CrossEntropyLoss(label_smoothing=0.1)  # 损失函数
    accuracy = 0
    with tqdm(range(epochs), dynamic_ncols=True) as tqdm_range:
        for epoch in tqdm_range:  # 训练迭代过程
            loss_sum = 0
            for i, (x, y_hat) in enumerate(mnist_data_loader_train):
                y = model(x)  # 模型预测
                loss = loss_function(y, y_hat)  # 预测值与真实值做损失

                optimizer.zero_grad()  # 清空梯度
                loss.backward()  # 方向传播
                optimizer.step()  # 梯度下降

                loss_sum += loss.detach().item()  # 统计损失
                scheduler.step()  # 调整学习速率,也可以写在该层for循环外,根据epoch改变学习率
                tqdm_range.set_postfix(
                    ordered_dict={
                        'Epoch': epoch,
                        'Batch': f'{i + 1}/{len(mnist_data_loader_train)}',
                        'Lr': optimizer.param_groups[0]['lr'],
                        'Loss': loss_sum / (i + 1),
                        'Accuracy': accuracy
                    }
                )

            """验证"""
            correct_sum = 0
            for i, (x, y_hat) in enumerate(mnist_data_loader_val):
                y = model(x)
                y = torch.argmax(y, dim=1)
                correct_sum += (y == y_hat).sum().item()
            accuracy = f"{str(correct_sum / len(mnist_val) * 100)[:6]}%"
            print()
y, dim=1)
                correct_sum += (y == y_hat).sum().item()
            accuracy = f"{str(correct_sum / len(mnist_val) * 100)[:6]}%"
            print()
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值