开发者指南 / 超参数调优 / 可视化超参数调优过程

可视化超参数调优过程

作者: Haifeng Jin
创建日期: 2021/06/25
最后修改: 2021/06/05
描述: 使用 TensorBoard 可视化 KerasTuner 中的超参数调优过程。

在 Colab 中查看 GitHub 源代码

!pip install keras-tuner -q

介绍

KerasTuner 将日志打印到屏幕,包括用户监控进度的每次试验中超参数的值。然而,读取日志并不足够直观,以感知超参数对结果的影响。因此,我们提供了一种方法,用于使用 TensorBoard 可视化超参数值及其相应的评估结果。

TensorBoard 是一个有用的工具,可以可视化机器学习实验。它可以在模型训练期间监控损失和指标,并可视化模型架构。与 TensorBoard 一起运行 KerasTuner 将为您提供使用 HParams 插件可视化超参数调优结果的附加功能。

我们将使用一个简单的例子来调优 MNIST 图像分类数据集的模型,以展示如何将 KerasTuner 与 TensorBoard 一起使用。

第一步是下载和格式化数据。

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

(x_train, y_train), (x_test, y_test) = keras.datasets.mnist.load_data()
# 将像素值归一化到 [0, 1] 的范围内。
x_train = x_train.astype("float32") / 255
x_test = x_test.astype("float32") / 255
# 在图像中添加通道维度。
x_train = np.expand_dims(x_train, -1)
x_test = np.expand_dims(x_test, -1)
# 打印数据的形状。
print(x_train.shape)
print(y_train.shape)
print(x_test.shape)
print(y_test.shape)
(60000, 28, 28, 1)
(60000,)
(10000, 28, 28, 1)
(10000,)

然后,我们编写一个 build_model 函数来构建带有超参数的模型并返回该模型。超参数包括使用的模型类型(多层感知器或卷积神经网络)、层数、单元或过滤器的数量,以及是否使用 dropout。

def build_model(hp):
    inputs = keras.Input(shape=(28, 28, 1))
    # 模型类型可以是 MLP 或 CNN。
    model_type = hp.Choice("model_type", ["mlp", "cnn"])
    x = inputs
    if model_type == "mlp":
        x = layers.Flatten()(x)
        # MLP 的层数是一个超参数。
        for i in range(hp.Int("mlp_layers", 1, 3)):
            # 每层的单元数量是
            # 具有不同名称的不同超参数。
            x = layers.Dense(
                units=hp.Int(f"units_{i}", 32, 128, step=32),
                activation="relu",
            )(x)
    else:
        # CNN 的层数也是一个超参数。
        for i in range(hp.Int("cnn_layers", 1, 3)):
            x = layers.Conv2D(
                hp.Int(f"filters_{i}", 32, 128, step=32),
                kernel_size=(3, 3),
                activation="relu",
            )(x)
            x = layers.MaxPooling2D(pool_size=(2, 2))(x)
        x = layers.Flatten()(x)

    # 一个超参数,用于决定是否使用 dropout 层。
    if hp.Boolean("dropout"):
        x = layers.Dropout(0.5)(x)

    # 最后一层包含 10 个单元,
    # 这与类别的数量相同。
    outputs = layers.Dense(units=10, activation="softmax")(x)
    model = keras.Model(inputs=inputs, outputs=outputs)

    # 编译模型。
    model.compile(
        loss="sparse_categorical_crossentropy",
        metrics=["accuracy"],
        optimizer="adam",
    )
    return model

我们可以对模型进行快速测试,以检查它是否成功构建了 CNN 和 MLP。

# 初始化 `HyperParameters` 并设置值。
hp = keras_tuner.HyperParameters()
hp.values["model_type"] = "cnn"
# 使用 `HyperParameters` 构建模型。
model = build_model(hp)
# 测试模型是否能与我们的数据一起运行。
model(x_train[:100])
# 打印模型的摘要。
model.summary()

# 对 MLP 模型执行相同操作。
hp.values["model_type"] = "mlp"
model = build_model(hp)
model(x_train[:100])
model.summary()
模型: "functional_1"

