在前一篇文案中,咱们介绍了一个运用Tensorflow和深度学习办法进行图像归类的案例科研。
尽管案例科研很少,但它展示了设备学习项目的每一个周期:清理、预处理、模型构建、训练和评定。但咱们跳过了调优。
在本文中,咱们将深入科研超参数优化。一样,咱们将运用Tensorflow中包括的Fashion MNIST[1]数据集。
提醒一下,数据集包括60000个 训练集中的灰度图像和10,000 测试集中的图像。每一个照片表率属于10个类别(“T恤/上衣”、“裤子”、“套头衫”等)之一的时尚项目。因此呢,咱们有一个多类归类问题。
设置
我将简要介绍准备数据集的过程。相关更加多信息,请查看上一篇文案的第1部分:简而言之,过程如下:
加载数据。
分为训练、验证和测试集。
规范化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 variable
train_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+
快速提醒一下,超参数调节是设备学习项目的基本部分。超参数有两种类型:
结构超参数:定义模型整体架构的超参数(例如,隐匿单元的数量、层数)
优化器超参数:影响训练速度和质量的参数(例如,优化器的学习速度和类型、批次体积、epoch数) 为何调优很棘手?
为何需要超参数调优库?咱们不可尝试所有可能的组合,瞧瞧验证集上什么是最好的吗?
不幸的是,无:
深层神经网络需要海量时间来训练,乃至需要几天。
倘若你在云上训练大型模型(例如亚马逊Sagemaker),记住每次实验都要花钱。
因此呢,一种限制超参数搜索空间的剪枝策略是必要的。 贝叶斯优化
幸运的是,Keras调节器供给了贝叶斯优化调节器。贝叶斯优化调节器无搜索每一个可能的组合,而是遵循一个迭代过程,随机选取前几个。而后,基于这些超参数的性能,贝叶斯调节器选取下一个可能的最佳。
因此呢,每一个超参数的选取都取决于先前的尝试。按照历史选取下一组超参数并评定性能的迭代次数将连续,直到调节器找到最佳组合或用尽最大次数的尝试。咱们能够用参数“max_trials”来配置它。
除了贝叶斯优化调节器之外,Keras调节器还供给了两个调节器:RandomSearch和Hyperband。咱们将在本文末尾讨论它们。
回到咱们的例子
接下来,咱们将对网络应用超参数调节。在上一篇文案中,咱们尝试了两种网络架构,标准多层感知器(MLP)和卷积神经网络(CNN)。 多层感知器(MLP)
但首要,让咱们记住咱们的基线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:设置值为整数的超参数范围-例如,“Dense”层中的隐匿单位数: 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=True momentum=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%! 卷积神经网络(CNN)
一样,咱们将遵循相同的程序。运用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
Conv层上的有效或相同填充
最后附加层的隐匿层体积:25–150,乘以25
优化器:SGD(nesterov=真,动量=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
]) elifhp_optimizer ==SGD
: hp_learning_rate = hp.Choice(learning_rate, values=[1e-2, 1e-3
]) nesterov=True momentum=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
))) foriin 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架构是标准管道,其中每层中的滤波器数量逐步增多。这是意料之中的,由于随着后续层中的计算向前推进,模式变得更加繁杂。因此呢,有更加多的模式组合需要更加多的滤波器才可被捕捉。
结束
毫无疑问,Keras Tuner是运用Tensorflow优化深度神经网络的通用工具。
最显著的选取是贝叶斯优化调节器。然则,还有两个选项能够运用:
随机搜索:这种类型的调节器经过随机选取几个超参数来避免探索超参数的全部搜索空间。然则,它不可保证此调节器会找到最佳调节器。
Hyperband:这个调节器选取有些超参数的随机组合,并运用它们来训练模型,只用于几个epoch。而后,调节器运用这些超参数来训练模型,直到所有的epoch都用完,并从中选取最好的。
感谢阅读!
参考引用
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/ ✄-----------------------------------------------
看到这儿,说明你爱好这篇文案,请点击「在看」或顺手「转发」「点赞」。
欢迎微X搜索「panchuangxx」,添加博主磐小小仙微X,每日伴侣圈更新一篇高质量推文(无宣传),为您供给更加多精彩内容。
▼ ▼ 扫描二维码添加博主 ▼▼
|