神经网络中学习率 warmup 策略为什么有效?学习率应该怎么变化会比较好?

本文探讨了随着BatchSize增大,如何调整学习率以保持模型稳定训练。讲解了Warmup策略防止初期模型不稳定,以及Decay防止后期震荡。提出了Linear+Warmup+Decay的综合方案,并给出了调整学习率的具体步骤和示例代码。建议的学习率范围和实践技巧也做了分享。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

Linear Scale

随着Batch Size增大,学习率也需要增大

如何调整:Batch Size理解、如何调整batch size和学习率之间的关系?_batch size 比较大时,需要把learning rate也调大吗-CSDN博客

Warmup

在训练最开始,模型中绝大多数参数都是随机初始化的,与最终模型很远。一开始就使用一个很大的LR,会增加不确定性。所以在训练最开始,先使用一个较小的LR,训练几轮Epoch后,再使用较大的LR。

1.直观理解就是最开始的时候,loss大,如果学习率太大,gradient也就弄的很大,容易崩,结果什么都学不到。所以最开始步子小一些,等模型收敛到合适的位置,loss不再爆炸,再加大学习率开始快速学习。

和你说的sgd的用法也不矛盾,但是那个的前提是模型不容易跑崩。

2.有同感,实际跑起来的时候,一开始如果保证网络不崩掉,lr就得调小,直观上到平台期以后(实际上并没有到),再做decay,loss更降不动,倒是增大lr反而又能观察到loss的下降。随机权值并不见得是个好的初始化方式,warm-up倒也可以看做某种程度上的“预训练”

通俗的解释:

3.开车进入一个新城市的时候,一开始总是要小心翼翼驾驶的,否则容易出事故,过一会了大致了解了周边环境了才能提速。

Decay

一直使用较大的LR也有问题,在训练中后期,过大的LR可能导致模型在最优解附近震荡,无法快速收敛。

所以,在中后期,需要将LR进行一些衰减(Decay)。ResNet论文中最初使用的Step Decay:每训练30个Epoch,LR衰减为刚才的0.1倍。还有Cosine衰减

Step Decay 和 cosine decay

最好的学习率调整方案:

Linear + Warmup + Decay

将以上三种LR策略组合起来,可以形成一个完整的LR策略:

  1. 根据Batch Size大小,线性地缩放LR基准值,
  2. 前几个Epoch使用较小的LR先进行Warmup逐渐增大学习率,
  3. 之后逐渐对LR进行Decay衰减。

整个训练过程随着epoch增加,学习率的变化方案

一般的学习率应该怎么选择?

batch-size用8-64

学习率10的-4到10的-2。

示例代码:

rcg用的就是这样的lr调整代码

此处给一个示例代码,到时候按需要调整即可

import math
import argparse

def adjust_learning_rate_cosine_epoch(optimizer, epoch, args):
    """Decay the learning rate with half-cycle cosine after warmup"""
    if epoch < args.warmup_epochs:
        lr = args.lr * epoch / args.warmup_epochs 
    else:
        lr = args.min_lr + (args.lr - args.min_lr) * 0.5 * \
            (1. + math.cos(math.pi * (epoch - args.warmup_epochs) / (args.epochs - args.warmup_epochs)))
    for param_group in optimizer.param_groups:
        if "lr_scale" in param_group:
            param_group["lr"] = lr * param_group["lr_scale"]
        else:
            param_group["lr"] = lr
    return lr

def adjust_learning_rate_cosine_step(optimizer, current_step, lr, **kwargs):
    """
    Linear + Warmup + cosine-Decay
    用于step为单位的程序
    :param optimizer:
    :param step:
    :param kwargs:
    :return:
    """

    warmup_steps = kwargs['warmup_steps']
    total_steps = kwargs['total_steps']
    lr = lr
    min_lr = kwargs['min_lr']


    if current_step < warmup_steps:
        lr = lr * current_step / warmup_steps
    else:
        lr = min_lr + (lr - min_lr) * 0.5 * (1. + math.cos(math.pi * (current_step - warmup_steps) / (total_steps - warmup_steps)))

    for param_group in optimizer.param_groups:
        if "lr_scale" in param_group:
            param_group["lr"] = lr * param_group["lr_scale"]
        else:
            param_group["lr"] = lr

    return lr




def adjust_learning_rate_const(optimizer, epoch, args):
    """Decay the learning rate with half-cycle cosine after warmup"""
    if epoch < args.warmup_epochs:
        lr = args.lr * epoch / args.warmup_epochs
    else:
        lr = args.lr
    for param_group in optimizer.param_groups:
        if "lr_scale" in param_group:
            param_group["lr"] = lr * param_group["lr_scale"]
        else:
            param_group["lr"] = lr
    return lr




def get_args_parser():
    parser = argparse.ArgumentParser('RDM training', add_help=False)
    parser.add_argument('--epochs', default=400, type=int)
    parser.add_argument('--accum_iter', default=1, type=int, help='Accumulate gradient iterations (for increasing the effective batch size under memory constraints)')

    # Optimizer parameters
    parser.add_argument('--weight_decay', type=float, default=0.05, help='weight decay (default: 0.05)')
    parser.add_argument('--lr', type=float, default=None, metavar='LR', help='learning rate (absolute lr)')
    parser.add_argument('--blr', type=float, default=1e-3, metavar='LR', help='base learning rate: absolute_lr = base_lr * total_batch_size')
    parser.add_argument('--min_lr', type=float, default=0., metavar='LR', help='decay lower lr bound for cyclic schedulers that hit 0')
    parser.add_argument('--cosine_lr', action='store_true', help='Use cosine lr scheduling.')
    parser.add_argument('--warmup_epochs', default=0, type=int)


# data_iter_step / len(data_loader) + epoch:是将学习率细致调整到了epoch中的step内,而不是简单的一个epoch用一个lr
adjust_learning_rate_cosine_step(optimizer, current_step, lr, **args)
# forward
# backward
# optimizer

# updata_lr
lr = optimizer.param_groups[0]["lr"]


Learning Rate Schedule:CNN学习率调整策略 - 知乎

神经网络中 warmup 策略为什么有效;有什么理论解释么? - 知乎

<think>好的,我现在需要解决用户关于VGG16神经网络学习率调整的问题。首先,我得回忆一下学习率在训练神经网络中的作用。学习率决定了参数更新的步长,过大会导致震荡甚至不收敛,过小则训练缓慢。VGG16作为深度卷积网络,层数较多,调整学习率尤为重要。 接下来,我应该考虑常见的调整策略。比如预热(Warmup)、阶段式下降(Step Decay)、余弦退火(Cosine Annealing)等。用户可能需要具体的例子,所以我得选几种典型的调整方法,并结合VGG16的结构来说明。 例如,预热方法适用于训练初期,避免初始梯度较大导致的不稳定。阶段式下降则是每隔一定epoch将学习率按比例降低,适合VGG16这种深网络。还有自适应优化器如Adam,但用户可能想了解手动调整的方法。 然后,我需要考虑如何将这些策略转化为具体的代码示例。比如在PyTorch中,可以使用学习率调度器。比如StepLR和CosineAnnealingLR。要展示不同调度器的使用方式,并解释参数设置的原因。 另外,用户可能需要知道调整学习率的原因和效果。比如,为什么在VGG16中使用阶段式下降?因为随着训练进行,参数接近最优,需要更小的步长来微调。而余弦退火能帮助跳出局部最优。 还需要注意不同层的学习率设置。VGG16的浅层和深层可能需要不同的学习率,比如微调时,全连接层学习率较高,卷积层较低。这可以通过参数组来设置,但用户的问题可能更关注整体调整,所以可能先不提,或者简要说明。 最后,检查例子是否正确,比如代码是否语法正确,学习率调整是否符合逻辑。比如StepLR的step_size和gamma参数是否合理,余弦退火的T_max设置是否正确。确保示例能实际运行,不会误导用户。 总结步骤:介绍学习率的重要性,列举几种调整策略,结合VGG16给出每种策略的代码示例,并解释参数和效果。可能还需要比较不同方法的优缺点,帮助用户选择适合的方案。</think>以下是关于VGG16神经网络学习率调整的逐步说明及示例: --- ### 一、学习率调整的必要性 在VGG16训练中,学习率($\alpha$)直接影响: 1. 收敛速度:过小导致训练缓慢 2. 模型精度:过大会跳过最优解 3. 训练稳定性:不合理值会导致梯度震荡 ### 二、基础调整策略示例 #### 1. 固定学习率衰减(Step Decay) $$ \alpha_{new} = \alpha \times \gamma^{floor(epoch/step\_size)} $$ ```python # PyTorch实现 optimizer = torch.optim.SGD(model.parameters(), lr=0.1) scheduler = torch.optim.lr_scheduler.StepLR(optimizer, step_size=30, gamma=0.1) # 每个epoch执行 scheduler.step() ``` #### 2. 余弦退火(Cosine Annealing) $$ \alpha_t = \alpha_{min} + \frac{1}{2}(\alpha_{max}-\alpha_{min})(1+\cos(\frac{T_{cur}}{T_{max}}\pi)) $$ ```python scheduler = torch.optim.lr_scheduler.CosineAnnealingLR( optimizer, T_max=100, eta_min=1e-5) ``` ### 三、VGG16专用策略 #### 1. 分层学习率(适用于微调) ```python # 卷积层参数组 conv_params = [p for n, p in model.named_parameters() if 'classifier' not in n] # 全连接层参数组 fc_params = [p for n, p in model.named_parameters() if 'classifier' in n] optimizer = torch.optim.SGD([ {'params': conv_params, 'lr': 1e-4}, {'params': fc_params, 'lr': 1e-3} ], momentum=0.9) ``` #### 2. 预热训练(Warmup) 前5个epoch线性增加学习率: ```python def warmup_lr(epoch, warmup_epochs=5, base_lr=0.1): return base_lr * (epoch + 1) / warmup_epochs for epoch in range(100): if epoch < warmup_epochs: lr = warmup_lr(epoch) for param_group in optimizer.param_groups: param_group['lr'] = lr else: scheduler.step() ``` ### 四、推荐组合策略 ```python # 使用1cycle策略(PyTorch示例) scheduler = torch.optim.lr_scheduler.OneCycleLR( optimizer, max_lr=0.1, total_steps=100, pct_start=0.3 # 30%时间用于学习率增长 ) ``` ### 五、验证调整效果 使用TensorBoard监控: ```python from torch.utils.tensorboard import SummaryWriter writer = SummaryWriter() for epoch in range(epochs): writer.add_scalar('Learning Rate', optimizer.param_groups[0]['lr'], epoch) writer.add_scalar('Training Loss', loss.item(), epoch) ``` --- ### 关键参数建议(ImageNet数据集) | 策略 | 初始学习率 | 衰减时机 | 最终学习率 | |--------------|------------|---------------|------------| | 标准训练 | 0.1 | 30/60/90 epoch| 0.001 | | 迁移学习 | 0.01 | 每20 epoch | 0.0001 | | 小样本训练 | 0.001 | 余弦退火 | 1e-6 | 实际应用中建议通过验证集准确率变化选择最佳调整策略,当验证集准确率连续3个epoch不提升时触发学习率衰减。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Pengsen Ma

太谢谢了

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值