Keras Tuner是一个库,可以为TensorFlow程序选择最佳的超参数集。为机器学习(ML)应用程序选择正确的超参数集的过程称为超参数调整或超调整。
超参数是控制训练过程和ML模型拓扑结构的变量。这些变量在训练过程中保持不变,并直接影响ML程序的性能。
超参数有两种类型:
- 影响模型选择的模型超参数,如隐藏层的数量和宽度
- 算法超参数影响学习算法的速度和质量,如随机梯度下降(SGD)的学习率和k近邻(KNN)分类器的近邻数
接下来使用Keras调谐器为图像分类应用程序执行超调。
import tensorflow as tf
from tensorflow import keras
import kerastuner as kt
#1 下载数据集
#使用Keras Tuner为从Fashion MNIST数据集中分类服装图像的机器学习模型找到最佳超参数。
(img_train, label_train), (img_test, label_test) = keras.datasets.fashion_mnist.load_data()
# Normalize pixel values between 0 and 1
#2 将想素值归一化到0和1之间
img_train = img_train.astype('float32') / 255.0
img_test = img_test.astype('float32') / 255.0
#3 定义模型
'''
在为超调构建模型时,除了模型体系结构之外,还定义了超参数搜索空间。为超参数调节设置的模型称为超模型。
可以通过两种方法定义超模型:
1,通过使用模型生成器函数
2,通过对Keras调谐器API的超模型类进行子类化
对于计算机视觉应用程序,还可以使用两个预定义的超模型类HyperXception和HyperResNet。
下面将使用模型生成器函数定义图像分类模型。modelbuilder函数返回已编译的模型,并使用在内联中定义的超参数对模型进行超调节。
'''
def model_builder(hp):
model = keras.Sequential()
model.add(keras.layers.Flatten(input_shape=(28, 28)))
# 调整第一个密集层(Dense layer)中的单元数
# 选择32-512之间的最佳值
hp_units = hp.Int('units', min_value=32, max_value=512, step=32)
model.add(keras.layers.Dense(units=hp_units, activation='relu'))
model.add(keras.layers.Dense(10))
# 调整优化器的学习速率
# 从0.01、0.001或0.0001中选择一个最佳值
hp_learning_rate = hp.Choice('learning_rate', values=[1e-2, 1e-3, 1e-4])
model.compile(optimizer=keras.optimizers.Adam(learning_rate=hp_learning_rate),
loss=keras.losses.SparseCategoricalCrossentropy(from_logits=True),
metrics=['accuracy'])
return model
#4 实例化调谐器并执行超调
'''
Keras Tuner有四个可用的调谐器:
RandomSearch、Hyperband、BayesianOptimization和Sklearn。我们将使用Hyperband调谐器。
要实例化Hyperband Tuner,必须指定超模型、要优化的目标和要训练的最大epoch数(max_epochs)。
'''
tuner = kt.Hyperband(model_builder,
objective='val_accuracy', # 优化的目标,验证集accuracy
max_epochs=10, # 最大迭代次数
factor=3,#有人知道这个有啥作用吗???
directory='my_dir', # my_dir/intro_to_kt目录包含超参数搜索期间运行的详细日志和checkpoints
project_name='intro_to_kt')
'''
Hyperband算法采用自适应资源分配(adaptive resource allocation)和提前停止(early-stopping )的方法快速收敛于高性能模型。
这是通过使用类似于体育锦标赛风格的赛制(bracket,括号)。该算法在几个时期内训练了大量的模型,只将性能最好的一半模型进行下一轮训练。
Hyperband通过计算多于一个的对数因子(logfactor(max_epochs))并将其四舍五入到最接近的整数来确定要在括号中训练的模型数。
'''
# 在达到验证损失的某个值后,创建回调以提前停止训练。
#!!!注意 tensorflow2.00-2.2支持tuner1.01不支持1.02,只有2.3支持1.029
stop_early = tf.keras.callbacks.EarlyStopping(monitor='val_loss', patience=5)
# 运行超参数搜索。搜索方法的参数与tf.keras.model.fit,除了上面的回调。
tuner.search(img_train, label_train, epochs=10, validation_data=(img_test, label_test),
callbacks=[stop_early])
# 获取最优超参数
best_hps=tuner.get_best_hyperparameters(num_trials=1)[0]
print(f"""
超参数搜索已完成。在第一密集连接层中的最佳单元数为{best_hps.get('units')} 优化器的最优学习率为 {best_hps.get('learning_rate')}.
""")
#5 训练模型
#利用搜索得到的超参数,找到训练模型的最优次数。
# 用最优超参数建立模型,并在50个epoch的数据上进行训练
model = tuner.hypermodel.build(best_hps)
history = model.fit(img_train, label_train, epochs=50, validation_split=0.2)
val_acc_per_epoch = history.history['val_accuracy']
best_epoch = val_acc_per_epoch.index(max(val_acc_per_epoch)) + 1
print('Best epoch: %d' % (best_epoch,))
#重新实例化超模型,并用上面的最佳历元数对其进行训练。
hypermodel = tuner.hypermodel.build(best_hps)
# 重新选练model
hypermodel.fit(img_test, label_test, epochs=best_epoch)
#在测试数据上评估超模型
eval_result = hypermodel.evaluate(img_test, label_test)
print("[test loss, test accuracy]:", eval_result)
'''
my_dir/intro_to_kt目录包含在超参数搜索期间运行的每个试验(模型配置)的详细日志和检查点。
如果重新运行超参数搜索,Keras调谐器将使用这些日志中的现有状态来恢复搜索。要禁用此行为,在实例
化调谐器时传递另一个overwrite=True参数。
'''