翻译《How to Grid Search Hyperparameters for Deep Learning Models in Python With Keras》

您所在的位置:网站首页 驾校陪练app 翻译《How to Grid Search Hyperparameters for Deep Learning Models in Python With Keras》

翻译《How to Grid Search Hyperparameters for Deep Learning Models in Python With Keras》

2023-03-24 12:35| 来源: 网络整理| 查看: 265

原文链接:https://machinelearningmastery.com/grid-search-hyperparameters-deep-learning-models-python-keras/ 超参数优化是深度学习的重要组成部分。 因为神经网络很难配置,而且有很多参数需要设置。除此之外,一些模型的训练速度可能非常慢。 在本文中,您将了解如何使用scikit-learn中的网格搜索功能来调整Keras深度学习模型的超参数。 在阅读后你将会理解:

如何在Keras模型中使用scikit-learn和如何使用网格搜索。如何用网格搜索常用的神经网络参数,如学习率、dropout率、训练批次(epochs)和神经元数目。如何在自己的项目中定义自己的超参数调整实验。 概述

在这篇文章中,我想向您展示如何使用scikit-learn网格搜索功能,并提供一套示例,您可以将这些示例复制粘贴到自己的项目中作为起点。 下面是我们要讨论的主题列表:

如何在scikit-learn中使用Keras模型。如何在scikit-learn中使用网格搜索。如何调整batch size和training epochs。如何调整优化算法。如何调整学习率和momentum(动量)。如何调整网络权重初始化。如何调整激活函数。如何调整dropout regularization(丢弃正则化)。如何调整隐藏层中神经元的数量。 如何在scikit-learn中使用Keras模型

通过KerasClassifier 和KerasRegressor 类包装keras中的model,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, epochs=10)

KerasClassifier类的构造函数也可以通过create_model() 接受新的参数,这些新参数必须在你自己的create_model()函数中定义。 You can learn more about the scikit-learn wrapper in Keras API documentation.

def create_model(dropout_rate=0.0): ... return model model = KerasClassifier(build_fn=create_model, dropout_rate=0.2)

可以在scikit-learn wrapper in Keras API documentation了解更多信息。

如何在scikit-learn中使用网格搜索

网格搜索是一种模型超参数优化技术。

在scikit-learn中的GridSearchCV类中提供这种技术。

在构造这个类时,必须提供一个超参数字典,来在param_grid参数中求值。这个字典是要尝试的模型参数名称和值。

默认情况下,accuracy(精度)是优化的标准,但可以在GridSearchCV构造函数中的score参数中指定其他指标。

默认情况下,网格搜索将只使用一个线程。通过将GridSearchCV构造函数中的n_jobs参数设置为-1,进程将使用计算机上的所有核心。根据你的Keras后端,这可能会干扰主要的神经网络训练过程。

然后GridSearchCV将为每个参数组合构造和评估一个模型。并使用交叉验证评估每个单独的模型,默认3倍交叉验证,可以指定cv参数覆盖这个值。 下面是一个定义简单网格搜索的示例:

param_grid = dict(epochs=[10,20,30]) grid = GridSearchCV(estimator=model, param_grid=param_grid, n_jobs=-1, cv=3) grid_result = grid.fit(X, Y)

了解更多GridSearchCV class in the scikit-learn API documentation

问题

现在已经知道如何在scikit-learn中使用Keras模型,以及如何在scikit-learn中使用网格搜索,让我们看一些示例。

所有的例子都将在一个小型的标准机器学习数据集,皮马印第安人糖尿病数据集上演示。这是一个很小的数据集,所有的数值属性都很容易处理。

下载数据集,并将其放在你当前工作目录下,命名为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。

如何调整batch size和epochs大小

在第一个简单的示例中,我们将研究调batch size和拟合网络时使用的epochs。

迭代梯度下降中的batch size是在权值更新之前显示给网络的数。它也是网络训练中的一个优化,定义了一次读取多少个模式并将其保存在内存中。

epochs是指在训练期间,整个训练数据集显示给网络的次数。有些网络对批量大小很敏感,如LSTM和CNN。

在这里,我们将计算以步长为20,从10到100的不同的小batch size。

完整代码如下所示:

# Use scikit-learn to grid search the batch size and epochs import numpy from sklearn.model_selection 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, epochs=epochs) grid = GridSearchCV(estimator=model, param_grid=param_grid, n_jobs=-1, cv=3) grid_result = grid.fit(X, Y) # summarize results print("Best: %f using %s" % (grid_result.best_score_, grid_result.best_params_)) means = grid_result.cv_results_['mean_test_score'] stds = grid_result.cv_results_['std_test_score'] params = grid_result.cv_results_['params'] for mean, stdev, param in zip(means, stds, params): print("%f (%f) with: %r" % (mean, stdev, param))

输出如下:

Best: 0.686198 using {'epochs': 100, 'batch_size': 20} 0.348958 (0.024774) with: {'epochs': 10, 'batch_size': 10} 0.348958 (0.024774) with: {'epochs': 50, 'batch_size': 10} 0.466146 (0.149269) with: {'epochs': 100, 'batch_size': 10} 0.647135 (0.021236) with: {'epochs': 10, 'batch_size': 20} 0.660156 (0.014616) with: {'epochs': 50, 'batch_size': 20} 0.686198 (0.024774) with: {'epochs': 100, 'batch_size': 20} 0.489583 (0.075566) with: {'epochs': 10, 'batch_size': 40} 0.652344 (0.019918) with: {'epochs': 50, 'batch_size': 40} 0.654948 (0.027866) with: {'epochs': 100, 'batch_size': 40} 0.518229 (0.032264) with: {'epochs': 10, 'batch_size': 60} 0.605469 (0.052213) with: {'epochs': 50, 'batch_size': 60} 0.665365 (0.004872) with: {'epochs': 100, 'batch_size': 60} 0.537760 (0.143537) with: {'epochs': 10, 'batch_size': 80} 0.591146 (0.094954) with: {'epochs': 50, 'batch_size': 80} 0.658854 (0.054904) with: {'epochs': 100, 'batch_size': 80} 0.402344 (0.107735) with: {'epochs': 10, 'batch_size': 100} 0.652344 (0.033299) with: {'epochs': 50, 'batch_size': 100} 0.542969 (0.157934) with: {'epochs': 100, 'batch_size': 100}

我们可以看到,batch size为20,epochs为100时,达到了最好的结果,约68%的准确率。

如何调整训练优化算法

Keras提供了一套最先进的优化算法。 在这个例子中,我们调整用于训练网络的优化算法,每个算法都有默认参数。 这是一个奇怪的例子,因为通常你会先选择一种方法,然后专注于根据你的问题调整它的参数(例如,见下一个例子)。 在这里,我们将评估suite of optimization algorithms supported by the Keras API

完整代码如下所示:

# Use scikit-learn to grid search the batch size and epochs import numpy from sklearn.model_selection 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(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 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, epochs=100, batch_size=10, verbose=0) # define the grid search parameters optimizer = ['SGD', 'RMSprop', 'Adagrad', 'Adadelta', 'Adam', 'Adamax', 'Nadam'] param_grid = dict(optimizer=optimizer) grid = GridSearchCV(estimator=model, param_grid=param_grid, n_jobs=-1, cv=3) grid_result = grid.fit(X, Y) # summarize results print("Best: %f using %s" % (grid_result.best_score_, grid_result.best_params_)) means = grid_result.cv_results_['mean_test_score'] stds = grid_result.cv_results_['std_test_score'] params = grid_result.cv_results_['params'] for mean, stdev, param in zip(means, stds, params): print("%f (%f) with: %r" % (mean, stdev, param))

运行结果如下:

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'}

结果表明,Adam优化算法的精度达到70%左右。

如何调整学习率和Momentum

通常预先选择一种优化算法来训练网络并调整其参数。

到目前为止,最常见的优化算法是普通的老随机梯度下降(SGD),因为它是如此的容易理解。在这个例子中,我们将研究如何优化SGD学习率和动量参数。

学习速率控制在每批处理结束时更新权重的程度,动量控制让上一次更新影响当前权重更新的程度。

我们将尝试一套小的标准学习率和动量值,从0.2到0.8,步长为0.2,以及0.9(因为它在实践中可能是一个流行的值)。

一般来说,在这样的优化中也包括时间段的数量是一个好主意,因为在每批学习量(学习率)、batch size和epochs之间存在依赖关系。

