PyTorch教程中的AdamW优化器

优化算法在深度学习中起着关键作用:它们在训练过程中微调模型权重以最小化损失函数。这样一个算法就是Adam优化器

由于Adam能够结合动量和自适应学习率的优点,因此在深度学习中变得非常受欢迎。这使得它在训练深层神经网络时非常高效。它还要求最小的超参数调整,因此使其在各种任务中广泛适用且有效。

在2017年,伊利亚·洛什奇洛夫和弗兰克·胡特在他们的论文“解耦权重衰减正则化。”中引入了流行的Adam算法的更高级版本。他们将它命名为AdamW,它出色地解耦了权重衰减和梯度更新过程。这种分离是Adam的一个关键改进,并有助于模型的更好泛化。

AdamW 在现代深度学习应用中变得越来越重要,特别是在处理大规模模型方面。它在调节权重更新方面的优越能力使其在高性能和稳定性要求的任务中被采用。

在本教程中,我们将探讨 Adam 和 AdamW 的关键区别以及不同的使用场景,并将逐步指导如何在PyTorch中实现 AdamW。

Adam 与 AdamW 的比较

亚当(Adam)和亚当W(AdamW)都是深度学习中广泛使用的自适应优化器。它们之间最大的区别在于它们处理权重正则化的方式,这影响了它们在不同场景中的效果。

尽管亚当结合了动量法和自适应学习率,以提供高效的优化,但它通过一种可能阻碍性能的方式合并了L2正则化。亚当W通过将权重衰减与学习率更新解耦,解决了这个问题,为大型模型提供更有效的方法并改善泛化能力。权重衰减是一种L2正则化形式,它惩罚模型中的大权重。亚当将权重衰减纳入梯度更新过程中,而亚当W在梯度更新之后单独应用它。

以下是它们之间的其他不同之处:

亚当和亚当W之间的关键区别

尽管这两个优化器都旨在管理动量并动态调整学习率,但它们在权重衰减的处理上存在根本差异。

在Adam中,权重衰减作为梯度更新的一部分间接应用,这可能会无意中改变学习动态,并干扰优化过程。然而,AdamW将权重衰减与梯度步分离,确保正则化直接影响参数,而不改变适应性学习机制。

这种设计导致更精确的正则化,帮助模型更好地泛化,特别是在涉及大量复杂数据集的任务中。因此,这两个优化器通常有不同的应用场景。

Adam的应用场景

Adam在正则化不太关键的任务或者当优先考虑计算效率而非泛化时表现更好。例如:

  • 小型神经网络。对于使用小型卷积神经网络(卷积神经网络)进行基本图像分类等任务,如MNIST或CIFAR-10数据集,模型复杂度较低,Adam可以有效优化,无需广泛的正则化。
  • 简单回归问题。在特征集有限的基本回归任务中,例如使用线性回归模型预测房价,Adam可以快速收敛,无需先进正则化技术。
  • 早期原型设计。在模型开发的早期阶段,需要快速实验,Adam使得在更简单的架构上快速迭代成为可能,帮助研究人员识别潜在问题,而不需要调整正则化参数的负担。
  • 数据噪音小。当处理干净的数据集,如用于情感分析的良好整理的文本数据时,Adam可以在没有过拟合风险的情况下有效学习模式,这可能不需要更重的正则化。
  • 短暂的训练周期。在时间受限的情况下,如为实时应用快速部署模型,Adam的有效优化可以帮助快速获得满意的结果,即使它们可能没有针对泛化进行完全优化。

AdamW的使用案例

AdamW 在过拟合问题突出且模型规模较大的场景中表现出色。例如:

  • 大规模转换器。在自然语言处理任务中,如在大规模文本语料库上微调GPT等模型,AdamW有效管理权重衰减的能力可以防止过拟合,确保更好的泛化能力。
  • 复杂的计算机视觉模型。对于涉及深度卷积神经网络(CNNs)在ImageNet等大型数据集上训练的任务,AdamW通过使权重衰减解耦来保持模型的稳定性和性能,这对于实现高精度至关重要。
  • 多任务学习. 在模型同时针对多个任务进行训练的场景中,AdamW提供了灵活性,能够处理多样的数据集,并防止在任何单个任务上过拟合。
  • 生成模型. 对于训练生成对抗网络(GANs),保持生成器和判别器之间的平衡至关重要,AdamW的改进正则化可以帮助稳定训练并提高生成输出的质量。
  • 强化学习. 在强化学习应用中,模型必须适应复杂环境并学习健壮的策略,AdamW有助于减轻对特定状态或动作的过拟合,提高模型在各种情况下的泛化性能。

AdamW相对于Adam的优势

但为什么有人会选择使用AdamW而不是Adam呢?原因很简单。AdamW提供了几个关键优势,特别是在复杂建模场景中,这些优势增强了其性能。

它解决了Adam优化器中的一些局限性,从而使其在优化方面更加有效,并有助于提高模型训练的效率和鲁棒性。

