1、绪论
在本文中我们将深入探讨如何在不直接修改HyperModel代码的情况下,定制Keras Tuner的搜索空间。在深度学习的超参数优化过程中,搜索空间的定制是一个关键的步骤,因为它决定了Tuner将尝试哪些不同的配置组合。通过定制搜索空间,我们可以更有效地探索那些可能对模型性能产生重大影响的超参数,同时避免在不必要的超参数上浪费资源。
首先,我们可以选择只调整模型架构中的部分超参数,而将其他部分保持固定。这允许我们专注于那些我们认为对模型性能影响最大的超参数,如隐藏层的单元数、激活函数或dropout率等。在定义HyperModel时,我们可以为这些关键超参数设置搜索空间,而将其他超参数设置为固定的默认值。
其次,我们还可以覆盖模型的编译参数,如优化器、损失函数和指标。这些参数在模型训练过程中起着至关重要的作用,它们的选择将直接影响模型的训练效果和泛化能力。通过定制搜索空间,我们可以尝试不同的优化器、损失函数和指标组合,以找到最适合我们任务的配置。
为了实现这一点,我们可以在创建Tuner实例时,通过传递额外的参数来定制搜索空间。这些参数可以包括要调整的超参数列表、它们的搜索空间以及要覆盖的编译参数等。具体来说,我们可以使用Tuner的构造函数中的相关参数来指定这些设置。
2、超参数调优的默认值
在定制搜索空间之前,了解每个超参数的默认值是很重要的。这个默认值在我们定制搜索空间时不调整该超参数时会作为该超参数的值使用。
每当程序员注册一个超参数时,就可以使用default
参数来指定一个默认值。这样,如果在搜索过程中没有特别指定这个超参数的值,Tuner 就会使用设定的默认值。
例如,在定义搜索空间时,您可以这样做:
import tensorflow as tf
from keras_tuner import HyperModel
class MyHyperModel(HyperModel):
def build(self, hp):
# 假设我们有一个隐藏层,其单元数是一个可调的超参数
units = hp.Int('units', min_value=32, max_value=256, step=32, default=64)
model = tf.keras.models.Sequential()
model.add(tf.keras.layers.Dense(units=units, activation='relu'))
# ... 其他层 ...
# 假设我们还想固定优化器为Adam,但损失函数和指标是可调的
optimizer = 'adam' # 这里没有使用hp注册,因此它是一个固定值
loss = hp.Choice('loss', values=['mse', 'mae'], default='mse')
metrics = ['accuracy'] # 或者,您也可以用hp.Fixed来明确它是一个固定值
model.compile(optimizer=optimizer, loss=loss, metrics=metrics)
return model
# 当我们在Tuner中使用这个HyperModel时,如果没有特别指定units或loss,
# 那么它们将分别使用默认值64和'mse'。
在这个例子中,units
超参数有一个默认值64,而loss
超参数有一个默认值’mse’。如果我们在搜索过程中不特别指定这些超参数的值,那么Tuner就会使用这些默认值。
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
3、确定要调整的超参数
如果程序员有一个现有的HyperModel,并且只想对其中几个超参数进行搜索,同时保持其他超参数固定,不需要更改模型构建函数或HyperModel中的代码。程序员可以通过将包含其要调整的所有超参数的HyperParameters对象传递给Tuner构造函数的hyperparameters参数来实现。指定tune_new_entries=False可以阻止Tuner对其他超参数进行调整,而使用它们的默认值。
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))
4、 固定超参数
在上面的例子中,我们展示了如何仅调整几个超参数并保持其余超参数固定。你也可以做相反的操作:仅固定几个超参数并调整所有其余超参数。
在以下示例中,我们固定了learning_rate
超参数的值。通过传递一个包含Fixed
条目的hyperparameters
参数(或任何数量的Fixed
条目)。同时,记得指定tune_new_entries=True
,这样我们就可以调整其余的超参数了。
import tensorflow as tf
from keras_tuner import RandomSearch
from your_model_module import YourHyperModel # 假设你有一个名为YourHyperModel的HyperModel
# 创建一个包含要固定的超参数的HyperParameters对象
hp = tf.keras.tuners.HyperParameters()
hp.Fixed('learning_rate', value=1e-3) # 固定learning_rate的值为1e-3
# 创建Tuner实例,并传入HyperParameters对象
tuner = RandomSearch(
YourHyperModel(),
objective='val_loss',
max_trials=10,
executions_per_trial=1,
hyperparameters=hp, # 传入包含Fixed条目的HyperParameters对象
tune_new_entries=True, # 允许Tuner调整未在此处指定的其他超参数
# ... 其他Tuner参数 ...
)
# 接下来,你可以调用tuner.search()来开始搜索过程
在这个例子中,我们创建了一个HyperParameters
对象,其中只包含一个要固定的超参数learning_rate
。然后,我们将这个对象传递给RandomSearch
Tuner的hyperparameters
参数,并设置了tune_new_entries=True
来确保Tuner可以调整除了我们明确固定的超参数之外的所有其他超参数。
5、覆盖编译参数
如果程序员有一个HyperModel,并希望更改现有的优化器、损失函数或指标,可以通过将这些参数传递给Tuner构造函数来实现:
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))
如果得到了最佳模型,程序员可以看到损失函数已经改变为均方误差(MSE)。
tuner.get_best_models()[0].loss
6、定制预构建HyperModels的搜索空间
你也可以在KerasTuner的预构建模型(如HyperResNet或HyperXception)中使用这些技术。但是,为了查看这些预构建HyperModels中有哪些超参数,你需要阅读源代码。
在以下示例中,我们仅对HyperXception的学习率(learning_rate)进行调整,并固定了所有其他超参数。由于HyperXception的默认损失函数是categorical_crossentropy
,它期望标签是one-hot编码的,这与我们的原始整数标签数据不匹配,因此我们需要通过覆盖编译参数中的损失函数来将其更改为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}
7、总结
当进行深度学习开发工作坊时,使用前面讨论的定制搜索空间(Tailor the search space)的技术可以帮助你更有效地调整和优化你的模型。以下是如何在深度学习开发工作坊中应用这些技术的步骤:
-
选择预构建模型或自定义HyperModel:
- 如果你正在使用KerasTuner提供的预构建模型(如HyperResNet或HyperXception),请确保你了解这些模型默认包含的超参数。 - 如果你正在使用自定义的HyperModel,请确保你已经定义了模型的结构和可能需要调整的超参数。
-
分析现有超参数:
- 对于预构建模型,查看源代码或官方文档来了解现有超参数及其默认值。
- 对于自定义模型,检查你定义的超参数和它们的作用。 -
确定要调整的超参数:
- 基于你的问题和数据集,确定哪些超参数最有可能影响模型的性能。
- 例如,你可能想要调整学习率、批量大小、层数、神经元数量等。 -
固定或覆盖某些超参数:
- 如果你知道某些超参数的最佳值或不想调整它们,可以使用Fixed
选项将它们固定在某个值上。
- 如果你想要更改某些编译参数(如损失函数、优化器或指标),可以在Tuner的构造函数中覆盖它们。 -
定义搜索空间:
- 对于要调整的超参数,定义它们的搜索空间。这可能包括范围、离散值、分布等。
- 使用HyperParameters
对象来组织你的搜索空间。 -
设置Tuner:
- 创建一个Tuner实例(如RandomSearch
、Hyperband
等),并将你的HyperModel和搜索空间传递给它。
- 如果需要,覆盖编译参数并设置tune_new_entries
为True
或False
。 -
运行搜索:
- 调用Tuner的search
方法来开始搜索过程。
- 根据需要监控进度和结果。 -
分析和评估结果:
- 检查Tuner生成的结果,找到最佳模型配置。
- 使用验证集或测试集评估最佳模型的性能。 -
迭代和优化:
- 根据结果调整搜索空间或策略。
- 重复步骤5到8,直到找到满意的模型性能。 -
部署和监控:
- 将最佳模型部署到生产环境。
- 监控模型的性能,并根据需要进行调整或重新训练。
在深度学习开发工作坊中,使用这些技术可以帮助参与者更好地理解模型优化过程,并学习如何有效地调整超参数以改善模型性能。