Resnet-18-训练实验-warm up操作

实验数据:cat-dog 二分类,训练集:19871 验证集:3975
实验模型:resnet-18
batchsize:128*2 (一个K80吃128张图片)

存在的问题: 对训练集 accuracy可达0.99 loss=1e-2 -3,然而验证集 accuracy 0.5,loss 很高,试了多个初始学习率(0.1 — 0.0001)都不行

解决上述问题: 采取warm up方法 ,对上述问题有点帮助

训练resnet,由于不finetune,很容易过拟合,paper《Deep Residual Learning for Image Recognition》中对cifar10的实验用了一个trick是 warm up(热身),就是先采用小的学习率(0.01)进行训练,训练了400iterations之后将学习率调整至0.1开始正式训练。

一开始不以为然,我分别用了四个初始学习率 lr=0.1; 0.01; 0.001; 0.0001; 然后每1000个iterations就降低一次lr。然而这四种初始学习率都试过之后,发现,验证集的accuracy怎么都上不去,都是0.5~0.6之间,而训练集的可以到0.99。而resnet采用了batch normalization,在caffe中,batch normalization 就有一个“坑”,就是use_global_stats 的设置问题。training时候是关闭,testing的时候是要打开,deploy也是要打开的。
对于训练集accuracy达0.99,验证集accuracy是0.5+的情况,我以为是batch normalization出问题,于是乎各种捣鼓BN去了,最后试了一下warm up,网络在验证集的loss才有所下降。

来看看warm up 的loss,分别采用 0.01 0.001 0.001 0.0001,gamma=10 ;stepsize在图中已经隔断
lr=0.01;step=1000

lr=0.001;step=500

lr=0.001;step=10000

lr=0.001;step=1000

### Warm Up 训练的概念与方法 Warm Up 是一种用于提升模型训练稳定性和效果的技术,尤其适用于大规模深度学习模型的训练。其核心思想是在训练初期使用较低的学习率,随着训练进程逐步增加至目标学习率。这种方法可以有效缓解因参数随机初始化而导致的梯度过大问题,从而提高训练稳定性。 #### 温暖启动的核心原理 在 mini-batch 梯度下降过程中,较大的 batch size 往往需要较高的学习率来加速收敛。然而,在训练初期,由于模型参数尚未经过充分调整,过高的学习率可能导致训练过程不稳定甚至发散[^4]。因此,通过引入 Warm Up 技术,在最初的若干步或 epoch 中采用较小的学习率,并逐渐将其增大到预定值,能够显著改善这一情况。 #### 实现方式 以下是两种常见的 Warm Up 实现策略: 1. **固定时间间隔后的切换** 此方法规定了一个固定的训练阶段(如前 10 epochs 或 10,000 steps),在此期间保持低学习率;随后切换回正常设定的学习率继续完成剩余部分的训练流程[^2]。例如 ResNet实验表明,在 cifar-10 数据集上的应用中,先以 0.01 的学习率运行约 400 iterations 直至达到一定条件后再转而运用更高的 0.1 学习率进行后续操作[^3]。 2. **渐进式升温 (Gradual Warmup)** 不同于简单的两段划分法,“gradual warmup”则采取更为平滑的方式过渡:从极小初始值开始按线性或其他函数形式连续上调直至标准水平为止。这种方式不仅有助于进一步增强系统的鲁棒性,而且对于超大网络结构尤为适用因为它们可能更加敏感于早期更新幅度的变化。 #### Python代码示例 下面展示如何基于 PyTorch 构建一个带有 Gradual Warmup 功能的学习率调度器: ```python import torch.optim.lr_scheduler as lr_scheduler class GradualWarmupScheduler(lr_scheduler._LRScheduler): """ Gradually warm-up(increasing) learning rate in optimizer. Proposed in 'Accurate, Large Minibatch SGD: Training ImageNet in 1 Hour'. """ def __init__(self, optimizer, multiplier, total_epoch, after_scheduler=None): self.multiplier = multiplier if self.multiplier < 1.: raise ValueError('multiplier should be greater thant or equal to 1.') self.total_epoch = total_epoch self.after_scheduler = after_scheduler super().__init__(optimizer) def get_lr(self): if self.last_epoch > self.total_epoch: if self.after_scheduler: if not self.finished: self.after_scheduler.base_lrs = [base_lr * self.multiplier for base_lr in self.base_lrs] self.finished = True return self.after_scheduler.get_last_lr() return [base_lr * self.multiplier for base_lr in self.base_lrs] return [base_lr * ((self.multiplier - 1.) / self.total_epoch * self.last_epoch + 1.) for base_lr in self.base_lrs] def step_ReduceLROnPlateau(self, metrics, epoch=None): if epoch is None: epoch = self.last_epoch + 1 self.last_epoch = epoch if epoch != 0 else 1 if self.last_epoch <= self.total_epoch: warmup_factor = (self.multiplier - 1.) / self.total_epoch * self.last_epoch + 1. for param_group, lr in zip(self.optimizer.param_groups ,self.base_lrs): param_group['lr'] = lr * warmup_factor else: if epoch == self.total_epoch + 1 and self.after_scheduler: self.after_scheduler.step(metrics, None) else: if self.after_scheduler: self.after_scheduler.step(metrics, None) else: pass def main(): model = ... # your model here optimizer = torch.optim.SGD(model.parameters(), lr=0.01, momentum=0.9, weight_decay=1e-4) scheduler_steplr = lr_scheduler.StepLR(optimizer, step_size=30, gamma=0.1) scheduler_warmup = GradualWarmupScheduler(optimizer, multiplier=8, total_epoch=5, after_scheduler=scheduler_steplr) for epoch in range(100): # 假设总共有100个epochs train(...) validate(...) scheduler_warmup.step() if __name__ == '__main__': main() ``` 上述脚本定义了一类新的调度程序 `GradualWarmupScheduler` ,它可以在指定数量的 Epochs 内执行温和上升的操作,之后可链接其他类型的 LR 调整机制共同作用。 ---
评论 8
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值