Keras/Python深度学习中的网格搜索超参数调优(上)

原文: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网格搜索功能,并给出一套代码实例。你可以将代码复制粘贴到自己的项目中,作为项目起始。

下文所涉及的议题列表:

  1. 如何在scikit-learn模型中使用Keras。
  2. 如何在scikit-learn模型中使用网格搜索。
  3. 如何调优批尺寸和训练epochs。
  4. 如何调优优化算法。
  5. 如何调优学习率和动量因子。
  6. 如何确定网络权值初始值。
  7. 如何选择神经元激活函数。
  8. 如何调优Dropout正则化。
  9. 如何确定隐藏层中的神经元的数量。

如何在scikit-learn模型中使用Keras

通过用KerasClassifierKerasRegressor类包装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 epochsimport numpyfrom sklearn.grid_search import GridSearchCVfrom keras.models import Sequentialfrom keras.layers import Densefrom keras.wrappers.scikit_learn import KerasClassifier# Function to create model, required for KerasClassifierdef 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 reproducibilityseed = 7numpy.random.seed(seed)# load datasetdataset = numpy.loadtxt("pima-indians-diabetes.csv", delimiter=",")# split into input (X) and output (Y) variablesX = dataset[:,0:8]
Y = dataset[:,8]# create modelmodel = KerasClassifier(build_fn=create_model, verbose=0)# define the grid search parametersbatch_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 resultsprint("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提供了一套最先进的不同的优化算法。

在这个例子中,我们调整用来训练网络的优化算法,每个都用默认参数。

这个例子有点奇怪,因为往往你会先选择一种方法,而不是将重点放在调整问题参数上(参见下一个示例)。

在这里,我们将评估Keras API支持的整套优化算法

完整代码如下:

# Use scikit-learn to grid search the batch size and epochsimport numpyfrom sklearn.grid_search import GridSearchCVfrom keras.models import Sequentialfrom keras.layers import Densefrom keras.wrappers.scikit_learn import KerasClassifier# Function to create model, required for KerasClassifierdef create_model(optimizer='adam'):
    # 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=optimizer, metrics=['accuracy'])    return model    # fix random seed for reproducibilityseed = 7numpy.random.seed(seed)    # load datasetdataset = numpy.loadtxt("pima-indians-diabetes.csv", delimiter=",")# split into input (X) and output (Y) variablesX = dataset[:,0:8]
Y = dataset[:,8]# create modelmodel = KerasClassifier(build_fn=create_model, nb_epoch=100, batch_size=10, verbose=0)# define the grid search parametersoptimizer = ['SGD', 'RMSprop', 'Adagrad', 'Adadelta', 'Adam', 'Adamax', 'Nadam']
param_grid = dict(optimizer=optimizer)
grid = GridSearchCV(estimator=model, param_grid=param_grid, n_jobs=-1)
grid_result = grid.fit(X, Y)# summarize resultsprint("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.704427 using {'optimizer': 'Adam'}0.348958 (0.024774) with: {'optimizer': 'SGD'}0.348958 (0.024774) with: {'optimizer': 'RMSprop'}0.471354 (0.156586) with: {'optimizer': 'Adagrad'}0.669271 (0.029635) with: {'optimizer': 'Adadelta'}0.704427 (0.031466) with: {'optimizer': 'Adam'}0.682292 (0.016367) with: {'optimizer': 'Adamax'}0.703125 (0.003189) with: {'optimizer': 'Nadam'}

结果表明,ATOM优化算法结果最好,精确度约为70%。

如何优化学习速率和动量因子?

预先选择一个优化算法来训练你的网络和参数调整是十分常见的。目前,最常用的优化算法是普通的随机梯度下降法(Stochastic Gradient Descent,SGD),因为它十分易于理解。在本例中,我们将着眼于优化SGD的学习速率和动量因子(momentum)。

学习速率控制每批(batch)结束时更新的权重,动量因子控制上次权重的更新对本次权重更新的影响程度。

