第9章 使用Scikit-Learn调用Keras的模型
scikit-learn是最受欢迎的Python机器学习库。本章我们将使用scikit-learn调用Keras生成的模型。本章将:
- 使用scikit-learn封装Keras的模型
- 使用scikit-learn对Keras的模型进行交叉验证
- 使用scikit-learn,利用网格搜索调整Keras模型的超参
我们开始吧。
9.1 简介
Keras在深度学习很受欢迎,但是只能做深度学习:Keras是最小化的深度学习库,目标在于快速搭建深度学习模型。基于SciPy的scikit-learn,数值运算效率很高,适用于普遍的机器学习任务,提供很多机器学习工具,包括但不限于:
- 使用K折验证模型
- 快速搜索并测试超参
Keras为scikit-learn封装了KerasClassifier和KerasRegressor。本章我们继续使用第7章的模型。
9.2 使用交叉验证检验深度学习模型
Keras的KerasClassifier和KerasRegressor两个类接受build_fn参数,传入编译好的模型。我们加入nb_epoch=150和batch_size=10这两个参数:这两个参数会传入模型的fit()方法。我们用scikit-learn的StratifiedKFold类进行10折交叉验证,测试模型在未知数据的性能,并使用cross_val_score()函数检测模型,打印结果。
# MLP for Pima Indians Dataset with 10-fold cross validation via sklearnfrom keras.models import Sequentialfrom keras.layers import Densefrom keras.wrappers.scikit_learn import KerasClassifierfrom sklearn.cross_validation import StratifiedKFoldfrom sklearn.cross_validation import cross_val_scoreimport numpyimport pandas# Function to create model, required for KerasClassifierdef create_model():# create modelmodel = Sequential()model.add(Dense(12, input_dim=8, init='uniform', activation='relu')) model.add(Dense(8, init='uniform', activation='relu')) model.add(Dense(1, init='uniform', activation='sigmoid'))# Compile modelmodel.compile(loss='binary_crossentropy', optimizer='adam', metrics=['accuracy']) return model# fix random seed for reproducibilityseed = 7numpy.random.seed(seed)# load pima indians 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=150, batch_size=10)# evaluate using 10-fold cross validationkfold = StratifiedKFold(y=Y, n_folds=10, shuffle=True, random_state=seed)results = cross_val_score(model, X, Y, cv=kfold)print(results.mean())
每轮训练会输出一次结果,加上最终的平均性能:
...Epoch 145/150692/692 [==============================] - 0s - loss: 0.4671 - acc: 0.7803Epoch 146/150692/692 [==============================] - 0s - loss: 0.4661 - acc: 0.7847Epoch 147/150692/692 [==============================] - 0s - loss: 0.4581 - acc: 0.7803Epoch 148/150692/692 [==============================] - 0s - loss: 0.4657 - acc: 0.7688Epoch 149/150692/692 [==============================] - 0s - loss: 0.4660 - acc: 0.7659Epoch 150/150692/692 [==============================] - 0s - loss: 0.4574 - acc: 0.770276/76 [==============================] - 0s0.756442244065
比起手工测试,使用scikit-learn容易的多。
9.3 使用网格搜索调整深度学习模型的参数
使用scikit-learn封装Keras的模型十分简单。进一步想:我们可以给fit()方法传入参数,KerasClassifier的build_fn方法也可以传入参数。可以利用这点进一步调整模型。
我们用网格搜索测试不同参数的性能:create_model()函数可以传入optimizer和init参数,虽然都有默认值。那么我们可以用不同的优化算法和初始权重调整网络。具体说,我们希望搜索:
- 优化算法:搜索权重的方法
- 初始权重:初始化不同的网络
- 训练次数:对模型训练的次数
- 批次大小:每次训练的数据量
所有的参数组成一个字典,传入scikit-learn的GridSearchCV类:GridSearchCV会对每组参数(2×3×3×3)进行训练,进行3折交叉检验。
计算量巨大:耗时巨长。如果模型小还可以取一部分数据试试。第7章的模型可以用,因为网络和数据集都不大(1000个数据内,9个参数)。最后scikit-learn会输出最好的参数和模型,以及平均值。
# MLP for Pima Indians Dataset with grid search via sklearnfrom keras.models import Sequentialfrom keras.layers import Densefrom keras.wrappers.scikit_learn import KerasClassifierfrom sklearn.grid_search import GridSearchCVimport numpyimport pandas# Function to create model, required for KerasClassifierdef create_model(optimizer='rmsprop', init='glorot_uniform'):# create modelmodel = Sequential()model.add(Dense(12, input_dim=8, init=init, activation='relu')) model.add(Dense(8, init=init, activation='relu')) model.add(Dense(1, init=init, activation='sigmoid'))# Compile modelmodel.compile(loss='binary_crossentropy', optimizer=optimizer, metrics=['accuracy']) return model# fix random seed for reproducibilityseed = 7numpy.random.seed(seed)# load pima indians 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)# grid search epochs, batch size and optimizeroptimizers = ['rmsprop', 'adam']init = ['glorot_uniform', 'normal', 'uniform']epochs = numpy.array([50, 100, 150])batches = numpy.array([5, 10, 20])param_grid = dict(optimizer=optimizers, nb_epoch=epochs, batch_size=batches, init=init) grid = GridSearchCV(estimator=model, param_grid=param_grid)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))
用CPU差不多要5分钟,结果如下。我们发现使用均匀分布初始化,rmsprop优化算法,150轮,批尺寸为5时效果最好,正确率约75%:
Best: 0.751302 using {'init': 'uniform', 'optimizer': 'rmsprop', 'nb_epoch': 150, 'batch_size': 5}0.653646 (0.031948) with: {'init': 'glorot_uniform', 'optimizer': 'rmsprop', 'nb_epoch': 50, 'batch_size': 5}0.665365 (0.004872) with: {'init': 'glorot_uniform', 'optimizer': 'adam', 'nb_epoch': 50, 'batch_size': 5}0.683594 (0.037603) with: {'init': 'glorot_uniform', 'optimizer': 'rmsprop', 'nb_epoch': 100, 'batch_size': 5}0.709635 (0.034987) with: {'init': 'glorot_uniform', 'optimizer': 'adam', 'nb_epoch': 100, 'batch_size': 5}0.699219 (0.009568) with: {'init': 'glorot_uniform', 'optimizer': 'rmsprop', 'nb_epoch': 150, 'batch_size': 5}0.725260 (0.008027) with: {'init': 'glorot_uniform', 'optimizer': 'adam', 'nb_epoch': 150, 'batch_size': 5}0.686198 (0.024774) with: {'init': 'normal', 'optimizer': 'rmsprop', 'nb_epoch': 50, 'batch_size': 5}0.718750 (0.014616) with: {'init': 'normal', 'optimizer': 'adam', 'nb_epoch': 50, 'batch_size': 5}0.725260 (0.028940) with: {'init': 'normal', 'optimizer': 'rmsprop', 'nb_epoch': 100, 'batch_size': 5}0.727865 (0.028764) with: {'init': 'normal', 'optimizer': 'adam', 'nb_epoch': 100, 'batch_size': 5}0.748698 (0.035849) with: {'init': 'normal', 'optimizer': 'rmsprop', 'nb_epoch': 150, 'batch_size': 5}0.712240 (0.039623) with: {'init': 'normal', 'optimizer': 'adam', 'nb_epoch': 150, 'batch_size': 5}0.699219 (0.024910) with: {'init': 'uniform', 'optimizer': 'rmsprop', 'nb_epoch': 50, 'batch_size': 5}0.703125 (0.011500) with: {'init': 'uniform', 'optimizer': 'adam', 'nb_epoch': 50, 'batch_size': 5}0.720052 (0.015073) with: {'init': 'uniform', 'optimizer': 'rmsprop', 'nb_epoch': 100, 'batch_size': 5}0.712240 (0.034987) with: {'init': 'uniform', 'optimizer': 'adam', 'nb_epoch': 100, 'batch_size': 5}0.751302 (0.031466) with: {'init': 'uniform', 'optimizer': 'rmsprop', 'nb_epoch': 150, 'batch_size': 5}0.734375 (0.038273) with: {'init': 'uniform', 'optimizer': 'adam', 'nb_epoch': 150, 'batch_size': 5}...
9.4 总结
本章关于使用scikit-learn封装并测试神经网络的性能。总结一下:
- 如何使用scikit-learn封装Keras模型
- 如何使用scikit-learn测试Keras模型的性能
- 如何使用scikit-learn调整Keras模型的超参
使用scikit-learn调整参数比手工调用Keras简便的多。
9.4.1 下一章
现在你已经知道如何如何在scikit-learn调用Keras模型:可以开工了。接下来几章我们会用Keras创造不同的端到端模型,从多类分类问题开始。
