开发者指南 / 超参数调优 / 微调搜索空间

微调搜索空间

作者: Luca Invernizzi, James Long, Francois Chollet, Tom O'Malley, Haifeng Jin
创建日期: 2019/05/31
最后修改: 2021/10/27
描述: 调整超参数的子集而不改变超模型。

在 Colab 中查看 GitHub 源代码

!pip install keras-tuner -q

在本指南中,我们将展示如何在不直接改变 HyperModel 代码的情况下调整搜索空间。例如,您可以只调整某些超参数,同时保持其他参数不变,或者您可以重写编译参数,例如 optimizerlossmetrics


超参数的默认值

在调整搜索空间之前,了解每个超参数都有一个默认值是很重要的。这个默认值在我们调整搜索空间时未调整时作为超参数值使用。

每当您注册一个超参数时,可以使用 default 参数指定默认值:

hp.Int("units", min_value=32, max_value=128, step=32, default=64)

如果您不这样做,超参数始终具有默认的默认值(对于 Int 来说,它等于 min_value)。

在以下模型构建函数中,我们将 units 超参数的默认值指定为 64。

import keras
from keras import layers
import keras_tuner
import numpy as np


def build_model(hp):
    model = keras.Sequential()
    model.add(layers.Flatten())
    model.add(
        layers.Dense(
            units=hp.Int("units", min_value=32, max_value=128, step=32, default=64)
        )
    )
    if hp.Boolean("dropout"):
        model.add(layers.Dropout(rate=0.25))
    model.add(layers.Dense(units=10, activation="softmax"))
    model.compile(
        optimizer=keras.optimizers.Adam(
            learning_rate=hp.Choice("learning_rate", values=[1e-2, 1e-3, 1e-4])
        ),
        loss="sparse_categorical_crossentropy",
        metrics=["accuracy"],
    )
    return model

我们将在教程的其余部分重用此搜索空间,通过覆盖超参数而不必定义新的搜索空间。


搜索少数并固定其余

如果您有一个现有的超模型,并且您只想在少数超参数上进行搜索,同时保持其余参数固定,您不必在模型构建函数或 HyperModel 中更改代码。您可以将 HyperParameters 传递给调优器构造函数的 hyperparameters 参数,其中包含您希望调整的所有超参数。指定 tune_new_entries=False 以防止调整其他超参数,默认值将被使用。

在以下示例中,我们只调整 learning_rate 超参数,并更改其类型和值范围。

hp = keras_tuner.HyperParameters()

# 这将使用您自己的选择覆盖 `learning_rate` 参数
hp.Float("learning_rate", min_value=1e-4, max_value=1e-2, sampling="log")

tuner = keras_tuner.RandomSearch(
    hypermodel=build_model,
    hyperparameters=hp,
    # 防止未列出的参数被调整
    tune_new_entries=False,
    objective="val_accuracy",
    max_trials=3,
    overwrite=True,
    directory="my_dir",
    project_name="search_a_few",
)

# 生成随机数据
x_train = np.random.rand(100, 28, 28, 1)
y_train = np.random.randint(0, 10, (100, 1))
x_val = np.random.rand(20, 28, 28, 1)
y_val = np.random.randint(0, 10, (20, 1))

# 运行搜索
tuner.search(x_train, y_train, epochs=1, validation_data=(x_val, y_val))
Trial 3 Complete [00h 00m 01s]
val_accuracy: 0.20000000298023224
最佳 val_accuracy: 0.25
总耗时: 00h 00m 03s

如果您总结搜索空间,您将只看到一个超参数。

tuner.search_space_summary()
搜索空间摘要
默认搜索空间大小: 1
learning_rate (Float)
{'default': 0.0001, 'conditions': [], 'min_value': 0.0001, 'max_value': 0.01, 'step': None, 'sampling': 'log'}

固定少数并调整其余

在上面的示例中,我们展示了如何只调整少数超参数并保持其余参数固定。您也可以反过来:只固定少数超参数并调整其余所有参数。

在以下示例中,我们固定了 learning_rate 超参数的值。通过传递带有 Fixed 条目(或任意数量的 Fixed 条目)的 hyperparameters 参数。还记得要指定 tune_new_entries=True, 允许我们调整其余的超参数。

