天涯论坛

 找回密码
 立即注册
搜索
查看: 32|回复: 2

运用贝叶斯优化进行深度神经网络超参数优化

[复制链接]

2950

主题

3万

回帖

9997万

积分

论坛元老

Rank: 8Rank: 8

积分
99979413
发表于 2024-8-31 06:07:53 | 显示全部楼层 |阅读模式

点击上方“Deephub Imba”,关注公众号,好文案错失 !

在本文中,咱们将深入科研超参数优化。

为了方便起见本文将运用 Tensorflow 中包括的 Fashion MNIST[1] 数据集。该数据集在训练集中包括 60,000 张灰度图像,在测试集中包括 10,000 张图像。每张照片表率属于 10 个类别之一的单品(“T 恤/上衣”、“裤子”、“套头衫”等)。因此呢这是一个多类归类问题。

这儿简单介绍准备数据集的过程由于本文的重点内容是超参数的优化,因此这部分只是简单介绍流程,通常状况下,流程如下:

加载数据。

分为训练集、验证集和测试集。

将像素值从 0–255 标准化到 0–1 范围。

One-hot 编码目的变量。

#load data(train_images, train_labels), (test_images, test_labels) = fashion_mnist.load_data()# split into train, validation and test setstrain_x, val_x, train_y, val_y = train_test_split(train_images, train_labels, stratify=train_labels, random_state=48, test_size=0.05)(test_x, test_y)=(test_images, test_labels)# normalize pixels to range 0-1train_x = train_x / 255.0val_x = val_x / 255.0test_x = test_x / 255.0#one-hot encode target variabletrain_y = to_categorical(train_y)val_y = to_categorical(val_y)test_y = to_categorical(test_y)

咱们所有训练、验证和测试集的形状是:

print(train_x.shape) #(57000, 28, 28)print(train_y.shape) #(57000, 10)print(val_x.shape)   #(3000, 28, 28)print(val_y.shape)   #(3000, 10)print(test_x.shape)   #(10000, 28, 28)print(test_y.shape)   #(10000, 10)

此刻咱们运用 Keras Tuner 库 [2]:它将帮忙咱们容易调节神经网络的超参数:

pip install keras-tuner

Keras Tuner 需要 Python 3.6+ 和 TensorFlow 2.0+

超参数调节是机器学习项目的基本部分。有两种类型的超参数:

结构超参数:定义模型的整体架构(例如隐匿单元的数量、层数)

优化器超参数:影响训练速度和质量的参数(例如学习率和优化器类型、批量体积、轮次数等)

为何需要超参数调优库?咱们不可尝试所有可能的组合,瞧瞧验证集上什么是最好的吗?

这肯定是不行的由于深度神经网络需要大量时间来训练,乃至几天。倘若在云服务器上训练大型模型,那样每一个实验实验都需要花非常多的钱。

因此呢,需要一种限制超参数搜索空间的剪枝策略。

keras-tuner供给了贝叶斯优化器。它搜索每一个可能的组合,而是随机选取前几个。而后按照这些超参数的性能,选取下一个可能的最佳值。因此呢每一个超参数的选取都取决于之前的尝试。按照历史记录选取下一组超参数并评定性能,直到找到最佳组合或到达最大实验次数。咱们能够运用参数“max_trials”来配置它。

除了贝叶斯优化器之外,keras-tuner还供给另一两个平常办法:RandomSearch 和 Hyperband。咱们将在本文末尾讨论它们。

接下来便是咱们的网络应用超参数调节咱们尝试两种网络架构,标准多层感知器(MLP)和卷积神经网络(CNN)。

首要咱们瞧瞧基线 MLP 模型是什么:

model_mlp = Sequential()model_mlp.add(Flatten(input_shape=(28, 28)))model_mlp.add(Dense(350, activation=relu))model_mlp.add(Dense(10, activation=softmax))print(model_mlp.summary())model_mlp.compile(optimizer="adam",loss=categorical_crossentropy)

调优过程需要两种重点办法

hp.Int():设置超参数的范围,其值为整数 - 例如,密集层中隐匿单元的数量:

