原文:How to Grid Search Hyperparameters for Deep Learning Models in Python With Keras
作者:Jason Brownlee
翻译:刘崇鑫
责编:周建丁(zhoujd@csdn.net)
超参数优化是深度学习中的重要组成部分。其原因在于,神经网络是公认的难以配置,而又有很多参数需要设置。最重要的是,个别模型的训练非常缓慢。
在这篇文章中,你会了解到如何使用scikit-learn python机器学习库中的网格搜索功能调整Keras深度学习模型中的超参数。
阅读本文后,你就会了解:
- 如何包装Keras模型以便在scikit-learn中使用,以及如何使用网格搜索。
- 如何网格搜索常见的神经网络参数,如学习速率、 dropout 率、epochs 和神经元数量。
- 如何设计自己的超参数优化实验。
概述
本文主要想为大家介绍如何使用scikit-learn网格搜索功能,并给出一套代码实例。你可以将代码复制粘贴到自己的项目中,作为项目起始。
下文所涉及的议题列表:
- 如何在scikit-learn模型中使用Keras。
- 如何在scikit-learn模型中使用网格搜索。
- 如何调优批尺寸和训练epochs。
- 如何调优优化算法。
- 如何调优学习率和动量因子。
- 如何确定网络权值初始值。
- 如何选择神经元激活函数。
- 如何调优Dropout正则化。
- 如何确定隐藏层中的神经元的数量。
如何在scikit-learn模型中使用Keras
通过用KerasClassifier
或KerasRegressor
类包装Keras模型,可将其用于scikit-learn。
要使用这些包装,必须定义一个函数,以便按顺序模式创建并返回Keras,然后当构建KerasClassifier
类时,把该函数传递给build_fn
参数。
例如:
def create_model():
...
return model
model = KerasClassifier(build_fn=create_model)
KerasClassifier类
的构建器为可以采取默认参数,并将其被传递给model.fit()
的调用函数,比如 epochs数目和批尺寸(batch size)。
例如:
def create_model():
...
return model
model = KerasClassifier(build_fn=create_model, nb_epoch=10)
KerasClassifier类的构造也可以使用新的参数,使之能够传递给自定义的create_model()函数。这些新的参数,也必须由使用默认参数的 create_model() 函数的签名定义。
例如:
def create_model(dropout_rate=0.0):
...
return model
model = KerasClassifier(build_fn=create_model, dropout_rate=0.2)
您可以在Keras API文档中,了解到更多关于scikit-learn包装器的知识。
如何在scikit-learn模型中使用网格搜索
网格搜索(grid search)是一项模型超参数优化技术。
在scikit-learn中,该技术由GridSearchCV
类提供。
当构造该类时,你必须提供超参数字典,以便用来评价param_grid
参数。这是模型参数名称和大量列值的示意图。
默认情况下,精确度是优化的核心,但其他核心可指定用于GridSearchCV构造函数的score参数。
默认情况下,网格搜索只使用一个线程。在GridSearchCV构造函数中,通过将 n_jobs参数设置为-1,则进程将使用计算机上的所有内核。这取决于你的Keras后端,并可能干扰主神经网络的训练过程。
当构造并评估一个模型中各个参数的组合时,GridSearchCV会起作用。使用交叉验证评估每个单个模型,且默认使用3层交叉验证,尽管通过将cv参数指定给 GridSearchCV构造函数时,有可能将其覆盖。
下面是定义一个简单的网格搜索示例:
param_grid = dict(nb_epochs=[10,20,30])
grid = GridSearchCV(estimator=model, param_grid=param_grid, n_jobs=-1)
grid_result = grid.fit(X, Y)
一旦完成,你可以访问网格搜索的输出,该输出来自结果对象,由grid.fit()返回。best_score_成员提供优化过程期间观察到的最好的评分, best_params_描述了已取得最佳结果的参数的组合。
您可以在scikit-learn API文档中了解更多关于GridSearchCV类的知识。
问题描述
现在我们知道了如何使用scikit-learn 的Keras模型,如何使用scikit-learn 的网格搜索。现在一起看看下面的例子。
所有的例子都将在一个小型的标准机器学习数据集上来演示,该数据集被称为Pima Indians onset of diabetes 分类数据集。该小型数据集包括了所有容易工作的数值属性。
下载数据集,并把它放置在你目前工作目录下,命名为:pima-indians-diabetes.csv
。
当我们按照本文中的例子进行,能够获得最佳参数。因为参数可相互影响,所以这不是网格搜索的最佳方法,但出于演示目的,它是很好的方法。
注意并行化网格搜索
所有示例的配置为了实现并行化(n_jobs=-1)。
如果显示像下面这样的错误:
INFO (theano.gof.compilelock): Waiting for existing lock by process '55614' (I am process '55613')
INFO (theano.gof.compilelock): To manually release the lock, delete ...
结束进程,并修改代码,以便不并行地执行网格搜索,设置n_jobs=1。
如何调优批尺寸和训练epochs
在第一个简单的例子中,当调整网络时,我们着眼于调整批尺寸和训练epochs。
迭代梯度下降的批尺寸大小是权重更新之前显示给网络的模式数量。它也是在网络训练的优选法,定义一次读取的模式数并保持在内存中。
训练epochs是训练期间整个训练数据集显示给网络的次数。有些网络对批尺寸大小敏感,如LSTM复发性神经网络和卷积神经网络。
在这里,我们将以20的步长,从10到100逐步评估不同的微型批尺寸。
完整代码如下:
# Use scikit-learn to grid search the batch size and epochs
import numpy
from sklearn.grid_search import GridSearchCV
from keras.models import Sequential
from keras.layers import Dense
from keras.wrappers.scikit_learn import KerasClassifier
# Function to create model, required for KerasClassifier
def create_model():
# create model
model = Sequential()
model.add(Dense(12, input_dim=8, activation='relu'))
model.add(Dense(1, activation='sigmoid'))
# Compile model
model.compile(loss='binary_crossentropy', optimizer='adam', metrics=['accuracy'])
return model
# fix random seed for reproducibility
seed = 7
numpy.random.seed(seed)
# load dataset
dataset = numpy.loadtxt("pima-indians-diabetes.csv", delimiter=",")
# split into input (X) and output (Y) variables
X = dataset[:,0:8]
Y = dataset[:,8]
# create model
model = KerasClassifier(build_fn=create_model, verbose=0)
# define the grid search parameters
batch_size = [10, 20, 40, 60, 80, 100]
epochs = [10, 50, 100]
param_grid = dict(batch_size=batch_size, nb_epoch=epochs)
grid = GridSearchCV(estimator=model, param_grid=param_grid, n_jobs=-1)
grid_result = grid.fit(X, Y)
# summarize results
print("Best: %f using %s" % (grid_result.best_score_, grid_result.best_params_))
for params, mean_score, scores in grid_result.grid_scores_:
print("%f (%f) with: %r" % (scores.mean(), scores.std(), params))
运行之后输出如下:
Best: 0.686198 using {
'nb_epoch': 100, 'batch_size': 20}
0.348958 (0.024774) with: {
'nb_epoch': 10, 'batch_size': 10}
0.348958 (0.024774) with: {
'nb_epoch': 50, 'batch_size': 10}
0.466146 (0.149269) with: {
'nb_epoch': 100, 'batch_size': 10}
0.647135 (0.021236) with: {
'nb_epoch': 10, 'batch_size': 20}
0.660156 (0.014616) with: {
'nb_epoch': 50, 'batch_size': 20}
0.686198 (0.024774) with: {
'nb_epoch': 100, 'batch_size': 20}
0.489583 (0.075566) with: {
'nb_epoch': 10, 'batch_size': 40}
0.652344 (0.019918) with: {
'nb_epoch': 50, 'batch_size': 40}
0.654948 (0.027866) with: {
'nb_epoch': 100, 'batch_size': 40}
0.518229 (0.032264) with: {
'nb_epoch': 10, 'batch_size': 60}
0.605469 (0.052213) with: {
'nb_epoch': 50, 'batch_size': 60}
0.665365 (0.004872) with: {
'nb_epoch': 100, 'batch_size': 60}
0.537760 (0.143537) with: {
'nb_epoch': 10, 'batch_size': 80}
0.591146 (0.094954) with: {
'nb_epoch': 50, 'batch_size': 80}
0.658854 (0.054904) with: {
'nb_epoch': 100, 'batch_size': 80}
0.402344 (0.107735) with: {
'nb_epoch': 10, 'batch_size': 100}
0.652344 (0.033299) with: {
'nb_epoch': 50, 'batch_size': 100}
0.542969 (0.157934) with: {
'nb_epoch': 100, 'batch_size': 100}
我们可以看到,批尺寸为20、100 epochs能够获得最好的结果,精确度约68%。
如何调优训练优化算法
Keras提供了一套最先进的不同的优化算法。
在这个例子中,我们调整用来训练网络的优化算法,每个都用默认参数。
这个例