深度学习模型通常具有许多可以调整的超参数,例如学习率、批次大小、隐藏层数、神经元数量及优化器等。为了在给定的任务和数据集上获得模型的最佳性能,我们需要找到在模型中使用的最佳超参数值。搜索最佳超参数组合的过程称为超参数优化。
在本文中,我们将介绍如何使用 Python 库 scikit-learn 和 TensorFlow- Keras 框架执行深度学习模型的超参数优化。
1. 核心步骤
利用sklearn中的RandomizedSearchCV:
- 转化为sklearn的model(其中,把tf的model转换成sklearn的model需要调用的api在tf.keras.wrappers下面)
- 定义参数集合
- 搜索参数
2. 转换为sklearn的model
虽然 Keras 是用于构建和训练深度学习模型的受欢迎框架,但它并没有内置的工具来执行超参数搜索。相反,scikit-learn 库提供了强大的工具,可用于执行高效的超参数搜索。为了在 Keras 模型中使用 scikit-learn 工具,我们需要将 Keras 模型包装成 scikit-learn 所支持的形式。
在这个步骤中,我们将使用 Keras 的 tensorflow.keras.wrappers.scikit_learn
模块将 Keras 模型转换为 scikit-learn 模型。该模块提供了一个名为 KerasRegressor
的类,它为回归问题提供了一个 scikit-learn 回归器接口。我们需要定义一个构建函数 build_model
,该函数将接受模型的超参数作为输入并返回编译好的 Keras 模型,然后将这个函数作为输入传递给 KerasRegressor
。接着用KerasRegressor的fit方法,训练模型,并传入callbacks参数。(到此只是完成了tf_keras到sklearn模型的转换)
# RandomizedSearchCV
# 1. 转化为sklearn的model
# 2. 定义参数集合
# 3. 搜索参数
def build_model(hidden_layers = 1,
layer_size = 30,
learning_rate = 3e-3):
model = keras.models.Sequential()
model.add(keras.layers.Dense(layer_size, activation='relu',
input_shape=x_train.shape[1:]))
for _ in range(hidden_layers - 1):
model.add(keras.layers.Dense(layer_size,
activation = 'relu'))
model.add(keras.layers.Dense(1))
optimizer = keras.optimizers.SGD(learning_rate)
model.compile(loss = 'mse', optimizer = optimizer)
return model
sklearn_model = KerasRegressor(
build_fn = build_model)
callbacks = [keras.callbacks.EarlyStopping(patience=5, min_delta=1e-2)]
history = sklearn_model.fit(x_train_scaled, y_train,
epochs = 10,
validation_data = (x_valid_scaled, y_valid),
callbacks = callbacks)
3.定义参数集合
现在我们已经有了可以用于超参数搜索的 scikit-learn 模型,下一步是定义我们要搜索的超参数及其值范围。在此示例中,我们将尝试对学习率、隐藏层数和每层神经元的数量进行优化。
将为学习率定义一个连续分布,而隐藏层和神经元数量将选择离散值范围。
代码语言:python代码运行次数:0复制from scipy.stats import reciprocal
# f(x) = 1/(x*log(b/a)) a <= x <= b
param_distribution = {
"hidden_layers":[1, 2, 3, 4],
"layer_size": np.arange(1, 100),
"learning_rate": reciprocal(1e-4, 1e-2),
}
参数定义在param_distribution这么一个dict里面,需要注意的是,learning_rate取的是连续值,所以需要给一个分布,这里调用的是scipy的reciprocal分布,最小值和最大值是1e-4和1e-2。
4.搜索参数
在本例中,我们将使用 RandomizedSearchCV
进行超参数搜索需要传入sklearn的模型,以及参数的dict,n_iter是采样数,cv是交叉验证参数,n_jobs是并行数。与 GridSearchCV
不同RandomizedSearchCV
不会尝试所有可能的参数组合,而是从参数分布中随机抽样。这通常会产生更快的结果,并在许多情况下(尤其是在参数空间非常大时)能够获得合适的参数组合。定义完之后,使用fit开始训练。训练的过程中它会自己交叉验证,并用全量数据做训练。
from sklearn.model_selection import RandomizedSearchCV
random_search_cv = RandomizedSearchCV(sklearn_model,
param_distribution,
n_iter = 10,
cv = 3,
n_jobs = 1)
random_search_cv.fit(x_train_scaled, y_train, epochs = 100,
validation_data = (x_valid_scaled, y_valid),
callbacks = callbacks)
# cross_validation: 训练集分成n份,n-1训练,最后一份验证.
执行此代码后,将获得一个最佳超参数组合的输出。进一步,可以将搜索到的最佳超参数值用于训练 Keras 模型。可以使用random_search_cv.best_estimator_
获取最佳模型。
print(random_search_cv.best_params_)
print(random_search_cv.best_score_)
print(random_search_cv.best_estimator_)
代码语言:javascript复制{'hidden_layers': 3, 'layer_size': 94, 'learning_rate': 0.009963250731270197}
-0.3331597646077474
<tensorflow.python.keras.wrappers.scikit_learn.KerasRegressor object at 0x7fc0c0212310>
In [13]:
model **=** random_search_cv.best_estimator_.model
model.evaluate(x_test_scaled, y_test)
162/162 [==============================] - 0s 807us/step - loss: 0.3224
Out[13]:
0.32240527868270874
本文介绍了使用 scikit-learn 和 Keras 进行深度学习超参数优化的方法。我们学会了如何将 Keras 模型转换为 scikit-learn 模型,定义超参数分布和范围,以及利用RandomizedSearchCV
执行参数搜索。这使得在Keras 模型中优化超参数更加简便和高效。最后,对于具体任务和数据,通过实验证据和调整搜索方法和参数来找到最佳超参数组合。