model.add(Dense(units = hp.Int(dense-bot, min_value=50, max_value=350, step=50))

hp.Choice():为超参数供给一组值——例如,Adam 或 SGD 做为最佳优化器?

hp_optimizer=hp.Choice(Optimizer, values=[Adam, SGD])

咱们的 MLP 示例中,咱们测试了以下超参数:

隐匿层数:1-3

第1密集层体积:50–350

第二和第三密集层体积:50–350

Dropout:0、0.1、0.2

优化器:SGD(nesterov=True,momentum=0.9) 或 Adam

学习率:0.1、0.01、0.001

代码如下:

model = Sequential()model.add(Dense(units = hp.Int(dense-bot, min_value=50, max_value=350, step=50), input_shape=(784,), activation=relu))for i in range(hp.Int(num_dense_layers, 1, 2)):model.add(Dense(units=hp.Int(dense_ + str(i), min_value=50, max_value=100, step=25), activation=relu)) model.add(Dropout(hp.Choice(dropout_+ str(i), values=[0.0, 0.1, 0.2])))model.add(Dense(10,activation="softmax"))hp_optimizer=hp.Choice(Optimizer, values=[Adam, SGD])if hp_optimizer == Adam:hp_learning_rate = hp.Choice(learning_rate, values=[1e-1, 1e-2, 1e-3])elif hp_optimizer == SGD:   hp_learning_rate = hp.Choice(learning_rate, values=[1e-1, 1e-2, 1e-3])   nesterov=Truemomentum=0.9

这儿需要重视第 5 行的 for 循环:让模型决定网络的深度!

最后,便是运行了。请重视咱们之前说到的 max_trials 参数。

model.compile(optimizer = hp_optimizer, loss=categorical_crossentropy, metrics=[accuracy])tuner_mlp = kt.tuners.BayesianOptimization(   model,   seed=random_seed,   objective=val_loss,   max_trials=30,   directory=.,   project_name=tuning-mlp)tuner_mlp.search(train_x, train_y, epochs=50, batch_size=32, validation_data=(dev_x, dev_y), callbacks=callback)

咱们得到结果

这个过程用尽了迭代次数,大约需要 1 小时才可完成。咱们能够运用以下命令打印模型的最佳超参数:

best_mlp_hyperparameters = tuner_mlp.get_best_hyperparameters(1)[0]print("Best Hyper-parameters")best_mlp_hyperparameters.values

此刻咱们能够运用最优超参数重新训练咱们的模型:

model_mlp = Sequential()model_mlp.add(Dense(best_mlp_hyperparameters[dense-bot], input_shape=(784,), activation=relu))for i in range(best_mlp_hyperparameters[num_dense_layers]): model_mlp.add(Dense(units=best_mlp_hyperparameters[dense_ +str(i)], activation=relu))model_mlp.add(Dropout(rate=best_mlp_hyperparameters[dropout_ +str(i)]))model_mlp.add(Dense(10,activation="softmax"))model_mlp.compile(optimizer=best_mlp_hyperparameters[Optimizer], loss=categorical_crossentropy,metrics=[accuracy])history_mlp= model_mlp.fit(train_x, train_y, epochs=100, batch_size=32, validation_data=(dev_x, dev_y), callbacks=callback)

咱们能够用这些参数重新训练咱们的模型:

model_mlp=tuner_mlp.hypermodel.build(best_mlp_hyperparameters)history_mlp=model_mlp.fit(train_x, train_y, epochs=100, batch_size=32,                           validation_data=(dev_x, dev_y), callbacks=callback)

而后测试准确率

mlp_test_loss, mlp_test_acc = model_mlp.evaluate(test_x, test_y, verbose=2)print(\nTest accuracy:, mlp_test_acc)# Test accuracy: 0.8823

与基线的模型测试精度相比:

基线 MLP 模型:86.6 %最佳 MLP 模型:88.2 %。测试准确度的差异约为 3%!

下面咱们运用相同的流程,将MLP改为CNN,这般能够测试更加多参数。

首要,这是咱们的基线模型:

model_cnn = Sequential()model_cnn.add(Conv2D(32, (3, 3), activation=relu, input_shape=(28, 28, 1)))model_cnn.add(MaxPooling2D((2, 2)))model_cnn.add(Flatten())model_cnn.add(Dense(100, activation=relu))model_cnn.add(Dense(10, activation=softmax))model_cnn.compile(optimizer="adam", loss=categorical_crossentropy, metrics=[accuracy])

基线模型 包括卷积和池化层。针对调优,咱们将测试以下内容:

卷积、MaxPooling 和 Dropout 层的“块”数

每一个块中 Conv 层的过滤器体积:32、64

转换层上的有效或相同填充

最后一个额外层的隐匿体积:25-150,乘以 25

优化器:SGD(nesterov=True,动量=0.9)或 Adam

学习率:0.01、0.001

model = Sequential()model = Sequential()model.add(Input(shape=(28, 28, 1)))for i in range(hp.Int(num_blocks, 1, 2)):   hp_padding=hp.Choice(padding_+ str(i), values=[valid, same])hp_filters=hp.Choice(filters_+ str(i), values=[32, 64])   model.add(Conv2D(hp_filters, (3, 3), padding=hp_padding, activation=relu, kernel_initializer=he_uniform, input_shape=(28, 28, 1)))model.add(MaxPooling2D((2, 2)))   model.add(Dropout(hp.Choice(dropout_+ str(i), values=[0.0, 0.1, 0.2])))model.add(Flatten())hp_units = hp.Int(units, min_value=25, max_value=150, step=25)model.add(Dense(hp_units, activation=relu, kernel_initializer=he_uniform))model.add(Dense(10,activation="softmax"))hp_learning_rate = hp.Choice(learning_rate, values=[1e-2, 1e-3])hp_optimizer=hp.Choice(Optimizer, values=[Adam, SGD])if hp_optimizer == Adam:hp_learning_rate = hp.Choice(learning_rate, values=[1e-2, 1e-3])elif hp_optimizer == SGD:   hp_learning_rate = hp.Choice(learning_rate, values=[1e-2, 1e-3])   nesterov=Truemomentum=0.9

像以前同样咱们让网络决定它的深度。最大迭代次数设置为 100:

model.compile( optimizer=hp_optimizer,loss=categorical_crossentropy, metrics=[accuracy])tuner_cnn = kt.tuners.BayesianOptimization(   model,   objective=val_loss,   max_trials=100,   directory=.,   project_name=tuning-cnn)

结果如下:

得到的超参数

最后运用最佳超参数训练咱们的 CNN 模型:

model_cnn = Sequential()model_cnn.add(Input(shape=(28, 28, 1)))for i in range(best_cnn_hyperparameters[num_blocks]): hp_padding=best_cnn_hyperparameters[padding_+ str(i)]hp_filters=best_cnn_hyperparameters[filters_+ str(i)]model_cnn.add(Conv2D(hp_filters, (3, 3), padding=hp_padding, activation=relu, kernel_initializer=he_uniform, input_shape=(28, 28, 1))) model_cnn.add(MaxPooling2D((2, 2))) model_cnn.add(Dropout(best_cnn_hyperparameters[dropout_+ str(i)]))model_cnn.add(Flatten())model_cnn.add(Dense(best_cnn_hyperparameters[units], activation=relu, kernel_initializer=he_uniform))model_cnn.add(Dense(10,activation="softmax"))model_cnn.compile(optimizer=best_cnn_hyperparameters[Optimizer],                                                 loss=categorical_crossentropy,                                                 metrics=[accuracy])print(model_cnn.summary())history_cnn= model_cnn.fit(train_x, train_y, epochs=50, batch_size=32, validation_data=(dev_x, dev_y), callbacks=callback)

检测测试集的准确率:

cnn_test_loss, cnn_test_acc = model_cnn.evaluate(test_x, test_y, verbose=2)print(\nTest accuracy:, cnn_test_acc)# Test accuracy: 0.92

与基线的 CNN 模型测试精度相比:

基线 CNN 模型:90.8 %

最佳 CNN 模型:92%

咱们看到优化模型的性能提高

除了准确性之外,咱们能够看到优化的效果很好,由于

在每种状况下都选取了一个非零的 Dropout 值,即使咱们供给了零 Dropout。这是意料之中的,由于 Dropout 是一种减少过拟合的机制。有趣的是,最好的 CNN 架构是标准CNN,其中过滤器的数量在每一层中逐步增多。这是意料之中的,由于随着后续层的增多,模式变得更加繁杂(这咱们在学习各样模型和论文时被证明的结果)需要更加多的过滤器才可捕捉这些模式组合。

以上例子说明Keras Tuner 是运用 Tensorflow 优化深度神经网络的很好用的工具。

咱们上面说了本文选取是贝叶斯优化器。然则还有两个其他的选项:

RandomSearch:随机选取其中的有些来避免探索超参数的全部搜索空间。然则,它不可保准会找到最佳超参数

Hyperband:选取有些超参数的随机组合,并仅运用它们来训练模型几个 epoch。而后运用这些超参数来训练模型,直到用尽所有 epoch 并从中选取最好的。

最后数据集位置和keras_tuner的文档如下

Fashion MNIST dataset by Zalando, https://www.kaggle.com/datasets/zalando-research/fashionmnist, MIT Licence (MIT) Copyright © [2017]

Keras Tuner, https://keras.io/keras_tuner/

作者:Nikos Kafritsas

MOREkaggle比赛交流和组队加我的微X,邀你进群

爱好就关注一下吧:

点个 在看 你最好看!





上一篇:运用贝叶斯优化调节深度神经网络
下一篇:华为区域LTE高负荷小区处理规范
回复

使用道具 举报

3126

主题

3万

回帖

9910万

积分

论坛元老

Rank: 8Rank: 8

积分
99108615
发表于 2024-10-15 10:36:02 | 显示全部楼层
楼主果然英明!不得不赞美你一下!
回复

使用道具 举报

3048

主题

3万

回帖

9910万

积分

论坛元老

Rank: 8Rank: 8

积分
99109040
发表于 昨天 18:03 | 显示全部楼层
你的见解真是独到,让我受益匪浅。
回复

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

站点统计|Archiver|手机版|小黑屋|天涯论坛 ( 非经营性网站 )|网站地图

GMT+8, 2024-11-23 13:25 , Processed in 0.114240 second(s), 21 queries .

Powered by Discuz! X3.4

Copyright © 2001-2023, Tencent Cloud.