完整代码如下:

# Use scikit-learn to grid search the learning rate and momentum import numpy from sklearn.model_selection import GridSearchCV from keras.models import Sequential from keras.layers import Dense from keras.wrappers.scikit_learn import KerasClassifier from keras.optimizers import SGD # Function to create model, required for KerasClassifier def 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 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, epochs=100, batch_size=10, verbose=0) # define the grid search parameters learn_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, cv=3) grid_result = grid.fit(X, Y) # summarize results print("Best: %f using %s" % (grid_result.best_score_, grid_result.best_params_)) means = grid_result.cv_results_['mean_test_score'] stds = grid_result.cv_results_['std_test_score'] params = grid_result.cv_results_['params'] for mean, stdev, param in zip(means, stds, params): print("%f (%f) with: %r" % (mean, stdev, param))

运行结果:

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%左右。

如何调整网络初始化权重

神经网络权值初始化以前很简单:使用小的随机值。 现在有一套不同的技术可供选择Keras provides a laundry list.

在这个例子中,我们将通过评估所有可用的技术来优化网络权重初始化的选择。

我们将在每个层上使用相同的权重初始化方法。理想情况下,根据每个层上使用的激活函数使用不同的权重初始化方案可能更好。在下面的例子中,我们在隐藏层上使用relu。输出层上使用sigmoid,因为预测是二分类的。 完整代码如下:

# Use scikit-learn to grid search the weight initialization import numpy from sklearn.model_selection 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(init_mode='uniform'): # create model model = Sequential() model.add(Dense(12, input_dim=8, kernel_initializer=init_mode, activation='relu')) model.add(Dense(1, kernel_initializer=init_mode, 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, epochs=100, batch_size=10, verbose=0) # define the grid search parameters init_mode = ['uniform', 'lecun_uniform', 'normal', 'zero', 'glorot_normal', 'glorot_uniform', 'he_normal', 'he_uniform'] param_grid = dict(init_mode=init_mode) grid = GridSearchCV(estimator=model, param_grid=param_grid, n_jobs=-1, cv=3) grid_result = grid.fit(X, Y) # summarize results print("Best: %f using %s" % (grid_result.best_score_, grid_result.best_params_)) means = grid_result.cv_results_['mean_test_score'] stds = grid_result.cv_results_['std_test_score'] params = grid_result.cv_results_['params'] for mean, stdev, param in zip(means, stds, params): print("%f (%f) with: %r" % (mean, stdev, param))

结果如下:

Best: 0.720052 using {'init_mode': 'uniform'} 0.720052 (0.024360) with: {'init_mode': 'uniform'} 0.348958 (0.024774) with: {'init_mode': 'lecun_uniform'} 0.712240 (0.012075) with: {'init_mode': 'normal'} 0.651042 (0.024774) with: {'init_mode': 'zero'} 0.700521 (0.010253) with: {'init_mode': 'glorot_normal'} 0.674479 (0.011201) with: {'init_mode': 'glorot_uniform'} 0.661458 (0.028940) with: {'init_mode': 'he_normal'} 0.678385 (0.004872) with: {'init_mode': 'he_uniform'}

我们可以看到,使用统一的权值初始化方案获得了最好的结果,性能达到了72%左右。

如何调整激活函数

激活函数控制单个神经元的非线性以及何时触发。

一般说来,relu激活函数是最常用的,但以前是sigmoid和tanh函数,这些函数可能仍然更适合于不同的问题。

代码如下:

# Use scikit-learn to grid search the activation function import numpy from sklearn.model_selection 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(activation='relu'): # create model model = Sequential() model.add(Dense(12, input_dim=8, kernel_initializer='uniform', activation=activation)) model.add(Dense(1, kernel_initializer='uniform', 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, epochs=100, batch_size=10, verbose=0) # define the grid search parameters activation = ['softmax', 'softplus', 'softsign', 'relu', 'tanh', 'sigmoid', 'hard_sigmoid', 'linear'] param_grid = dict(activation=activation) grid = GridSearchCV(estimator=model, param_grid=param_grid, n_jobs=-1, cv=3) grid_result = grid.fit(X, Y) # summarize results print("Best: %f using %s" % (grid_result.best_score_, grid_result.best_params_)) means = grid_result.cv_results_['mean_test_score'] stds = grid_result.cv_results_['std_test_score'] params = grid_result.cv_results_['params'] for mean, stdev, param in zip(means, stds, params): print("%f (%f) with: %r" % (mean, stdev, param))