┏━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┳━━━━━━━━━━━━━━━━━━━━━━━━━━━┳━━━━━━━━━━━━┓ ┃ 图层 (类型) 输出形状 参数 # ┃ ┡━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━╇━━━━━━━━━━━━━━━━━━━━━━━━━━━╇━━━━━━━━━━━━┩ │ input_layer (输入层) │ (, 28, 28, 1) │ 0 │ ├─────────────────────────────────┼───────────────────────────┼────────────┤ │ conv2d (卷积层) │ (, 26, 26, 32) │ 320 │ ├─────────────────────────────────┼───────────────────────────┼────────────┤ │ max_pooling2d (最大池化层) │ (, 13, 13, 32) │ 0 │ ├─────────────────────────────────┼───────────────────────────┼────────────┤ │ flatten (展平) │ (, 5408) │ 0 │ ├─────────────────────────────────┼───────────────────────────┼────────────┤ │ dense (全连接层) │ (, 10) │ 54,090 │ └─────────────────────────────────┴───────────────────────────┴────────────┘

 Total params: 54,410 (212.54 KB)
 Trainable params: 54,410 (212.54 KB)
 Non-trainable params: 0 (0.00 B)
Model: "functional_3"
┏━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┳━━━━━━━━━━━━━━━━━━━━━━━━━━━┳━━━━━━━━━━━━┓
┃ Layer (type)                     Output Shape                  Param # ┃
┡━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━╇━━━━━━━━━━━━━━━━━━━━━━━━━━━╇━━━━━━━━━━━━┩
│ input_layer_1 (输入层)          │ (, 28, 28, 1)         │          0 │
├─────────────────────────────────┼───────────────────────────┼────────────┤
│ flatten_1 (展平层)              │ (, 784)               │          0 │
├─────────────────────────────────┼───────────────────────────┼────────────┤
│ dense_1 (全连接层)             │ (, 32)                │     25,120 │
├─────────────────────────────────┼───────────────────────────┼────────────┤
│ dense_2 (全连接层)             │ (, 10)                │        330 │
└─────────────────────────────────┴───────────────────────────┴────────────┘
 总参数: 25,450 (99.41 KB)
 可训练参数: 25,450 (99.41 KB)
 不可训练参数: 0 (0.00 B)

初始化 RandomSearch 调优器,进行 10 次试验,并使用验证 准确率作为选择模型的指标。

tuner = keras_tuner.RandomSearch(
    build_model,
    max_trials=10,
    # 不继续上一次在同一目录的搜索。
    overwrite=True,
    objective="val_accuracy",
    # 设置一个目录来存储中间结果。
    directory="/tmp/tb",
)

通过调用 tuner.search(...) 开始搜索。要使用 TensorBoard,我们需要 将 keras.callbacks.TensorBoard 实例传递给回调函数。

tuner.search(
    x_train,
    y_train,
    validation_split=0.2,
    epochs=2,
    # 使用 TensorBoard 回调。
    # 日志将写入 "/tmp/tb_logs"。
    callbacks=[keras.callbacks.TensorBoard("/tmp/tb_logs")],
)
试验 10 完成 [00时 00分 06秒]
val_accuracy: 0.9617499709129333
最佳 val_accuracy 到目前为止: 0.9837499856948853
总耗时: 00时 08分 32秒

如果在 Colab 中运行,以下两个命令将向您展示 Colab 中的 TensorBoard。

%load_ext tensorboard

%tensorboard --logdir /tmp/tb_logs

您可以访问 TensorBoard 的所有常见功能。例如,您 可以查看损失和指标曲线,并可视化不同试验中的模型计算图。

损失和指标曲线 计算图

除了这些功能,我们还有一个 HParams 选项卡,其中有 三个视图。在表格视图中,您可以查看 10 个不同试验在 表格中不同超参数值和评估指标的情况。

表格视图

在左侧,您可以为某些超参数指定过滤器。例如,您可以指定只查看没有 dropout 层且具有 1 到 2 个全连接层的 MLP 模型。

过滤后的表格视图

除了表格视图外,它还提供了两种其他视图,平行坐标视图和散点图矩阵视图。它们只是相同数据的不同可视化方法。您仍然可以使用左侧面板来过滤结果。 在并行坐标视图中,每条彩色线代表一个试验。 轴线是超参数和评估指标。

在散点图矩阵视图中,每个点代表一个试验。图形是试验在不同超参数和指标作为轴线的平面上的投影。