開發者指南 / 超參數調整 / 調整搜尋空間

調整搜尋空間

作者: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` 程式碼的情況下調整搜尋空間。例如,您可以只調整部分超參數並保持其餘部分固定,或者您可以覆寫編譯參數,例如 `optimizer`、`loss` 和 `metrics`。


超參數的預設值

在我們調整搜尋空間之前,重要的是要知道每個超參數都有一個預設值。當我們在調整搜尋空間時未調整超參數時,會使用此預設值作為超參數值。

每當您註冊超參數時,您都可以使用 `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()

# This will override the `learning_rate` parameter with your
# own selection of choices
hp.Float("learning_rate", min_value=1e-4, max_value=1e-2, sampling="log")

tuner = keras_tuner.RandomSearch(
    hypermodel=build_model,
    hyperparameters=hp,
    # Prevents unlisted parameters from being tuned
    tune_new_entries=False,
    objective="val_accuracy",
    max_trials=3,
    overwrite=True,
    directory="my_dir",
    project_name="search_a_few",
)

# Generate random data
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))

# Run the search
tuner.search(x_train, y_train, epochs=1, validation_data=(x_val, y_val))
Trial 3 Complete [00h 00m 01s]
val_accuracy: 0.20000000298023224
Best val_accuracy So Far: 0.25
Total elapsed time: 00h 00m 03s

如果您總結搜索空間,您將只看到一個超參數。

tuner.search_space_summary()
Search space summary
Default search space size: 1
learning_rate (Float)
{'default': 0.0001, 'conditions': [], 'min_value': 0.0001, 'max_value': 0.01, 'step': None, 'sampling': 'log'}

固定部分參數並調整其餘參數

在上面的示例中,我們展示了如何僅調整幾個超參數並保持其餘參數固定。 您也可以反過來做:僅固定幾個超參數並調整所有其餘參數。

在以下示例中,我們固定了 learning_rate 超參數的值。 傳遞一個帶有 Fixed 條目的 hyperparameters 參數(或任意數量的 Fixed 條目)。 同時請記住指定 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))
Trial 3 Complete [00h 00m 01s]
val_accuracy: 0.15000000596046448
Best val_accuracy So Far: 0.15000000596046448
Total elapsed time: 00h 00m 03s

如果您總結搜索空間,您將看到 learning_rate 被標記為固定,並且其餘的超參數正在被調整。

tuner.search_space_summary()
Search space summary
Default search space size: 3
learning_rate (Fixed)
{'conditions': [], 'value': 0.0001}
units (Int)
{'default': 64, 'conditions': [], 'min_value': 32, 'max_value': 128, 'step': 32, 'sampling': 'linear'}
dropout (Boolean)
{'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))
Trial 3 Complete [00h 00m 01s]
val_loss: 29.39796257019043
Best val_loss So Far: 29.39630699157715
Total elapsed time: 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: UserWarning: Skipping variable loading for optimizer 'adam', because it has 2 variables whereas the saved optimizer has 10 variables. 
  trackable.load_own_variables(weights_store.get(inner_path))

'mse'

調整預建 HyperModel 的搜索空間

您也可以將這些技術與 KerasTuner 中的預建模型一起使用,例如 HyperResNetHyperXception。 但是,要查看這些預建 HyperModel 中有哪些超參數,您必須閱讀源代碼。

在以下示例中,我們僅調整 HyperXceptionlearning_rate 並固定所有其餘的超參數。 由於 HyperXception 的默認損失是 categorical_crossentropy,它期望標籤是獨熱編碼的,這與我們的原始整數標籤數據不匹配,因此我們需要通過覆蓋編譯參數中的 loss 來更改它到 sparse_categorical_crossentropy

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

hp = keras_tuner.HyperParameters()

# This will override the `learning_rate` parameter with your
# own selection of choices
hp.Choice("learning_rate", values=[1e-2, 1e-3, 1e-4])

tuner = keras_tuner.RandomSearch(
    hypermodel,
    hyperparameters=hp,
    # Prevents unlisted parameters from being tuned
    tune_new_entries=False,
    # Override the loss.
    loss="sparse_categorical_crossentropy",
    metrics=["accuracy"],
    objective="val_accuracy",
    max_trials=3,
    overwrite=True,
    directory="my_dir",
    project_name="helloworld",
)

# Run the search
tuner.search(x_train, y_train, epochs=1, validation_data=(x_val, y_val))
tuner.search_space_summary()
Trial 3 Complete [00h 00m 19s]
val_accuracy: 0.15000000596046448
Best val_accuracy So Far: 0.20000000298023224
Total elapsed time: 00h 00m 58s
Search space summary
Default search space size: 1
learning_rate (Choice)
{'default': 0.01, 'conditions': [], 'values': [0.01, 0.001, 0.0001], 'ordered': True}