结果如下:

Best: 0.722656 using {'activation': 'linear'} 0.649740 (0.009744) with: {'activation': 'softmax'} 0.720052 (0.032106) with: {'activation': 'softplus'} 0.688802 (0.019225) with: {'activation': 'softsign'} 0.720052 (0.018136) with: {'activation': 'relu'} 0.691406 (0.019401) with: {'activation': 'tanh'} 0.680990 (0.009207) with: {'activation': 'sigmoid'} 0.691406 (0.014616) with: {'activation': 'hard_sigmoid'} 0.722656 (0.003189) with: {'activation': 'linear'}

令人惊讶的是(至少对我来说),“线性”激活函数达到了最好的结果,准确率约为72%。

如何调整Dropout正则化

在这个例子中,我们将考虑调整正则化的dropout率,以限制过度拟合并提高模型的泛化能力。

为了获得良好的结果,dropout最好与权重约束(如max-norm约束)相结合。

有关在Keras的深度学习模型中使用dropout的更多信息,请参阅以下文章:

基于Keras的深度学习模型中的dropout正则化

这涉及到拟合dropout百分比和权重约束。我们将尝试在0.0和0.9之间的dropout百分比(1.0没有意义)和maxnorm权重约束值介于0和5之间。

代码如下:

# Use scikit-learn to grid search the dropout rate import numpy from sklearn.model_selection import GridSearchCV from keras.models import Sequential from keras.layers import Dense from keras.layers import Dropout from keras.wrappers.scikit_learn import KerasClassifier from keras.constraints import maxnorm # Function to create model, required for KerasClassifier def create_model(dropout_rate=0.0, weight_constraint=0): # create model model = Sequential() model.add(Dense(12, input_dim=8, kernel_initializer='uniform', activation='linear', kernel_constraint=maxnorm(weight_constraint))) model.add(Dropout(dropout_rate)) model.add(Dense(1, kernel_initializer='uniform', 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, epochs=100, batch_size=10, verbose=0) # define the grid search parameters weight_constraint = [1, 2, 3, 4, 5] dropout_rate = [0.0, 0.1, 0.2, 0.3, 0.4, 0.5, 0.6, 0.7, 0.8, 0.9] param_grid = dict(dropout_rate=dropout_rate, weight_constraint=weight_constraint) grid = GridSearchCV(estimator=model, param_grid=param_grid, n_jobs=-1, cv=3) grid_result = grid.fit(X, Y) # summarize results print("Best: %f using %s" % (grid_result.best_score_, grid_result.best_params_)) means = grid_result.cv_results_['mean_test_score'] stds = grid_result.cv_results_['std_test_score'] params = grid_result.cv_results_['params'] for mean, stdev, param in zip(means, stds, params): print("%f (%f) with: %r" % (mean, stdev, param))

运行结果:

Best: 0.723958 using {'dropout_rate': 0.2, 'weight_constraint': 4} 0.696615 (0.031948) with: {'dropout_rate': 0.0, 'weight_constraint': 1} 0.696615 (0.031948) with: {'dropout_rate': 0.0, 'weight_constraint': 2} 0.691406 (0.026107) with: {'dropout_rate': 0.0, 'weight_constraint': 3} 0.708333 (0.009744) with: {'dropout_rate': 0.0, 'weight_constraint': 4} 0.708333 (0.009744) with: {'dropout_rate': 0.0, 'weight_constraint': 5} 0.710937 (0.008438) with: {'dropout_rate': 0.1, 'weight_constraint': 1} 0.709635 (0.007366) with: {'dropout_rate': 0.1, 'weight_constraint': 2} 0.709635 (0.007366) with: {'dropout_rate': 0.1, 'weight_constraint': 3} 0.695312 (0.012758) with: {'dropout_rate': 0.1, 'weight_constraint': 4} 0.695312 (0.012758) with: {'dropout_rate': 0.1, 'weight_constraint': 5} 0.701823 (0.017566) with: {'dropout_rate': 0.2, 'weight_constraint': 1} 0.710938 (0.009568) with: {'dropout_rate': 0.2, 'weight_constraint': 2} 0.710938 (0.009568) with: {'dropout_rate': 0.2, 'weight_constraint': 3} 0.723958 (0.027126) with: {'dropout_rate': 0.2, 'weight_constraint': 4} 0.718750 (0.030425) with: {'dropout_rate': 0.2, 'weight_constraint': 5} 0.721354 (0.032734) with: {'dropout_rate': 0.3, 'weight_constraint': 1} 0.707031 (0.036782) with: {'dropout_rate': 0.3, 'weight_constraint': 2} 0.707031 (0.036782) with: {'dropout_rate': 0.3, 'weight_constraint': 3} 0.694010 (0.019225) with: {'dropout_rate': 0.3, 'weight_constraint': 4} 0.709635 (0.006639) with: {'dropout_rate': 0.3, 'weight_constraint': 5} 0.704427 (0.008027) with: {'dropout_rate': 0.4, 'weight_constraint': 1} 0.717448 (0.031304) with: {'dropout_rate': 0.4, 'weight_constraint': 2} 0.718750 (0.030425) with: {'dropout_rate': 0.4, 'weight_constraint': 3} 0.718750 (0.030425) with: {'dropout_rate': 0.4, 'weight_constraint': 4} 0.722656 (0.029232) with: {'dropout_rate': 0.4, 'weight_constraint': 5} 0.720052 (0.028940) with: {'dropout_rate': 0.5, 'weight_constraint': 1} 0.703125 (0.009568) with: {'dropout_rate': 0.5, 'weight_constraint': 2} 0.716146 (0.029635) with: {'dropout_rate': 0.5, 'weight_constraint': 3} 0.709635 (0.008027) with: {'dropout_rate': 0.5, 'weight_constraint': 4} 0.703125 (0.011500) with: {'dropout_rate': 0.5, 'weight_constraint': 5} 0.707031 (0.017758) with: {'dropout_rate': 0.6, 'weight_constraint': 1} 0.701823 (0.018688) with: {'dropout_rate': 0.6, 'weight_constraint': 2} 0.701823 (0.018688) with: {'dropout_rate': 0.6, 'weight_constraint': 3} 0.690104 (0.027498) with: {'dropout_rate': 0.6, 'weight_constraint': 4} 0.695313 (0.022326) with: {'dropout_rate': 0.6, 'weight_constraint': 5} 0.697917 (0.014382) with: {'dropout_rate': 0.7, 'weight_constraint': 1} 0.697917 (0.014382) with: {'dropout_rate': 0.7, 'weight_constraint': 2} 0.687500 (0.008438) with: {'dropout_rate': 0.7, 'weight_constraint': 3} 0.704427 (0.011201) with: {'dropout_rate': 0.7, 'weight_constraint': 4} 0.696615 (0.016367) with: {'dropout_rate': 0.7, 'weight_constraint': 5} 0.680990 (0.025780) with: {'dropout_rate': 0.8, 'weight_constraint': 1} 0.699219 (0.019401) with: {'dropout_rate': 0.8, 'weight_constraint': 2} 0.701823 (0.015733) with: {'dropout_rate': 0.8, 'weight_constraint': 3} 0.684896 (0.023510) with: {'dropout_rate': 0.8, 'weight_constraint': 4} 0.696615 (0.017566) with: {'dropout_rate': 0.8, 'weight_constraint': 5} 0.653646 (0.034104) with: {'dropout_rate': 0.9, 'weight_constraint': 1} 0.677083 (0.012075) with: {'dropout_rate': 0.9, 'weight_constraint': 2} 0.679688 (0.013902) with: {'dropout_rate': 0.9, 'weight_constraint': 3} 0.669271 (0.017566) with: {'dropout_rate': 0.9, 'weight_constraint': 4} 0.669271 (0.012075) with: {'dropout_rate': 0.9, 'weight_constraint': 5}

我们可以看到,20%的dropout率和4的最大范数权重约束得到了72%左右的最佳准确率。

如何调整隐层神经元的数量

隐层中神经元的数量是调节的一个重要参数。一般来说,一个层中的神经元数量控制着网络的表现能力,至少在拓扑结构中是这样。