以下是一些显著的优势:

  • 解耦权重衰减。通过将权重衰减与梯度更新分离,AdamW使得能够更精确地控制正则化,从而提高模型的泛化能力。
  • 增强泛化能力. AdamW降低了过拟合的风险,特别是在大规模模型中,使其适合涉及大量数据和复杂架构的任务。
  • 训练过程中的稳定性。 AdamW的设计有助于在整个训练过程中保持稳定性,这对于需要仔细调整超参数的模型至关重要。
  • 可扩展性。 AdamW特别适合于扩大模型规模,因为它可以处理深度网络的复杂性增加而不牺牲性能,从而可以应用于最先进的架构中。

AdamW的工作原理

AdamW的核心优势在于其权重衰减的方法,该方法与Adam典型的自适应梯度更新解耦。这种调整确保正则化直接应用于模型

优化器基于Adam的自适应特性,保持了动量和平衡参数学习率调整的优势。独立应用权重衰减解决了Adam的一个关键不足:在正则化过程中影响梯度更新的倾向。这种分离使得AdamW即使在复杂的大规模模型中也能保持稳定的学习,同时控制过拟合。

在接下来的部分,我们将探讨权重衰减和正则化的理论基础以及支撑AdamW优化过程的数学原理。

权重衰减和L2正则化的背后理论

L2正则化是一种防止过拟合的技术。它通过向损失函数添加惩罚项来实现这一目标,抑制大的权重值。这种技术有助于创建更简单的模型,这些模型在新数据上的泛化能力更强。

在传统的优化器中,例如Adam,权重衰减作为梯度更新的一部分被应用,这无意中影响了学习率,可能导致次优性能。

AdamW通过将权重衰减与梯度计算解耦来改进这一点。换句话说,而不是在梯度更新时应用权重衰减,AdamW将其视为一个独立的步骤,在梯度更新后直接对权重进行应用。这防止权重衰减干扰优化过程,导致训练更加稳定和更好的泛化。

AdamW的数学基础

AdamW通过改变权重衰减的应用方式来修改传统的Adam优化器。AdamW的核心方程可以表示如下:

  1. 动量和自适应学习率:与Adam算法相似,AdamW算法使用动量和自适应学习率,根据梯度的移动平均值和平方梯度来计算参数更新。

动量和自适应学习率的方程式

  1. 偏差校正估计使用以下方法对一阶和二阶估计进行偏差校正:

偏差校正估计的公式

  1. 参数更新与解耦权重衰减:在AdamW中,权重衰减在梯度更新后直接应用于参数。更新规则是:

带有解耦权重衰减的参数更新

在此处,η是学习率,λ是权重衰减因子,θt代表参数。这个解耦的权重衰减项λθt确保了正规化独立于梯度更新应用,这是与Adam的主要区别。

在PyTorch中实现AdamW

PyTorch中实现AdamW是简单的;本节提供了设置的全面指南。按照这些步骤,学习如何有效地使用Adam优化器微调模型。

PyTorch中AdamW的逐步指南

注意:本教程假定您已经安装了PyTorch。有关指导,请参考文档

步骤1:导入所需库

import torch import torch.nn as nn import torch.optim as optim Import torch.nn.functional as F

步骤2:定义模型

class SimpleCNN(nn.Module): def __init__(self): super(SimpleCNN, self).__init__() self.conv1 = nn.Conv2d(3, 32, kernel_size=3, stride=1, padding=1) self.pool = nn.MaxPool2d(kernel_size=2, stride=2, padding=0) self.conv2 = nn.Conv2d(32, 64, kernel_size=3, stride=1, padding=1) self.fc1 = nn.Linear(64 * 8 * 8, 128) self.fc2 = nn.Linear(128, 10) def forward(self, x): x = self.pool(F.relu(self.conv1(x))) x = self.pool(F.relu(self.conv2(x))) x = x.view(-1, 64 * 8 * 8) x = F.relu(self.fc1(x)) x = self.fc2(x)

步骤3:设置超参数

learning_rate = 1e-4 weight_decay = 1e-2 num_epochs = 10 # 轮次数量

步骤4:初始化AdamW优化器并设置损失函数

optimizer = optim.AdamW(model.parameters(), lr=learning_rate, weight_decay=weight_decay) criterion = nn.CrossEntropyLoss()

完成啦!

现在,您已经准备好开始训练卷积神经网络模型了,我们将在下一节进行这项工作。

实践示例:使用AdamW微调模型

上面,我们已经定义了模型,设置了超参数,初始化了优化器(AdamW),并设置了损失函数。

为了训练模型,我们还需要导入几个模块;

from torch.utils.data import DataLoader # 提供数据集的迭代器 import torchvision import torchvision.transforms as transforms

接下来,定义数据集和数据加载器。作为一个例子,我们将使用CIFAR-10数据集:

# 为训练集定义转换 transform = transforms.Compose([ transforms.ToTensor(), transforms.Normalize((0.5, 0.5, 0.5), (0.5, 0.5, 0.5)), ]) # 加载CIFAR-10数据集 train_dataset = torchvision.datasets.CIFAR10(root='./data', train=True, download=True, transform=transform) val_dataset = torchvision.datasets.CIFAR10(root='./data', train=False, download=True, transform=transform) # 创建数据加载器 train_loader = DataLoader(train_dataset, batch_size=32, shuffle=True) val_loader = DataLoader(val_dataset, batch_size=32, shuffle=False)

