【介绍+代码实现】使用GradualWarmupScheduler进行学习率预热

找了一晚上warmup资料,有用的很少,基本都是互相转载,要不就是讲的很空泛,代码没有可使用的价值。但是最后我还是解决了,于是写一个warmup教程造福大家,这里抛砖引玉了。

一、介绍GradualWarmupScheduler

GradualWarmupScheduler(optimizer, multiplier, total_epoch, after_scheduler)

参数解释
optimizer:优化器
multiplier:当multiplier=1.0时,学习率lr从0开始增到base_lr为止,当multiplier大于1.0时,学习率lr从base_lr开始增到base_lr*multiplier为止。multiplier不能小于1.0。
【那么base_lr又是什么?】
【就是传入优化器的lr,例如optimizer = optim.SGD(net.parameters(), lr=learning_rate, momentum=0.9, weight_decay=weight_decay),base_lr就是learning_rate】
total_epoch:在total_epoch个epoch后达到目标学习率,也就是warmup持续的代数
after_scheduler:在经过total_epoch个epoch以后,所使用的学习率策略。

如果想了解更多细节,比如每个epoch的步长计算方式,可以查看源代码实现链接::pytorch-gradual-warmup-lr/blob/master/warmup_scheduler/scheduler.py

二、如何使用GradualWarmupScheduler

这里以我的代码为例,简单讲解下如何使用GradualWarmupScheduler。

  1. 如果没有warmup_scheduler包的话,需要安装:pip install warmup_scheduler

  2. 我先实现了optimizer,schedular_r(这里我定义的策略是如果测试准确率【mode=‘max’】连续三代不上升【patience=3】,则学习率变为原学习率的0.1倍【factor=0.1】),最后再实现schedular。

  3. schedular的含义是经过10代【total_epoch=10】warm up,学习率由0.01(base_lr)逐渐上升至0.1【multiplier=10】,从第11代开始学习率策略将按照schedular_r进行衰减【after_scheduler=schedular_r】,也就是我第二点中介绍的。

  4. 值得注意的是schedular.step(metrics=test_acc)是在每个epoch进行迭代,且由于我后续使用的策略是ReduceLROnPlateau,所以这里需要传入一个参数metrics=test_acc。

from warmup_scheduler import GradualWarmupScheduler

def train(net, device, epochs, learning_rate, weight_decay):
    optimizer = optim.SGD(net.parameters(), lr=learning_rate, momentum=0.9, weight_decay=weight_decay)
    # if loss do not change for 5 epochs, change lr*0.1
    schedular_r = torch.optim.lr_scheduler.ReduceLROnPlateau(optimizer, mode='max', factor=0.1, patience=3, verbose=True, eps=1e-5)
    schedular = GradualWarmupScheduler(optimizer, multiplier=10, total_epoch=10, after_scheduler=schedular_r)
    #schedular = torch.optim.lr_scheduler.CosineAnnealingLR(optimizer, eta_min=1e-5, T_max=5)
    initepoch = 0
    loss = nn.CrossEntropyLoss()
    best_test_acc = 0

    for epoch in range(initepoch, epochs):  # loop over the dataset multiple times

        net.train()

        timestart = time.time()

        running_loss = 0.0
        total = 0
        correct = 0
        #print(optimizer.param_groups[0]['lr'])
        for i, data in tqdm(enumerate(train_iter)):
            # get the inputs
            inputs, labels = data
            inputs, labels = inputs.to(device), labels.to(device)
            # zero the parameter gradients
            optimizer.zero_grad()
            # forward + backward + optimize
            outputs = net(inputs)
            l = loss(outputs, labels)
            l.backward()
            optimizer.step()
            running_loss += l.item()

            _, predicted = torch.max(outputs.data, 1)
            total += labels.size(0)
            correct += (predicted == labels).sum().item()
            train_acc = 100.0 * correct / total

        print('epoch %d, loss: %.4f,tran Acc: %.3f%%,time:%3f sec, lr: %.7f'
              % (epoch+1, running_loss, train_acc, time.time() - timestart, optimizer.param_groups[0]['lr']))
        print(schedular.last_epoch)

        # test

        net.eval()

        total = 0
        correct = 0
        with torch.no_grad():
            for data in tqdm(test_iter):
                images, labels = data
                images, labels = images.to(device), labels.to(device)
                outputs = net(images)
                # print(outputs.shape)
                _, predicted = torch.max(outputs.data, 1)
                total += labels.size(0)
                correct += (predicted == labels).sum().item()
            test_acc = 100.0 * correct / total
            print('test Acc: %.3f%%' % (test_acc))
            # if epoch > 30:
            #     torch.save(net.state_dict(), '/root/Desktop/cifar-100/checkpoint_512_512_100/' + str(test_acc) + '_Resnet18.pth')
            if test_acc > best_test_acc:
                print('find best! save at checkpoint/cnn_best.pth')
                best_test_acc = test_acc
                best_epoch = epoch
                torch.save(net.state_dict(),
                           '/root/Desktop/exps/cifar100/model_512_100_IF10/best_' + str(best_test_acc) + '_' + str(train_acc) + '_resnet34.pth')

        schedular.step(metrics=test_acc)


    print('Finished Training')
    print('best test acc epoch: %d' % epoch+1)

  • 11
    点赞
  • 34
    收藏
    觉得还不错? 一键收藏
  • 4
    评论
