介绍
PyTorch 中的 torch.optim.AdamW 优化器,它是Adam 优化器的权重衰减改进版,解决了原始 Adam 权重衰减实现的缺陷,是目前深度学习(尤其是大模型、CV/NLP 任务)中最常用的优化器之一,PyTorch 从 1.2.0 版本开始正式支持。
为什么需要 AdamW?
原始 Adam 优化器的权重衰减(L2 正则)是嵌入在梯度更新步骤中的,会和动量(momentum)、自适应学习率相互干扰,导致权重衰减的实际效果远弱于预期。
AdamW 的核心改进是将权重衰减和梯度更新解耦:
- 梯度更新仅由 Adam 的自适应学习率+动量逻辑计算;
- 权重衰减单独作为独立的步骤直接作用在模型参数上,保证衰减效果精准生效。
简单说:AdamW = 正确实现的权重衰减 + 原始 Adam,在相同超参数下,AdamW 的泛化能力、收敛稳定性通常优于 Adam。
使用
和 PyTorch 其他优化器(SGD、Adam)的使用流程完全一致,核心是定义优化器时传入模型参数+超参数,训练中执行optimizer.step()更新参数、optimizer.zero_grad()清空梯度。
语法
torch.optim.AdamW(
params,
lr=0.001,
betas=(0.9, 0.999),
eps=1e-08,
weight_decay=0.01,
amsgrad=False,
foreach=None,
maximize=False,
capturable=False,
differentiable=False,
fused=None
)
参数详解
🔴 必传参数(无默认值,必须指定)
| 参数 | 类型 | 含义 |
|---|---|---|
params |
迭代器/列表 | 模型的可训练参数,几乎都是传model.parameters();也可以传参数分组字典(如之前讲的分lr/weight_decay) |
🟠 核心可调参数(需根据任务调优,AdamW的关键)
| 参数 | 类型 | 默认值 | 常用值 | 核心含义 |
|---|---|---|---|---|
lr |
float | 0.001(1e-3) | 1e-3/CV;1e-4/NLP/大模型 | 基础学习率,优化器的核心步长 |
weight_decay |
float | 0.01(1e-2) | 1e-2/1e-4/0 | 权重衰减系数(L2正则),AdamW解耦后的核心,0表示不衰减 |
- weight_decay:唯一需要重点调参的新增项,0表示不使用权重衰减;
- 小模型/简单任务:可设为 1e-4 或 0;
- 大模型/复杂任务(CV/NLP):常用 1e-2(这是AdamW的经典值)。
- lr:需和 weight_decay 配合调参,权重衰减越大,学习率通常适当调小。
🟢 默认参数(99%场景直接用默认,无需修改)
| 参数 | 类型 | 默认值 | 含义 | 调优说明 |
|---|---|---|---|---|
betas |
元组(float, float) | (0.9, 0.999) | 一阶动量β₁、二阶动量β₂,控制梯度的指数移动平均 | 工业界固定值,绝不修改 |
eps |
float | 1e-08 | 极小常数,防止自适应学习率的分母为0,避免数值溢出 | 固定值,绝不修改 |
amsgrad |
bool | False | 是否启用AMSGrad变体,解决Adam的动量偏差问题 | 效果提升极有限,开启会增加计算量,不用 |
foreach |
bool/None | None | 批量更新参数,提升优化器计算速度 | PyTorch2.0+自动适配,None表示框架自动判断 |
maximize |
bool | False | 是否最大化目标函数(而非最小化损失) | 常规任务都是最小化损失,保持False |
capturable |
bool | False | 支持CUDA异步梯度捕获 | 仅分布式/异步训练、CUDA高性能场景开启 |
differentiable |
bool | False | 是否让优化器步骤支持自动微分 | 仅高阶优化/元学习场景使用,普通任务关闭 |
fused |
bool/None | None | 融合多个优化步骤为CUDA核函数,大幅加速训练 | PyTorch2.0+支持,仅CUDA环境可开启,None自动判断 |
最常用的极简语法(实际开发90%的场景)
直接使用必传参数+核心参数,默认参数全部省略,是工业界的标准写法:
# CV任务(如分类/检测)
optimizer = torch.optim.AdamW(model.parameters(), lr=1e-3, weight_decay=1e-2)
# NLP/大模型微调(核心调小lr)
optimizer = torch.optim.AdamW(model.parameters(), lr=1e-4, weight_decay=1e-4)
特殊语法:参数分组(不同参数用不同超参)
这是params参数的高级用法,传入字典列表,为模型不同部分(如骨干/分类头、weight/bias)单独设置lr/weight_decay,语法格式如下:
optimizer = torch.optim.AdamW(
[
# 分组1:骨干网络参数,小lr+大衰减
{"params": model.backbone.parameters(), "lr": 1e-4, "weight_decay": 1e-2},
# 分组2:分类头参数,大lr+小衰减(默认继承外层超参)
{"params": model.head.parameters(), "lr": 1e-3},
# 分组3:偏置/BN参数,不衰减(weight_decay=0)
{"params": no_decay_params, "weight_decay": 0.0}
],
# 外层超参:作为所有分组的「默认值」,分组内指定会覆盖
lr=1e-3,
weight_decay=1e-2
)
总结
AdamW基础语法:torch.optim.AdamW(params, lr=1e-3, weight_decay=1e-2),仅需指定必传的params和核心的lr/weight_decay;- 所有默认参数(betas/eps/amsgrad等)无需修改,工业界固定使用框架默认值;
- 高级用法通过参数分组实现,params传入字典列表即可为不同参数单独设置超参;
- PyTorch2.0+的新参数(foreach/fused)保持None,框架会自动适配硬件(CPU/GPU)做加速。
例子
import torch
import torch.nn as nn
import torch.optim as optim
# 1. 定义简单模型(示例)
model = nn.Linear(10, 2) # 输入10维,输出2维的全连接层
# 2. 定义AdamW优化器(核心步骤)
optimizer = optim.AdamW(
model.parameters(), # 必须传入模型的可训练参数
lr=1e-3, # 学习率(核心超参数,常用1e-3/1e-4)
weight_decay=1e-2 # 权重衰减系数(核心超参数,常用1e-2/1e-4)
)
# 3. 训练流程(标准步骤)
for epoch in range(10):
optimizer.zero_grad() # 每次迭代前清空梯度(避免累加)
output = model(torch.randn(32, 10)) # 前向传播:32个样本
loss = output.sum() # 示例损失(实际任务替换为真实损失)
loss.backward() # 反向传播:计算梯度
optimizer.step() # 优化器更新参数(AdamW核心逻辑)
AdamW 与 Adam 的区别
| 特性 | Adam | AdamW |
|---|---|---|
| 权重衰减实现 | 嵌入梯度更新,与动量干扰 | 独立步骤,直接衰减参数,无干扰 |
| 实际衰减效果 | 弱于设定值,效果打折扣 | 等于设定值,精准生效 |
| 超参数 weight_decay | 常用0(因效果差) | 核心超参数,常用1e-2/1e-4 |
| 泛化能力 | 中等,易过拟合 | 更强,过拟合抑制效果更好 |
| 适用场景 | 小模型/简单任务 | 所有场景(尤其大模型/CV/NLP) |
结论:新项目优先使用 AdamW,完全替代 Adam,仅在极特殊的小模型场景下可考虑Adam。
实用技巧(工业界常用)
学习率调度(必备):AdamW 单独使用固定学习率易收敛到局部最优,需配合学习率调度器(如余弦退火、步长衰减),示例:
# 定义AdamW + 余弦退火调度器(最常用) optimizer = optim.AdamW(model.parameters(), lr=1e-3, weight_decay=1e-2) scheduler = optim.lr_scheduler.CosineAnnealingLR(optimizer, T_max=100) # T_max为迭代轮数 # 训练中新增scheduler.step() loss.backward() optimizer.step() scheduler.step() # 每次迭代更新学习率参数分组优化:对模型不同部分(如骨干网络/分类头、冻结层/训练层)设置不同的
lr和weight_decay,示例(分类任务常用):# 骨干网络(如ResNet)用小学习率+大权重衰减,分类头用大学习率+小衰减 backbone_params = list(model.backbone.parameters()) head_params = list(model.head.parameters()) optimizer = optim.AdamW( [ {"params": backbone_params, "lr": 1e-4, "weight_decay": 1e-2}, {"params": head_params, "lr": 1e-3, "weight_decay": 1e-4} ] )权重衰减排除偏置/批归一化(BN)参数:偏置(bias)和 BN 层的
weight/bias通常不做权重衰减(会导致模型表达能力下降),这是工业界标准操作,示例:def get_optimizer(model): # 分组:需要衰减的参数(weight)、无需衰减的参数(bias/BN) decay_params = [] no_decay_params = [] for name, param in model.named_parameters(): if not param.requires_grad: continue # 跳过冻结的参数 # 偏置/BN的weight/bias:不衰减 if name.endswith("bias") or ("bn" in name and name.endswith("weight")): no_decay_params.append(param) else: decay_params.append(param) # 定义AdamW,对两组参数分别设置weight_decay optimizer = optim.AdamW( [ {"params": decay_params, "weight_decay": 1e-2}, {"params": no_decay_params, "weight_decay": 0.0} ], lr=1e-3 ) return optimizer # 使用 optimizer = get_optimizer(model)- 梯度裁剪(Gradient Clipping):配合 AdamW 使用,解决梯度爆炸问题(尤其NLP/大模型),示例:
loss.backward() torch.nn.utils.clip_grad_norm_(model.parameters(), max_norm=1.0) # 裁剪梯度到最大范数1.0 optimizer.step()
六、适用场景
AdamW 是通用型优化器,几乎适配所有深度学习任务,尤其在以下场景表现最优:
- 计算机视觉(CV):分类、检测、分割、生成(GAN/Stable Diffusion);
- 自然语言处理(NLP):大模型(LLaMA/Transformer)、文本分类、翻译、问答;
- 大模型训练/微调:是目前大模型微调的标配优化器;
- 复杂模型/高维数据:相比SGD,收敛速度更快,相比Adam,泛化能力更强。
总结
torch.optim.AdamW是 Adam 的改进版,核心是解耦权重衰减和梯度更新,让权重衰减精准生效;- 用法和其他PyTorch优化器一致,核心超参数为
lr(1e-3/1e-4)和weight_decay(1e-2/1e-4),其余超参数用默认值; - 工业界标配用法:AdamW + 学习率调度器 + 排除bias/BN的权重衰减 + 可选梯度裁剪;
- 优先替代原始Adam,是目前CV/NLP/大模型等任务的首选优化器。