我们选取了一组较小的学习速率和动量因子的取值范围:从0.2到0.8,步长为0.2,以及0.9(实际中常用参数值)。

一般来说,在优化算法中包含epoch的数目是一个好主意,因为每批(batch)学习量(学习速率)、每个 epoch更新的数目(批尺寸)和 epoch的数量之间都具有相关性。

完整代码如下:

# Use scikit-learn to grid search the learning rate and momentumimport numpyfrom sklearn.grid_search import GridSearchCVfrom keras.models import Sequentialfrom keras.layers import Densefrom keras.wrappers.scikit_learn import KerasClassifierfrom keras.optimizers import SGD# Function to create model, required for KerasClassifierdef create_model(learn_rate=0.01, momentum=0):
    # create model
    model = Sequential()
    model.add(Dense(12, input_dim=8, activation='relu'))
    model.add(Dense(1, activation='sigmoid'))    # Compile model
    optimizer = SGD(lr=learn_rate, momentum=momentum)
    model.compile(loss='binary_crossentropy', optimizer=optimizer, metrics=['accuracy'])    return model    # fix random seed for reproducibilityseed = 7numpy.random.seed(seed)    # load datasetdataset = numpy.loadtxt("pima-indians-diabetes.csv", delimiter=",")    # split into input (X) and output (Y) variablesX = dataset[:,0:8]
Y = dataset[:,8]    # create modelmodel = KerasClassifier(build_fn=create_model, nb_epoch=100, batch_size=10, verbose=0)    # define the grid search parameterslearn_rate = [0.001, 0.01, 0.1, 0.2, 0.3]
momentum = [0.0, 0.2, 0.4, 0.6, 0.8, 0.9]
param_grid = dict(learn_rate=learn_rate, momentum=momentum)
grid = GridSearchCV(estimator=model, param_grid=param_grid, n_jobs=-1)
grid_result = grid.fit(X, Y)    # summarize resultsprint("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.680990 using {'learn_rate': 0.01, 'momentum': 0.0}0.348958 (0.024774) with: {'learn_rate': 0.001, 'momentum': 0.0}0.348958 (0.024774) with: {'learn_rate': 0.001, 'momentum': 0.2}0.467448 (0.151098) with: {'learn_rate': 0.001, 'momentum': 0.4}0.662760 (0.012075) with: {'learn_rate': 0.001, 'momentum': 0.6}0.669271 (0.030647) with: {'learn_rate': 0.001, 'momentum': 0.8}0.666667 (0.035564) with: {'learn_rate': 0.001, 'momentum': 0.9}0.680990 (0.024360) with: {'learn_rate': 0.01, 'momentum': 0.0}0.677083 (0.026557) with: {'learn_rate': 0.01, 'momentum': 0.2}0.427083 (0.134575) with: {'learn_rate': 0.01, 'momentum': 0.4}0.427083 (0.134575) with: {'learn_rate': 0.01, 'momentum': 0.6}0.544271 (0.146518) with: {'learn_rate': 0.01, 'momentum': 0.8}0.651042 (0.024774) with: {'learn_rate': 0.01, 'momentum': 0.9}0.651042 (0.024774) with: {'learn_rate': 0.1, 'momentum': 0.0}0.651042 (0.024774) with: {'learn_rate': 0.1, 'momentum': 0.2}0.572917 (0.134575) with: {'learn_rate': 0.1, 'momentum': 0.4}0.572917 (0.134575) with: {'learn_rate': 0.1, 'momentum': 0.6}0.651042 (0.024774) with: {'learn_rate': 0.1, 'momentum': 0.8}0.651042 (0.024774) with: {'learn_rate': 0.1, 'momentum': 0.9}0.533854 (0.149269) with: {'learn_rate': 0.2, 'momentum': 0.0}0.427083 (0.134575) with: {'learn_rate': 0.2, 'momentum': 0.2}0.427083 (0.134575) with: {'learn_rate': 0.2, 'momentum': 0.4}0.651042 (0.024774) with: {'learn_rate': 0.2, 'momentum': 0.6}0.651042 (0.024774) with: {'learn_rate': 0.2, 'momentum': 0.8}0.651042 (0.024774) with: {'learn_rate': 0.2, 'momentum': 0.9}0.455729 (0.146518) with: {'learn_rate': 0.3, 'momentum': 0.0}0.455729 (0.146518) with: {'learn_rate': 0.3, 'momentum': 0.2}0.455729 (0.146518) with: {'learn_rate': 0.3, 'momentum': 0.4}0.348958 (0.024774) with: {'learn_rate': 0.3, 'momentum': 0.6}0.348958 (0.024774) with: {'learn_rate': 0.3, 'momentum': 0.8}0.348958 (0.024774) with: {'learn_rate': 0.3, 'momentum': 0.9}