### 回答1: 可以使用学习率调度器来实现学习率的调优,例如 PyTorch 中的 StepLR、ReduceLROnPlateau 等调度器。这些调度器可以根据训练过程中的指标变化自动调整学习率,从而提高模型的性能。 ### 回答2: 在深度学习中,学习率是指定模型在每次迭代中应该跳跃的步长的参数。选择合适的学习率对于优化深度学习模型的训练非常重要。以下是一种可以用代码实现学习率进行调优的方法: 1. 首先,定义一个学习率初始值: ``` learning_rate = 0.001 ``` 2. 然后,定义一个函数或循环来训练模型,并在每次迭代结束后使用以下方法来更新学习率: ``` if current_iteration % update_frequency == 0: # 每隔一定迭代次数更新一次学习率 learning_rate *= update_factor # 根据预先设定的更新因子更新学习率 ``` 其中,`current_iteration`表示当前迭代次数,`update_frequency`表示设定的更新频率,`update_factor`表示学习率的更新因子。 3. 在每次更新学习率后,使用新的学习率来优化模型参数。例如,在使用梯度下降法进行优化时,可以使用如下公式更新模型参数: ``` parameters -= learning_rate * gradients ``` 其中,`parameters`表示模型的参数,`gradients`表示计算得到的梯度。 通过这种方式,可以在训练过程中动态地调整学习率,使其逐渐减小或增大,以寻找到更好的模型性能。这样的调优方法可以提高模型在训练过程中的收敛速度和稳定性。不同的更新频率和更新因子的选择可能会导致不同的效果,因此需要根据具体情况进行调试和优化。 ### 回答3: 在深度学习中,学习率的选择对于算法的性能至关重要。过小的学习率会导致梯度下降的收敛速度过慢,而过大的学习率则容易导致算法发散。因此,调优学习率是深度学习模型中非常重要的一步。 调优学习率的方法主要有两种:手动调优和自动调优。 手动调优是指根据经验和观察模型的训练过程来调整学习率。一般来说,开始训练时可以选择一个较大的学习率,然后逐渐减小学习率,直到模型达到最佳性能。观察模型在训练过程中损失函数的变化情况,如果损失函数一直下降,说明学习率较合适;如果损失函数震荡或不收敛,说明学习率过大或过小。 自动调优学习率的方法有很多,其中一种常用的方法是使用学习率调度器。学习率调度器根据模型训练的进展情况自动调整学习率。具体来说,在每个迭代更新参数之前,学习率调度器通过提前设定好的规则来决定当前的学习率。常见的学习率调度方法有StepLR、MultiStepLR、ReduceLROnPlateau等。 以PyTorch为例,可以使用其提供的learning rate scheduler实现学习率自动调优。首先,需要定义一个优化器,如SGD或Adam,并设置一个初始学习率。然后,根据需求选择一个学习率调度器,并将Optimizer和调度器作为参数传入。接下来,在每个epoch之后调用调度器的step方法来更新学习率。调度器会根据预设的规则调整学习率,并将其应用到优化器上。 总之,在深度学习中,学习率的选择是一个很重要的问题。通过手动调优或使用学习率调度器,我们可以更好地控制学习率的变化,从而提高模型的性能和收敛速度。
评论 4
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值