而且,一般来说,一个足够大的单层网络可以近似任何其他神经网络,至少在理论上是这样。

在这个例子中,我们将研究调整单个隐藏层中神经元的数量。我们将尝试以5为步长从1到30的值。

一个更大的网络需要更多的训练,并且batch size和epochs应该与基于神经元的数量来优化。

代码如下:

# Use scikit-learn to grid search the number of neurons import numpy from sklearn.model_selection import GridSearchCV from keras.models import Sequential from keras.layers import Dense from keras.layers import Dropout from keras.wrappers.scikit_learn import KerasClassifier from keras.constraints import maxnorm # Function to create model, required for KerasClassifier def create_model(neurons=1): # create model model = Sequential() model.add(Dense(neurons, input_dim=8, kernel_initializer='uniform', activation='linear', kernel_constraint=maxnorm(4))) model.add(Dropout(0.2)) model.add(Dense(1, kernel_initializer='uniform', 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, epochs=100, batch_size=10, verbose=0) # define the grid search parameters neurons = [1, 5, 10, 15, 20, 25, 30] param_grid = dict(neurons=neurons) grid = GridSearchCV(estimator=model, param_grid=param_grid, n_jobs=-1, cv=3) grid_result = grid.fit(X, Y) # summarize results print("Best: %f using %s" % (grid_result.best_score_, grid_result.best_params_)) means = grid_result.cv_results_['mean_test_score'] stds = grid_result.cv_results_['std_test_score'] params = grid_result.cv_results_['params'] for mean, stdev, param in zip(means, stds, params): print("%f (%f) with: %r" % (mean, stdev, param))

结果如下:

Best: 0.714844 using {'neurons': 5} 0.700521 (0.011201) with: {'neurons': 1} 0.714844 (0.011049) with: {'neurons': 5} 0.712240 (0.017566) with: {'neurons': 10} 0.705729 (0.003683) with: {'neurons': 15} 0.696615 (0.020752) with: {'neurons': 20} 0.713542 (0.025976) with: {'neurons': 25} 0.705729 (0.008027) with: {'neurons': 30}

我们可以看到,在隐藏层中有5个神经元的网络取得了最好的结果,准确率约为71%。

超参数优化提示

本节列出了一些在调整神经网络的超参数时要考虑的便捷技巧。

k倍交叉验证(k-fold Cross Validation)。 您可以看到本文中示例的结果显示出一些差异。 使用默认的交叉验证3,但也许k = 5或k = 10会更稳定。 仔细选择交叉验证配置,以确保结果稳定。查看整个网格(Review the Whole Grid)。 不要仅仅关注最佳结果,查看整个结果网格并寻找趋势来支持配置决策。并行化(Parallelize)。 如果可以的话,请使用所有核心,神经网络训练起来很慢,我们经常想尝试很多不同的参数。 考虑分解很多AWS实例。使用数据集样本(Use a Sample of Your Dataset)。 由于网络训练速度较慢,请尝试在较小的训练数据集样本上进行训练,只是为了了解参数的一般方向,而不是最佳配置。从粗网格开始(Start with Coarse Grids)。 一旦可以缩小范围,就从粗粒度网格开始,然后放大到细粒度网格。不传输结果(Do not Transfer Results)。 结果通常是针对特定问题的。 尝试避免在遇到的每个新问题上使用喜欢的配置。 您在一个问题上发现的最佳结果不太可能转移到您的下一个项目中。 而是寻找更广泛的趋势,例如层数或参数之间的关系。可重复性是一个问题(Reproducibility is a Problem)。 尽管我们在NumPy中为随机数生成器设置了种子,但结果并非100%可再现。 网格搜索包装的Keras模型时,重现性要比本文中介绍的更多 总结

在本文中,您发现了如何使用Keras和scikit-learn在Python中调整深度学习网络的超参数。 具体来说,您了解到:

如何包装Keras模型以在scikit-learn中使用以及如何使用网格搜索。如何对Keras模型的一组不同标准神经网络参数进行网格搜索。如何设计自己的超参数优化实验。


【本文地址】


今日新闻


推荐新闻


CopyRight 2018-2019 办公设备维修网 版权所有 豫ICP备15022753号-3