正如我们在前几章中所见,深度神经网络带有大量在训练过程中学习的参数或权重。除此之外,每个神经网络都有额外的 超参数需要用户配置。例如,为了确保随机梯度下降收敛到训练损失的局部最优(参见第 12 节),我们必须调整学习率和批量大小。为了避免在训练数据集上过度拟合,我们可能必须设置正则化参数,例如权重衰减(参见第 3.7 节)或 dropout(参见 第 5.6 节)). 我们可以通过设置层数和每层单元或过滤器的数量(即权重的有效数量)来定义模型的容量和归纳偏差。
不幸的是,我们不能简单地通过最小化训练损失来调整这些超参数,因为这会导致训练数据过度拟合。例如,将正则化参数(如 dropout 或权重衰减)设置为零会导致较小的训练损失,但可能会损害泛化性能。
如果没有不同形式的自动化,就必须以反复试验的方式手动设置超参数,这相当于机器学习工作流程中耗时且困难的部分。例如,考虑在 CIFAR-10 上训练 ResNet(参见第 8.6 节g4dn.xlarge
),这需要在 Amazon Elastic Cloud Compute (EC2)实例上训练 2 个多小时。即使只是依次尝试十个超参数配置,这也已经花费了我们大约一天的时间。更糟糕的是,超参数通常不能直接跨架构和数据集传输 (Bardenet等人,2013 年,Feurer等人,2022 年,Wistuba等人,2018 年),并且需要针对每个新任务重新优化。此外,对于大多数超参数,没有经验法则,需要专业知识才能找到合理的值。
超参数优化 (HPO)算法旨在以一种有原则的和自动化的方式解决这个问题 (Feurer 和 Hutter,2018 年),将其定义为一个全局优化问题。默认目标是保留验证数据集上的错误,但原则上可以是任何其他业务指标。它可以与次要目标结合或受其约束,例如训练时间、推理时间或模型复杂性。
最近,超参数优化已扩展到神经架构搜索 (NAS) (Elsken等人,2018 年,Wistuba等人,2019 年),目标是找到全新的神经网络架构。与经典 HPO 相比,NAS 在计算方面的成本更高,并且需要额外的努力才能在实践中保持可行性。HPO 和 NAS 都可以被视为 AutoML 的子领域 ( Hutter et al. , 2019 ),旨在自动化整个 ML 管道。
在本节中,我们将介绍 HPO 并展示我们如何自动找到第 4.5 节介绍的逻辑回归示例的最佳超参数。
19.1.1. 优化问题
我们将从一个简单的玩具问题开始:搜索第 4.5 节SoftmaxRegression
中 的多类逻辑回归模型的学习率,以最小化 Fashion MNIST 数据集上的验证错误。虽然批量大小或轮数等其他超参数也值得调整,但为简单起见,我们只关注学习率。
在运行 HPO 之前,我们首先需要定义两个要素:目标函数和配置空间。
19.1.1.1。目标函数
学习算法的性能可以看作是一个函数 f:X→R从超参数空间映射x∈X到验证损失。对于每一个评价f(x),我们必须训练和验证我们的机器学习模型,对于在大型数据集上训练的深度神经网络,这可能是时间和计算密集型的。鉴于我们的标准f(x)我们的目标是找到 x⋆∈argminx∈Xf(x).
没有简单的方法来计算的梯度f关于 x,因为它需要在整个训练过程中传播梯度。虽然最近有工作 (Franceschi等人,2017 年,Maclaurin等人,2015 年)通过近似“超梯度”驱动 HPO,但现有方法中没有一种与最先进的方法具有竞争力,我们将不在这里讨论它们。此外,评估的计算负担f 要求 HPO 算法以尽可能少的样本接近全局最优。
神经网络的训练是随机的(例如,权重是随机初始化的,mini-batches 是随机采样的),因此我们的观察结果会很嘈杂:y∼f(x)+ϵ,我们通常假设ϵ∼N(0,σ) 观察噪声呈高斯分布。
面对所有这些挑战,我们通常会尝试快速识别一小组性能良好的超参数配置,而不是准确地达到全局最优值。然而,由于大多数神经网络模型的大量计算需求,即使这样也可能需要数天或数周的计算时间。我们将在19.4 节中探讨如何通过分布搜索或使用目标函数的评估成本更低的近似值来加快优化过程。
我们从计算模型验证误差的方法开始。
class HPOTrainer(d2l.Trainer): #@save
def validation_error(self):
self.model.eval()
accuracy = 0
val_batch_idx = 0
for batch in self.val_dataloader:
with torch.no_grad():
x, y = self.prepare_batch(batch)
y_hat = self.model(x)
accuracy += self.model.accuracy(y_hat, y)
val_batch_idx += 1
return 1 - accuracy / val_batch_idx
我们优化了关于超参数配置的验证错误config
,由learning_rate
. 对于每个评估,我们训练我们的模型max_epochs
epochs,然后计算并返回其验证错误:
def hpo_objective_softmax_classification(config, max_epochs=8):
learning_rate = config["learning_rate"]
trainer = d2l.HPOTrainer(max_epochs=max_epochs)
data = d2l.FashionMNIST(batch_size=16)
model = d2l.SoftmaxRegression(num_outputs=10, lr=learning_rate)
trainer.fit(model=model, data=data)
return trainer.validation_error().detach().numpy()
19.1.1.2。配置空间
随着目标函数f(x),我们还需要定义可行集x∈X优化过来,称为配置空间或搜索空间。对于我们的逻辑回归示例,我们将使用:
这里我们使用loguniform
SciPy 中的对象,它表示对数空间中 -4 和 -1 之间的均匀分布。这个对象允许我们从这个分布中抽样随机变量。
每个超参数都有一个数据类型,例如float
for learning_rate
,以及一个封闭的有界范围(即下限和上限)。我们通常为每个超参数分配一个先验分布(例如,均匀分布或对数均匀分布)以从中进行采样。一些正参数(例如learning_rate
)最好用对数标度表示,因为最佳值可能相差几个数量级,而其他参数(例如动量)则采用线性标度。
下面我们展示了一个配置空间的简单示例,该配置空间由多层感知器的典型超参数组成,包括它们的类型和标准范围。
姓名 |
类型 |
超参数范围 |
对数刻度 |
---|---|---|---|
学习率 |
漂浮 |
[10−6,10−1] |
是的 |
批量大小 |
整数 |
[8,256] |
是的 |
势头 |
|