当前位置:   article > 正文

AdamW算法

AdamW算法

AdamW算法是优化算法Adam的一个变体,它在深度学习中广泛应用。AdamW的主要改进在于它正则化方法的改变,即通过权重衰减(weight decay)而不是L2正则化,来控制模型参数的大小,从而提升了训练的稳定性和效果。

背景

  • Adam优化器结合了动量(Momentum)和RMSProp的优点,能够在各种神经网络结构中实现高效的训练。然而,Adam算法中的L2正则化实现存在一些问题,特别是在实际实现中,L2正则化被融合到了梯度更新中,这可能导致不稳定的权重更新。
  • AdamW通过将权重衰减(weight decay)从梯度更新过程中分离出来,解决了这些问题。具体来说,AdamW将权重衰减直接应用到权重更新步骤中,而不是将其作为损失函数的一部分进行梯度计算。

公式

AdamW的更新公式与Adam类似,但引入了显式的权重衰减项。以下是AdamW的核心公式:

  1. 偏移修正的动量估计
    m t = β 1 m t − 1 + ( 1 − β 1 ) g t m_t = \beta_1 m_{t-1} + (1 - \beta_1) g_t mt=β1mt1+(1β1)gt v t = β 2 v t − 1 + ( 1 − β 2 ) g t 2 v_t = \beta_2 v_{t-1} + (1 - \beta_2) g_t^2 vt=β2vt1+(1β2)gt2

  2. 偏移修正
    m ^ t = m t 1 − β 1 t \hat{m}_t = \frac{m_t}{1 - \beta_1^t} m^t=1β1tmt v ^ t = v t 1 − β 2 t \hat{v}_t = \frac{v_t}{1 - \beta_2^t} v^t=1β2tvt

  3. 参数更新
    θ t = θ t − 1 − η m ^ t v ^ t + ϵ − η λ θ t − 1 \theta_t = \theta_{t-1} - \eta \frac{\hat{m}_t}{\sqrt{\hat{v}_t} + \epsilon} - \eta \lambda \theta_{t-1} θt=θt1ηv^t +ϵm^tηλθt1

其中:

  • θ t \theta_t θt 是参数。
  • g t g_t gt 是梯度。
  • m t m_t mt v t v_t vt是一阶和二阶动量估计。
  • η \eta η 是学习率。
  • β 1 \beta_1 β1 β 2 \beta_2 β2分别是动量项的指数衰减率。
  • ϵ \epsilon ϵ是防止除零的小常数。
  • λ \lambda λ 是权重衰减系数。

优点

  1. 更稳定的权重更新:权重衰减独立于梯度计算,使得权重更新更稳定。
  2. 更好的正则化效果:权重衰减可以更有效地防止模型过拟合。
  3. 适用于广泛的模型:AdamW在各种深度学习模型中表现优异,尤其是在大规模神经网络中。

实现

import torch
import torch.optim as optim
from torch.utils.data import DataLoader, TensorDataset

# 定义数据集和数据加载器
data = torch.randn(1000, 10)  # 假设有1000个样本,每个样本有10个特征
labels = torch.randint(0, 2, (1000,))  # 假设二分类任务
dataset = TensorDataset(data, labels)
data_loader = DataLoader(dataset, batch_size=32, shuffle=True)

# 定义模型
model = torch.nn.Linear(10, 2)
criterion = torch.nn.CrossEntropyLoss()

# 创建AdamW优化器
optimizer = optim.AdamW(model.parameters(), lr=0.001, weight_decay=0.01)

# 训练循环
num_epochs = 100
for epoch in range(num_epochs):
    for batch_data, batch_labels in data_loader:
        optimizer.zero_grad()
        outputs = model(batch_data)
        loss = criterion(outputs, batch_labels)
        loss.backward()
        optimizer.step()

    # 打印每个epoch的损失
    print(f'Epoch {epoch+1}/{num_epochs}, Loss: {loss.item()}')

  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/2023面试高手/article/detail/685247
推荐阅读
相关标签
  

闽ICP备14008679号