可以看到,SGD在该问题上相对表现不是很好,但当学习速率为0.01、动量因子为0.0时可取得最好的结果,正确率约为68%。

原文发布于微信公众号 - 人工智能头条(AI_Thinker)

原文发表时间:2016-08-19

本文参与腾讯云自媒体分享计划,欢迎正在阅读的你也加入,一起分享。

发表于

我来说两句

0 条评论
登录 后参与评论

相关文章

来自专栏LhWorld哥陪你聊算法

【TensorFlow篇】--Tensorflow框架可视化之Tensorboard

TensorBoard是tensorFlow中的可视化界面,可以清楚的看到数据的流向以及各种参数的变化,本文基于一个案例讲解TensorBoard的用法。

15120
来自专栏Deep Learning 笔记

图像识别(二) cifar10_input.py详解

tf.variable_scope和tf.name_scope的用法:https://blog.csdn.net/uestc_c2_403/article/de...

65560
来自专栏PaddlePaddle

【命名实体识别】训练端到端的序列标注模型

导语 PaddlePaddle提供了丰富的运算单元,帮助大家以模块化的方式构建起千变万化的深度学习模型来解决不同的应用问题。这里,我们针对常见的机器学习任务,提...

81180
来自专栏书山有路勤为径

第四天-模型选择

每次将不同的包用作测试集,剩下的作为训练集,然后求结果的平均值,得到最终模型。

8010
来自专栏瓜大三哥

图像分割(六)

图像分割(六) 之基于FPGA的局部自适应分割 子模块设计 顶层模块gauss_segment_2d 有了以上几个模块,顶层设计就十分简单了。需要例化一个均值...

239100
来自专栏机器学习算法工程师

从0 到1 实现YOLO v3(part two)

本部分是 从0到1 实现YOLO v3 的第二部分 的第二部分,前两部分主要介绍了YOLO的工作原理,包含的模块的介绍以及如何用pytorch搭建完整的YOL...

86940
来自专栏大数据挖掘DT机器学习

用python实现支持向量机对婚介数据的用户配对预测

网上有人用libsvm2.89在Python2.6成功。(一定要libsvm2.89搭配python2.6,其他版本都不能成功,我就是浪费了大量时间在这里!) ...

40750
来自专栏超智能体

YJango:TensorFlow高层API Custom Estimator建立CNN+RNN的演示

该文是YJango:TensorFlow中层API Datasets+TFRecord的数据导入的后续。

1.6K70
来自专栏贾志刚-OpenCV学堂

OpenCV中KMeans算法介绍与应用

一:KMeans算法介绍 ? KMeans算法MacQueen在1967年提出的,是最简单与最常见数据分类方法之一并且最为一种常见数据分析技术在机器学习、数据挖...

421100
来自专栏Python中文社区

用Python从零开始构造决策树

專 欄 ❈ 作者:weapon,不会写程序的浴室麦霸不是好的神经科医生 ❈ 起步 本章介绍如何不利用第三方库,仅用python自带的标准库来构造一个决策树。 ...

22670

扫码关注云+社区

领取腾讯云代金券