PyTorch实战用CosineAnnealingWarmRestarts优化你的深度学习模型附完整代码深度学习模型的训练过程中学习率的选择和调整策略往往决定了模型能否收敛到最优解。传统的固定学习率或简单线性衰减策略在面对复杂非凸优化问题时常常显得力不从心。本文将深入解析PyTorch中的CosineAnnealingWarmRestarts学习率调度器通过完整代码示例和实战技巧帮助你掌握这一强大的学习率优化工具。1. 为什么需要动态学习率策略在深度学习模型训练中学习率控制着参数更新的步长。过大的学习率会导致模型在最优解附近震荡甚至发散而过小的学习率则会使训练过程变得极其缓慢。更复杂的是模型在不同训练阶段对学习率的需求是不同的。传统学习率调整策略如StepLR和LinearLR存在几个明显缺陷StepLR在预设的固定epoch数进行学习率跳跃式衰减这种突变可能导致训练不稳定LinearLR学习率线性递减无法适应损失曲面的复杂变化固定学习率完全忽视了训练不同阶段对学习率的不同需求相比之下余弦退火策略通过模拟物理退火过程为学习率调整提供了更平滑、更智能的方案。2. 余弦退火原理深度解析余弦退火学习率策略的核心思想来源于材料科学中的退火过程。在物理学中退火是指将材料加热到高温后缓慢冷却以消除内部应力获得更稳定的晶体结构。类比到深度学习我们可以将学习率视为温度通过精心设计的冷却计划让模型参数结晶到最优状态。2.1 基本余弦退火公式标准的余弦退火学习率变化遵循以下公式η_t η_min 0.5*(η_max - η_min)*(1 cos(π*t/T))其中η_t 是当前epoch的学习率η_min 是预设的最小学习率η_max 是预设的最大学习率t 是当前epoch计数T 是总epoch数这个公式产生的学习率变化曲线具有以下特点平滑过渡避免了学习率的突变使训练更加稳定自适应衰减初期衰减较慢中期加快后期再次变慢周期性重启可以周期性地重启学习率帮助跳出局部最优2.2 带预热的余弦退火改进基本余弦退火策略的一个改进是加入预热(warmup)阶段。在训练初期模型参数通常处于随机初始化状态直接使用较大学习率可能导致不稳定。预热阶段让学习率从很小的值线性增长到预设最大值为模型提供一个热身过程。预热阶段的数学表达为η_t η_min (η_max - η_min)*t/T_warmup其中T_warmup是预热阶段的epoch数。3. PyTorch实现详解PyTorch提供了CosineAnnealingWarmRestarts调度器下面我们通过完整代码示例来解析其实现细节。3.1 基础使用示例import torch import torch.nn as nn import torch.optim as optim from torch.optim.lr_scheduler import CosineAnnealingWarmRestarts # 定义简单模型 model nn.Sequential( nn.Linear(10, 50), nn.ReLU(), nn.Linear(50, 2) ) # 定义优化器 optimizer optim.SGD(model.parameters(), lr0.1) # 定义调度器 scheduler CosineAnnealingWarmRestarts( optimizer, T_050, # 第一个周期的epoch数 T_mult1, # 周期长度倍增系数 eta_min0.001, # 最小学习率 last_epoch-1 ) # 训练循环 for epoch in range(100): # 训练代码... optimizer.step() scheduler.step() current_lr optimizer.param_groups[0][lr] print(fEpoch {epoch}, lr: {current_lr:.6f})3.2 关键参数解析CosineAnnealingWarmRestarts的主要参数包括参数名类型描述默认值T_0int第一个周期的epoch数-T_multfloat周期长度倍增系数1eta_minfloat最小学习率0last_epochint上一个epoch索引-1提示T_mult参数控制每个新周期的长度变化。设置为1表示所有周期长度相同大于1则每个周期长度会倍增。3.3 自定义实现解析PyTorch内置的调度器已经足够强大但有时我们需要更灵活的控制。下面是一个自定义实现的简化版本import math class CustomCosineAnnealingWarmRestarts: def __init__(self, optimizer, T_0, T_mult1, eta_min0, last_epoch-1): self.optimizer optimizer self.T_0 T_0 self.T_mult T_mult self.eta_min eta_min self.last_epoch last_epoch self.T_cur last_epoch self.cycle 0 self.base_lrs [group[lr] for group in optimizer.param_groups] def step(self, epochNone): if epoch is None: epoch self.last_epoch 1 self.last_epoch epoch if epoch self.T_0: if self.T_mult 1: self.T_cur epoch % self.T_0 self.cycle epoch // self.T_0 else: n int(math.log((epoch / self.T_0 * (self.T_mult - 1) 1), self.T_mult)) self.cycle n self.T_cur epoch - self.T_0 * (self.T_mult ** n - 1) / (self.T_mult - 1) self.T_i self.T_0 * self.T_mult ** n else: self.T_i self.T_0 self.T_cur epoch for i, param_group in enumerate(self.optimizer.param_groups): param_group[lr] self.eta_min 0.5 * (self.base_lrs[i] - self.eta_min) * \ (1 math.cos(math.pi * self.T_cur / self.T_i))4. 实战调参技巧在实际项目中应用余弦退火策略时以下几个技巧可以帮助你获得更好的效果4.1 初始学习率选择通常设置为标准学习率的2-5倍可以通过小批量数据上的快速实验确定合适范围与优化器类型相关Adam通常需要比SGD更小的初始学习率4.2 周期长度设置第一个周期T_0通常设为总epoch数的1/4到1/2对于T_mult固定长度T_mult1逐步增加T_mult2每次周期长度翻倍注意太短的周期可能导致学习率变化过于频繁影响收敛稳定性。4.3 最小学习率设置通常设为初始学习率的1/10到1/100太小的eta_min可能导致训练后期进展缓慢可以结合验证集表现动态调整4.4 预热策略虽然PyTorch内置的CosineAnnealingWarmRestarts不直接支持预热但我们可以组合使用from torch.optim.lr_scheduler import LinearLR, SequentialLR optimizer optim.SGD(model.parameters(), lr0.1) # 预热阶段前10个epoch线性增加学习率 warmup LinearLR(optimizer, start_factor0.01, total_iters10) # 主训练阶段余弦退火 cosine_annealing CosineAnnealingWarmRestarts( optimizer, T_050, eta_min0.001 ) # 组合调度器 scheduler SequentialLR( optimizer, schedulers[warmup, cosine_annealing], milestones[10] )5. 多任务训练中的学习率调度在实际项目中我们经常需要同时优化多个损失函数。不同任务可能对学习率有不同的敏感度这时可以考虑5.1 分层学习率策略optimizer optim.SGD([ {params: model.backbone.parameters(), lr: 0.1}, {params: model.head.parameters(), lr: 0.2} ]) scheduler CosineAnnealingWarmRestarts( optimizer, T_050, eta_min0.001 )5.2 自适应任务权重结合余弦退火动态调整多任务权重def weighted_loss(loss1, loss2, epoch, T_0): # 使用余弦变化调整权重 weight 0.5 * (1 math.cos(math.pi * epoch / T_0)) return weight * loss1 (1 - weight) * loss26. 常见问题与解决方案6.1 训练初期震荡严重可能原因及解决方案初始学习率过高 → 降低初始学习率或增加预热阶段预热不足 → 延长预热epoch数批量大小不合适 → 调整批量大小或使用梯度累积6.2 训练后期进展缓慢可能原因及解决方案最小学习率设置过低 → 适当提高eta_min周期长度过长 → 缩短T_0或增大T_mult模型已收敛 → 早停或调整模型结构6.3 周期性性能波动可能原因及解决方案周期重启时学习率跳跃过大 → 减小最大最小学习率差距周期长度不一致 → 使用固定周期长度(T_mult1)优化器动量不合适 → 调整优化器的动量参数7. 进阶应用结合其他优化策略7.1 与SWA结合随机权重平均(Stochastic Weight Averaging)可以与余弦退火完美配合from torch.optim.swa_utils import AveragedModel, SWALR # 创建SWA模型 swa_model AveragedModel(model) # 在训练后期切换到SWA调度器 swa_scheduler SWALR(optimizer, swa_lr0.05) # 训练循环 for epoch in range(100): # ...正常训练... if epoch 50: swa_model.update_parameters(model) swa_scheduler.step() else: scheduler.step()7.2 与梯度裁剪结合在NLP等任务中可以结合梯度裁剪使用max_norm 1.0 # 最大梯度范数 for epoch in range(100): # ...前向传播和损失计算... loss.backward() torch.nn.utils.clip_grad_norm_(model.parameters(), max_norm) optimizer.step() scheduler.step()7.3 与混合精度训练结合from torch.cuda.amp import GradScaler, autocast scaler GradScaler() for epoch in range(100): optimizer.zero_grad() with autocast(): outputs model(inputs) loss criterion(outputs, targets) scaler.scale(loss).backward() scaler.step(optimizer) scaler.update() scheduler.step()8. 可视化分析工具为了更好地理解学习率的变化过程我们可以使用可视化工具import matplotlib.pyplot as plt def plot_lr_schedule(scheduler, num_epochs): lrs [] for epoch in range(num_epochs): scheduler.step() lrs.append(optimizer.param_groups[0][lr]) plt.figure(figsize(10, 5)) plt.plot(lrs) plt.xlabel(Epoch) plt.ylabel(Learning Rate) plt.title(Learning Rate Schedule) plt.grid() plt.show() # 使用示例 optimizer optim.SGD([torch.randn(2, 2, requires_gradTrue)], lr0.1) scheduler CosineAnnealingWarmRestarts(optimizer, T_050, T_mult2) plot_lr_schedule(scheduler, 200)这种可视化可以帮助我们直观地看到学习率随训练过程的变化趋势便于调整调度器参数。9. 不同任务中的参数设置建议9.1 计算机视觉任务任务类型T_0T_multeta_min预热epoch图像分类50-1001-21e-45-10目标检测30-5011e-53-5语义分割50-8025e-55-89.2 自然语言处理任务任务类型T_0T_multeta_min预热epoch文本分类20-3011e-53-5机器翻译30-5015e-65-10语言模型50-10021e-510-159.3 强化学习任务算法类型T_0T_multeta_min预热epochDQN20-3011e-40PPO50-10011e-55SAC30-5025e-5310. 完整实战案例下面我们以一个图像分类任务为例展示完整的实现流程import torch import torchvision import torch.nn as nn import torch.optim as optim from torch.optim.lr_scheduler import CosineAnnealingWarmRestarts, LinearLR, SequentialLR from torch.utils.data import DataLoader # 1. 准备数据 transform torchvision.transforms.Compose([ torchvision.transforms.ToTensor(), torchvision.transforms.Normalize((0.5,), (0.5,)) ]) train_set torchvision.datasets.MNIST(root./data, trainTrue, downloadTrue, transformtransform) train_loader DataLoader(train_set, batch_size128, shuffleTrue) # 2. 定义模型 class CNNClassifier(nn.Module): def __init__(self): super().__init__() self.conv1 nn.Conv2d(1, 32, 3, 1) self.conv2 nn.Conv2d(32, 64, 3, 1) self.dropout nn.Dropout(0.5) self.fc1 nn.Linear(9216, 128) self.fc2 nn.Linear(128, 10) def forward(self, x): x self.conv1(x) x nn.ReLU()(x) x self.conv2(x) x nn.ReLU()(x) x nn.MaxPool2d(2)(x) x self.dropout(x) x torch.flatten(x, 1) x self.fc1(x) x nn.ReLU()(x) x self.fc2(x) return x model CNNClassifier() # 3. 定义优化器和调度器 optimizer optim.AdamW(model.parameters(), lr0.001) # 预热阶段 warmup LinearLR(optimizer, start_factor0.01, total_iters10) # 余弦退火阶段 cosine_annealing CosineAnnealingWarmRestarts( optimizer, T_050, T_mult1, eta_min1e-5 ) # 组合调度器 scheduler SequentialLR( optimizer, schedulers[warmup, cosine_annealing], milestones[10] ) # 4. 训练循环 device torch.device(cuda if torch.cuda.is_available() else cpu) model.to(device) criterion nn.CrossEntropyLoss() for epoch in range(100): model.train() total_loss 0 for batch_idx, (data, target) in enumerate(train_loader): data, target data.to(device), target.to(device) optimizer.zero_grad() output model(data) loss criterion(output, target) loss.backward() optimizer.step() total_loss loss.item() scheduler.step() print(fEpoch {epoch}, Loss: {total_loss/len(train_loader):.4f}, LR: {optimizer.param_groups[0][lr]:.6f})这个完整示例展示了如何在真实项目中实现数据准备和加载模型定义优化器和调度器配置完整的训练循环学习率预热与余弦退火的组合使用
PyTorch实战:用CosineAnnealingWarmRestarts优化你的深度学习模型(附完整代码)
发布时间:2026/7/15 5:26:30
PyTorch实战用CosineAnnealingWarmRestarts优化你的深度学习模型附完整代码深度学习模型的训练过程中学习率的选择和调整策略往往决定了模型能否收敛到最优解。传统的固定学习率或简单线性衰减策略在面对复杂非凸优化问题时常常显得力不从心。本文将深入解析PyTorch中的CosineAnnealingWarmRestarts学习率调度器通过完整代码示例和实战技巧帮助你掌握这一强大的学习率优化工具。1. 为什么需要动态学习率策略在深度学习模型训练中学习率控制着参数更新的步长。过大的学习率会导致模型在最优解附近震荡甚至发散而过小的学习率则会使训练过程变得极其缓慢。更复杂的是模型在不同训练阶段对学习率的需求是不同的。传统学习率调整策略如StepLR和LinearLR存在几个明显缺陷StepLR在预设的固定epoch数进行学习率跳跃式衰减这种突变可能导致训练不稳定LinearLR学习率线性递减无法适应损失曲面的复杂变化固定学习率完全忽视了训练不同阶段对学习率的不同需求相比之下余弦退火策略通过模拟物理退火过程为学习率调整提供了更平滑、更智能的方案。2. 余弦退火原理深度解析余弦退火学习率策略的核心思想来源于材料科学中的退火过程。在物理学中退火是指将材料加热到高温后缓慢冷却以消除内部应力获得更稳定的晶体结构。类比到深度学习我们可以将学习率视为温度通过精心设计的冷却计划让模型参数结晶到最优状态。2.1 基本余弦退火公式标准的余弦退火学习率变化遵循以下公式η_t η_min 0.5*(η_max - η_min)*(1 cos(π*t/T))其中η_t 是当前epoch的学习率η_min 是预设的最小学习率η_max 是预设的最大学习率t 是当前epoch计数T 是总epoch数这个公式产生的学习率变化曲线具有以下特点平滑过渡避免了学习率的突变使训练更加稳定自适应衰减初期衰减较慢中期加快后期再次变慢周期性重启可以周期性地重启学习率帮助跳出局部最优2.2 带预热的余弦退火改进基本余弦退火策略的一个改进是加入预热(warmup)阶段。在训练初期模型参数通常处于随机初始化状态直接使用较大学习率可能导致不稳定。预热阶段让学习率从很小的值线性增长到预设最大值为模型提供一个热身过程。预热阶段的数学表达为η_t η_min (η_max - η_min)*t/T_warmup其中T_warmup是预热阶段的epoch数。3. PyTorch实现详解PyTorch提供了CosineAnnealingWarmRestarts调度器下面我们通过完整代码示例来解析其实现细节。3.1 基础使用示例import torch import torch.nn as nn import torch.optim as optim from torch.optim.lr_scheduler import CosineAnnealingWarmRestarts # 定义简单模型 model nn.Sequential( nn.Linear(10, 50), nn.ReLU(), nn.Linear(50, 2) ) # 定义优化器 optimizer optim.SGD(model.parameters(), lr0.1) # 定义调度器 scheduler CosineAnnealingWarmRestarts( optimizer, T_050, # 第一个周期的epoch数 T_mult1, # 周期长度倍增系数 eta_min0.001, # 最小学习率 last_epoch-1 ) # 训练循环 for epoch in range(100): # 训练代码... optimizer.step() scheduler.step() current_lr optimizer.param_groups[0][lr] print(fEpoch {epoch}, lr: {current_lr:.6f})3.2 关键参数解析CosineAnnealingWarmRestarts的主要参数包括参数名类型描述默认值T_0int第一个周期的epoch数-T_multfloat周期长度倍增系数1eta_minfloat最小学习率0last_epochint上一个epoch索引-1提示T_mult参数控制每个新周期的长度变化。设置为1表示所有周期长度相同大于1则每个周期长度会倍增。3.3 自定义实现解析PyTorch内置的调度器已经足够强大但有时我们需要更灵活的控制。下面是一个自定义实现的简化版本import math class CustomCosineAnnealingWarmRestarts: def __init__(self, optimizer, T_0, T_mult1, eta_min0, last_epoch-1): self.optimizer optimizer self.T_0 T_0 self.T_mult T_mult self.eta_min eta_min self.last_epoch last_epoch self.T_cur last_epoch self.cycle 0 self.base_lrs [group[lr] for group in optimizer.param_groups] def step(self, epochNone): if epoch is None: epoch self.last_epoch 1 self.last_epoch epoch if epoch self.T_0: if self.T_mult 1: self.T_cur epoch % self.T_0 self.cycle epoch // self.T_0 else: n int(math.log((epoch / self.T_0 * (self.T_mult - 1) 1), self.T_mult)) self.cycle n self.T_cur epoch - self.T_0 * (self.T_mult ** n - 1) / (self.T_mult - 1) self.T_i self.T_0 * self.T_mult ** n else: self.T_i self.T_0 self.T_cur epoch for i, param_group in enumerate(self.optimizer.param_groups): param_group[lr] self.eta_min 0.5 * (self.base_lrs[i] - self.eta_min) * \ (1 math.cos(math.pi * self.T_cur / self.T_i))4. 实战调参技巧在实际项目中应用余弦退火策略时以下几个技巧可以帮助你获得更好的效果4.1 初始学习率选择通常设置为标准学习率的2-5倍可以通过小批量数据上的快速实验确定合适范围与优化器类型相关Adam通常需要比SGD更小的初始学习率4.2 周期长度设置第一个周期T_0通常设为总epoch数的1/4到1/2对于T_mult固定长度T_mult1逐步增加T_mult2每次周期长度翻倍注意太短的周期可能导致学习率变化过于频繁影响收敛稳定性。4.3 最小学习率设置通常设为初始学习率的1/10到1/100太小的eta_min可能导致训练后期进展缓慢可以结合验证集表现动态调整4.4 预热策略虽然PyTorch内置的CosineAnnealingWarmRestarts不直接支持预热但我们可以组合使用from torch.optim.lr_scheduler import LinearLR, SequentialLR optimizer optim.SGD(model.parameters(), lr0.1) # 预热阶段前10个epoch线性增加学习率 warmup LinearLR(optimizer, start_factor0.01, total_iters10) # 主训练阶段余弦退火 cosine_annealing CosineAnnealingWarmRestarts( optimizer, T_050, eta_min0.001 ) # 组合调度器 scheduler SequentialLR( optimizer, schedulers[warmup, cosine_annealing], milestones[10] )5. 多任务训练中的学习率调度在实际项目中我们经常需要同时优化多个损失函数。不同任务可能对学习率有不同的敏感度这时可以考虑5.1 分层学习率策略optimizer optim.SGD([ {params: model.backbone.parameters(), lr: 0.1}, {params: model.head.parameters(), lr: 0.2} ]) scheduler CosineAnnealingWarmRestarts( optimizer, T_050, eta_min0.001 )5.2 自适应任务权重结合余弦退火动态调整多任务权重def weighted_loss(loss1, loss2, epoch, T_0): # 使用余弦变化调整权重 weight 0.5 * (1 math.cos(math.pi * epoch / T_0)) return weight * loss1 (1 - weight) * loss26. 常见问题与解决方案6.1 训练初期震荡严重可能原因及解决方案初始学习率过高 → 降低初始学习率或增加预热阶段预热不足 → 延长预热epoch数批量大小不合适 → 调整批量大小或使用梯度累积6.2 训练后期进展缓慢可能原因及解决方案最小学习率设置过低 → 适当提高eta_min周期长度过长 → 缩短T_0或增大T_mult模型已收敛 → 早停或调整模型结构6.3 周期性性能波动可能原因及解决方案周期重启时学习率跳跃过大 → 减小最大最小学习率差距周期长度不一致 → 使用固定周期长度(T_mult1)优化器动量不合适 → 调整优化器的动量参数7. 进阶应用结合其他优化策略7.1 与SWA结合随机权重平均(Stochastic Weight Averaging)可以与余弦退火完美配合from torch.optim.swa_utils import AveragedModel, SWALR # 创建SWA模型 swa_model AveragedModel(model) # 在训练后期切换到SWA调度器 swa_scheduler SWALR(optimizer, swa_lr0.05) # 训练循环 for epoch in range(100): # ...正常训练... if epoch 50: swa_model.update_parameters(model) swa_scheduler.step() else: scheduler.step()7.2 与梯度裁剪结合在NLP等任务中可以结合梯度裁剪使用max_norm 1.0 # 最大梯度范数 for epoch in range(100): # ...前向传播和损失计算... loss.backward() torch.nn.utils.clip_grad_norm_(model.parameters(), max_norm) optimizer.step() scheduler.step()7.3 与混合精度训练结合from torch.cuda.amp import GradScaler, autocast scaler GradScaler() for epoch in range(100): optimizer.zero_grad() with autocast(): outputs model(inputs) loss criterion(outputs, targets) scaler.scale(loss).backward() scaler.step(optimizer) scaler.update() scheduler.step()8. 可视化分析工具为了更好地理解学习率的变化过程我们可以使用可视化工具import matplotlib.pyplot as plt def plot_lr_schedule(scheduler, num_epochs): lrs [] for epoch in range(num_epochs): scheduler.step() lrs.append(optimizer.param_groups[0][lr]) plt.figure(figsize(10, 5)) plt.plot(lrs) plt.xlabel(Epoch) plt.ylabel(Learning Rate) plt.title(Learning Rate Schedule) plt.grid() plt.show() # 使用示例 optimizer optim.SGD([torch.randn(2, 2, requires_gradTrue)], lr0.1) scheduler CosineAnnealingWarmRestarts(optimizer, T_050, T_mult2) plot_lr_schedule(scheduler, 200)这种可视化可以帮助我们直观地看到学习率随训练过程的变化趋势便于调整调度器参数。9. 不同任务中的参数设置建议9.1 计算机视觉任务任务类型T_0T_multeta_min预热epoch图像分类50-1001-21e-45-10目标检测30-5011e-53-5语义分割50-8025e-55-89.2 自然语言处理任务任务类型T_0T_multeta_min预热epoch文本分类20-3011e-53-5机器翻译30-5015e-65-10语言模型50-10021e-510-159.3 强化学习任务算法类型T_0T_multeta_min预热epochDQN20-3011e-40PPO50-10011e-55SAC30-5025e-5310. 完整实战案例下面我们以一个图像分类任务为例展示完整的实现流程import torch import torchvision import torch.nn as nn import torch.optim as optim from torch.optim.lr_scheduler import CosineAnnealingWarmRestarts, LinearLR, SequentialLR from torch.utils.data import DataLoader # 1. 准备数据 transform torchvision.transforms.Compose([ torchvision.transforms.ToTensor(), torchvision.transforms.Normalize((0.5,), (0.5,)) ]) train_set torchvision.datasets.MNIST(root./data, trainTrue, downloadTrue, transformtransform) train_loader DataLoader(train_set, batch_size128, shuffleTrue) # 2. 定义模型 class CNNClassifier(nn.Module): def __init__(self): super().__init__() self.conv1 nn.Conv2d(1, 32, 3, 1) self.conv2 nn.Conv2d(32, 64, 3, 1) self.dropout nn.Dropout(0.5) self.fc1 nn.Linear(9216, 128) self.fc2 nn.Linear(128, 10) def forward(self, x): x self.conv1(x) x nn.ReLU()(x) x self.conv2(x) x nn.ReLU()(x) x nn.MaxPool2d(2)(x) x self.dropout(x) x torch.flatten(x, 1) x self.fc1(x) x nn.ReLU()(x) x self.fc2(x) return x model CNNClassifier() # 3. 定义优化器和调度器 optimizer optim.AdamW(model.parameters(), lr0.001) # 预热阶段 warmup LinearLR(optimizer, start_factor0.01, total_iters10) # 余弦退火阶段 cosine_annealing CosineAnnealingWarmRestarts( optimizer, T_050, T_mult1, eta_min1e-5 ) # 组合调度器 scheduler SequentialLR( optimizer, schedulers[warmup, cosine_annealing], milestones[10] ) # 4. 训练循环 device torch.device(cuda if torch.cuda.is_available() else cpu) model.to(device) criterion nn.CrossEntropyLoss() for epoch in range(100): model.train() total_loss 0 for batch_idx, (data, target) in enumerate(train_loader): data, target data.to(device), target.to(device) optimizer.zero_grad() output model(data) loss criterion(output, target) loss.backward() optimizer.step() total_loss loss.item() scheduler.step() print(fEpoch {epoch}, Loss: {total_loss/len(train_loader):.4f}, LR: {optimizer.param_groups[0][lr]:.6f})这个完整示例展示了如何在真实项目中实现数据准备和加载模型定义优化器和调度器配置完整的训练循环学习率预热与余弦退火的组合使用