cosineannealinglr最直接无需手写公式,按step数余弦衰减,t_max须设为完整周期的step总数,断点续训需手动设last_epoch;onecyclelr先升后降,不适用于单纯平滑下降场景。

PyTorch里用torch.optim.lr_scheduler.CosineAnnealingLR最直接
不需要自己写余弦公式,PyTorch原生就提供了稳定、可复现的实现。它按训练步数(而非epoch)做余弦衰减,终点学习率默认是0,但可通过eta_min设为非零值。
常见错误是把T_max设成总epoch数却忘了模型实际step数远大于此——T_max必须是**scheduler更新一次所需的step总数**,比如每个epoch有100个batch,训练200个epoch,那T_max=20000才对。
实操建议:
-
T_max填的是「调度器完成一个完整余弦周期所需的step数」,不是epoch数 - 若想每个epoch重启一次余弦(即Warm Restarts),改用
CosineAnnealingWarmRestarts - 初始化后必须在每次
optimizer.step()之后调用scheduler.step(),否则不生效 - 如果用了
torch.cuda.amp.GradScaler,scheduler.step()仍需在scaler.step(optimizer)之后调用
为什么last_epoch参数容易被忽略却很关键
默认last_epoch=-1表示从头开始;但如果从中断处恢复训练,必须显式传入已训练的step数(比如last_epoch=5000),否则调度器会重置为初始学习率,导致lr突变。
典型场景:断点续训时加载optimizer和scheduler state_dict后,last_epoch不会自动同步——得手动传参或改scheduler.last_epoch。
示例代码片段:
scheduler = torch.optim.lr_scheduler.CosineAnnealingLR(
optimizer, T_max=20000, eta_min=1e-6, last_epoch=checkpoint['step']
)
和torch.optim.lr_scheduler.OneCycleLR怎么选
两者都含余弦成分,但行为完全不同:CosineAnnealingLR单调下降(可带最小值平台),OneCycleLR先升后降,且默认包含学习率预热(anneal_strategy='cos'只是其中一半)。
如果你明确要「平滑下降到某个底限」,别用OneCycleLR;它更适合配合大batch、强正则的端到端训练流程。
性能差异不大,但兼容性上:CosineAnnealingLR支持任何optimizer,OneCycleLR要求optimizer中所有param_group必须有相同初始lr。
自定义余弦退火(比如带线性warmup)得组合调度器
PyTorch不内置warmup+cosine联合调度,但可以用torch.optim.lr_scheduler.SequentialLR拼接。
注意点:
-
SequentialLR的schedulers列表里,每个scheduler的T_max或total_iters必须对应各自阶段的step数 - 组合时
milestones指「切换到下一个scheduler的step索引」,不是epoch - 不要试图用
LambdaLR手写余弦公式——浮点精度、边界条件(如step=0)易出错,且无法利用state_dict保存/恢复
真正难的不是写公式,而是让warmup结束时刻与cosine起始时刻的lr值严格对齐,稍有偏差就会出现跳变。
大量免费API接口:立即使用
涵盖生活服务API、金融科技API、企业工商API、等相关的API接口服务。免费API接口可安全、合规地连接上下游,为数据API应用能力赋能!