hp = keras_tuner.HyperParameters()
hp.Fixed("learning_rate", value=1e-4)

tuner = keras_tuner.RandomSearch(
    build_model,
    hyperparameters=hp,
    tune_new_entries=True,
    objective="val_accuracy",
    max_trials=3,
    overwrite=True,
    directory="my_dir",
    project_name="fix_a_few",
)

tuner.search(x_train, y_train, epochs=1, validation_data=(x_val, y_val))
试验3完成 [00h 00m 01s]
val_accuracy: 0.15000000596046448
迄今为止最佳val_accuracy: 0.15000000596046448
总耗时: 00h 00m 03s

如果你汇总搜索空间,你会看到learning_rate被标记为固定的,其余的超参数正在调整。

tuner.search_space_summary()
搜索空间摘要
默认搜索空间大小: 3
learning_rate (固定)
{'conditions': [], 'value': 0.0001}
units (整数)
{'default': 64, 'conditions': [], 'min_value': 32, 'max_value': 128, 'step': 32, 'sampling': 'linear'}
dropout (布尔)
{'default': False, 'conditions': []}

覆盖编译参数

如果你有一个超模型,你想要更改现有的优化器、损失或指标,可以通过将这些参数传递给调优器构造函数来实现:

tuner = keras_tuner.RandomSearch(
    build_model,
    optimizer=keras.optimizers.Adam(1e-3),
    loss="mse",
    metrics=[
        "sparse_categorical_crossentropy",
    ],
    objective="val_loss",
    max_trials=3,
    overwrite=True,
    directory="my_dir",
    project_name="override_compile",
)

tuner.search(x_train, y_train, epochs=1, validation_data=(x_val, y_val))
试验3完成 [00h 00m 01s]
val_loss: 29.39796257019043
迄今为止最佳val_loss: 29.39630699157715
总耗时: 00h 00m 04s

如果你获取最佳模型,你可以看到损失函数已更改为MSE。

tuner.get_best_models()[0].loss
/usr/local/python/3.10.13/lib/python3.10/site-packages/keras/src/saving/saving_lib.py:388: 用户警告: 跳过优化器'adam'的变量加载,因为它有2个变量,而保存的优化器有10个变量。
  trackable.load_own_variables(weights_store.get(inner_path))

'mse'

定制预构建超模型的搜索空间

你也可以对KerasTuner中的预构建模型使用这些技术,如HyperResNetHyperXception。但是,要查看这些预构建的HyperModel中有哪些超参数,你需要阅读源代码。

在以下示例中,我们仅调整HyperXceptionlearning_rate,并固定其余所有超参数。因为HyperXception的默认损失是categorical_crossentropy,它期望标签是独热编码的,这与我们的原始整数标签数据不匹配,我们需要通过在编译参数中覆盖losssparse_categorical_crossentropy来更改它。

hypermodel = keras_tuner.applications.HyperXception(input_shape=(28, 28, 1), classes=10)

hp = keras_tuner.HyperParameters()

# 这将覆盖`learning_rate`参数为你
# 自己选择的选项
hp.Choice("learning_rate", values=[1e-2, 1e-3, 1e-4])

tuner = keras_tuner.RandomSearch(
    hypermodel,
    hyperparameters=hp,
    # 防止未列出的参数被调整
    tune_new_entries=False,
    # 覆盖损失。
    loss="sparse_categorical_crossentropy",
    metrics=["accuracy"],
    objective="val_accuracy",
    max_trials=3,
    overwrite=True,
    directory="my_dir",
    project_name="helloworld",
)

# 运行搜索
tuner.search(x_train, y_train, epochs=1, validation_data=(x_val, y_val))
tuner.search_space_summary()
试验3完成 [00h 00m 19s]
val_accuracy: 0.15000000596046448
迄今为止最佳val_accuracy: 0.20000000298023224
总耗时: 00h 00m 58s
搜索空间摘要
默认搜索空间大小: 1
learning_rate (选择)
{'default': 0.01, 'conditions': [], 'values': [0.01, 0.001, 0.0001], 'ordered': True}