由于我们已经定义了我们的模型,下一个步骤是实现训练循环,使用AdamW优化模型。

这是它的样子:

for epoch in range(num_epochs): model.train() # 将模型设置为训练模式 running_loss = 0.0 for inputs, labels in train_loader: optimizer.zero_grad() # 清除梯度 outputs = model(inputs) # 前向传播 loss = criterion(outputs, labels) # 计算损失 loss.backward() # 反向传播 optimizer.step() # 更新权重 running_loss += loss.item() print(f'Epoch [{epoch+1}/{num_epochs}], Loss: {running_loss/len(train_loader):.4f}')

最后一步是验证模型在之前创建的验证数据集上的性能。

这里的代码:

model.eval() # 将模型设置为评估模式 correct = 0 total = 0 with torch.no_grad(): for inputs, labels in val_loader: outputs = model(inputs) # 前向传播 _, predicted = torch.max(outputs.data, 1) # 获取预测的类别 total += labels.size(0) # 更新总样本数 correct += (predicted == labels).sum().item() # 更新正确预测数 accuracy = 100 * correct / total print(f'Validation Accuracy: {accuracy:.2f}%')

就这样了。

现在你知道如何在PyTorch中实现AdamW了。

AdamW的常见使用场景

好的,我们已经确定AdamW之所以受欢迎,是因为它在管理权重衰减方面比其前身Adam更有效。

但是这个优化器有哪些常见使用场景呢?

我们将在本节中讨论这个问题…

大规模深度学习模型

AdamW 在训练像 BERT、GPT 和其他变换器架构的大型模型方面特别有益。这类模型通常具有数百万甚至数十亿的参数,这意味着它们通常需要能够处理复杂权重更新和泛化挑战的高效优化算法。

计算机视觉和自然语言处理任务

AdamW 已成为涉及 CNN 的计算机视觉任务和涉及变换器的 NLP 任务的优化器首选。它防止过拟合的能力使其成为涉及大型数据集和复杂架构的任务的理想选择。权重的解耦意味着 AdamW 避免了 Adam 在过度正则化模型时遇到的问题。

AdamW 中的超参数调整

超参数调优是选择控制机器学习模型训练但不是从数据本身学习到的参数的最佳值的过程。这些参数直接影响模型如何优化和收敛。

在AdamW中适当调整这些超参数对于实现高效训练、避免过拟合并确保模型对未见数据有很好的泛化能力是至关重要的。

在本节中,我们将探讨如何精细调整AdamW的关键超参数以实现最佳性能。

选择学习率和权重衰减的最佳实践

学习率是一个超参数,它控制着在每次训练步骤中根据损失梯度调整模型权重的程度。较高的学习率可以加快训练速度,但可能导致模型过度超出最优权重,而较低的学习率允许进行更精细的调整,但可能会使训练速度变慢或陷入局部最小值。

另一方面,权重衰减是一种正则化技术,通过惩罚模型中的大权重来防止过拟合。具体来说,权重衰减在训练过程中增加了与模型权重大小成比例的小惩罚,有助于减少模型复杂度并提高对新数据的泛化能力。

为AdamW选择最佳的学习率和权重衰减值:

  1. 从适中的学习率开始 – 对于AdamW,大约1e-3的学习率通常是一个很好的起点。您可以根据模型收敛的情况进行调整,如果模型难以收敛,可以降低它;如果训练太慢,可以增加它。
  2. 尝试权重衰减. 从大约1e-2到1e-4的值开始,具体取决于模型大小和数据集。稍微高一点的权重衰减对于较大、复杂的模型有助于防止过拟合,而较小的模型可能需要较少的正则化。
  3. 使用学习率调度。实现学习率调度(如步进衰减或余弦退火),随着训练的进行动态降低学习率,帮助模型在接近收敛时微调其参数。
  4. 监控性能持续跟踪模型在验证集上的性能。如果您观察到过拟合,考虑增加权重衰减,或者如果训练损失停滞,降低学习率以实现更好的优化。

结语

AdamW已经成为深度学习中最有效的优化器之一,特别是在大规模模型中。这是因为其能够将权重衰减与梯度更新解耦。即,AdamW的设计改善了正则化,并帮助模型更好地泛化,特别是在处理复杂架构和大量数据时。

正如本教程所证明的,在PyTorch中实现AdamW是直接的——它只需要对Adam进行一些调整。然而,超参数调优仍然是最大化AdamW效果的关键步骤。找到学习率与权重衰减之间的正确平衡对于确保优化器高效地工作,同时避免过拟合或欠拟合模型至关重要。

现在您已经知道足够多来实现AdamW自己的模型。为了继续您的学习,请查看以下资源:

Source:
https://www.datacamp.com/tutorial/adamw-optimizer-in-pytorch