引言
本文是 Python 系列的第十五篇,也是深度学习框架的 Keras 下篇。整套 Python 盘一盘系列目录如下:
回顾《Keras 中篇》介绍的多输出模型,在线性回归两队得分的模型中,直接使用了三个超参数的值:
这几个参数不是随意设定的,当然很多情况下使用 Adam 优化器中默认学习率 0.001 效果就不错,但是对此同时回归两队得分的任务效果很差,因此需要 Keras 自带的“调参神器” Keras Tuner 来调节学习率。此过程称为超参数调整 (hypertuning)。超参数是控制训练过程和机器学习模型拓扑的变量,它们在训练过程中保持不变,有三种类型:
Keras Tuner 只能调节前两种超参数,第一节会介绍,而第三种超参数需要通过Keras Wrapper 加上 sklearn.model_selection 库来调节,第二节会介绍。首先安装并引入 Keras Tuner。
!pip install -q -U keras-tunerimport kerastuner as kt
1
Keras Tuner 调参
当构建用于调参模型时,除了原模型架构之外,还需要定义超参数搜索空间,称为超模型 (hypermodel)。定义超模型有两种方式:
注意两种方法都包含参数 hp,实际上需要语句 hp = kt.HyperParameters() 来创建它,但为了代码更好维护,hp 已被内联定义 (defined inline) 在上述两种方法中了。作为超参数采样对象,hp 有以下几种类型:
此外还可使用 hp.get(name) 可获取超参数的最新值。
超模型构建完毕之后,就需要设定调参方式了,Keras Tuner 有四个选项:
接下来将使用 Hyperband 调参器。要实例化它,需要指定超模型,优化目标以及训练最大期数等。
打印出搜索空间的信息。
tuner.search_space_summary()
Search space summary
Default search space size: 1
learning_rate (Choice)
{'default': 0.1, 'conditions': [], 'values': [0.1, 0.01, 0.001], 'ordered': True}
然后搜索最佳的超参数配置。搜索超参的语法 tuner.search() 和拟合模型的语法 model.fit() 很相似。
tuner.search( train[['seed_diff']], train[['score_1','score_2']], epochs=10, validation_split=0.2 )
Trial 3 Complete [00h 00m 00s]
val_loss: 68.01530456542969
Best val_loss So Far: 53.07466125488281
Total elapsed time: 00h 00m 02s
在搜索中,根据 hp 对象中的超参数空间的每种配置,会调用模型构建函数 build_model里的模型,并记录每种配置下运行的指标。最后用.results_summary() 方法可查看调参总结,或者去 my_dir/ 路径下查找详细的日志。
tuner.results_summary()
根据上面结果,选取最低 Score 即最低验证损失 53.07 对应的超参数 0.1,这样就定下了 Adam 优化器里的最优学习率为 0.1。
Keras Tuner 中不论是用函数还是子类化创建超模型,只能调节所有在 model.compile() 之前出现的超参数,不能调节在 model.fit() 时出现的超参数,比如 epochs 和 batch_size,要调节这两者需要用到在 Keras 中 Scikit-Learn API 的封装器。在下节讲解它之前先用一图来总结用函数构建超模型的过程。
2
Keras Wrapper 调参
在 Keras 中可通过以下两种方式创建 “ScikitLearn” 中的估计器:
通过包装模型可以利用 Scikit Learn 强大的工具来将深度学习模型应用于一般的机器学习过程,具体而言,Keras 中的神经网络模型可享受 Scikit Learn 中的估计器所有功能,比如原估计器 model_selection 下的超参数调节的几个模块。
首先引入必要模块,由于该模型本质是线性回归,因此引入 kerasRegressor;在本例中使用随机追踪法,因此引入RandomizedSearchCV。
from sklearn.model_selection import RandomizedSearchCVfrom keras.wrappers.scikit_learn import KerasRegressor
构建 Keras 模型,配上上节用 Keras Tuner 调节得到的最优学习率 0.1。
def create_model(): input_tensor = Input(shape=(1,)) output_tensor = Dense(2)(input_tensor) model = Model(input_tensor, output_tensor) model.compile( optimizer=Adam(learning_rate=0.1), loss='mae' ) return model
构建模型后,将其签名 create_model 赋予 kerasRegressor 函数中的参数 build_fn,得到 models。可把 models 想象成很多神经网络模型,拟合它们的语法都是
models.fit(X, y, epochs, batch_size,… )
随机追踪 RandomizedSearchCV更进一步,设定好其参数 param_distributions,具体来说:
然后在每组参数配置上随机选取运行 models 并记录对应的指标,代码如下:
当运行完 random_search.fit()之后,最优参数、得分和模型可通过以下字段获取。
以上结果都是通过 RandomizedSearchCV 在超参数组合随机选取 10 组 (n_iter=10),然后根据 3 折交叉验证 (cv=3) 得到的。要查看更详细的信息,可用 .cv_results 字段。下图按测试分数均值从高到低排序画出折线图,并添加相对应的拟合模型耗时的折线图。
cv_results = results.cv_results_
idx = np.argsort(cv_results['mean_test_score'])[::-1]param_grp = [ cv_results['params'][i] for i in idx ]score = cv_results['mean_test_score'][idx]std = cv_results['std_test_score'][idx]
fit_time = cv_results['mean_fit_time'][idx]fit_time_std = cv_results['std_fit_time'][idx]
fig = plt.figure(figsize=(10,3))x = np.arange(len(param_grp))ax = fig.add_subplot(1,1,1)
ax.plot( x, score, 'o-', color='b', label='score')ax.fill_between( x, score-std, score+std, alpha=0.1, color='b')ax.set_xticks(x)ax.set_xticklabels( param_grp, rotation=90 )ax.set_ylabel('score')ax.legend(loc='upper right')
ax1 = ax.twinx()ax1.plot( x, fit_time, 'd-', color='r', label='time')ax1.fill_between( x, fit_time-fit_time_std, fit_time+fit_time_std, alpha=0.1, color='r')ax1.set_ylabel('time')ax1.legend(loc='center right')
plt.show()
均衡考虑使用不同参数组合情况下模型的得分和用时,最终选择超参数组 epochs = 50, batch_size = 128,和第一节用 Keras Tuner 选择的 Adam 优化器中 learning_rate = 0.1 一起作为模型的最优超参数。在多输出模型那节也是用这组参数来训练模型的。
Python 付费精品视频课
6 节 Python 数据分析 (NumPy/Pandas/Scipy) 课:
11 节 Python 基础课:
今年还会出 Python 三个系列: