在Keras中使用Scikit-Learn进行模型评估和调参

在Keras中使用Scikit-Learn

Keras是python在深度学习领域非常受欢迎的类库之一,但Keras的侧重点是深度学习,而不是所有的机器学习。事实上,Keras力求极简主义,只专注于快速,简单的定义和构建深度学习模型所需要的内容。python中的Scikit-Learn是一个非常受欢迎的机器学习库,它基于scipy,用于高效的数值计算。
Keras库为深度学习提供了一个包装类(Wrapper),将Keras的深度学习模型包装成Scikit-Learn中的分类模型或回归模型,以便于方便的使用Scikit-Learn中的方法和函数。对深度学习模型的包装是通过kerasClassifier(分类模型)和KerasRegressor(回归模型)来实现的。本文将介绍如何使用KerasClassifier在Keras中创建神经网络分类模型,并在Scikit-Learn中使用。本文的数据集使用Pima Indians糖尿病数据集,读者可自行下载(下载链接为:链接: link。本文将介绍使用K折交叉验证和利用网格搜索算法进行调参。

使用交叉验证评估模型

kerasClassfier和kerasRegressor类使用参数build_fn,指定用来创建模型的函数名称。所以,必须要定义一个函数,并通过函数来定义深度学习的模型,编译并返回它。在下面的例子中,定义了利用create_model()函数创建一个简单的多层神经网络。
除通过使用build_fn参数将这个函数传递给KerasClassfier类之外,还设置epochs参数为150,batch_size为10,并传递这两个参数为KerasClassfier实例。参数将自动绑定并传递给由KerasClassfier类内部调用的fit()函数。在这个例子中,使用Scikit-Learn中的StratifiedKFold()来执行10折交叉验证。使用Scikit-Learn中的函数cross_val_score()来评估深度学习模型并输出结果,代码如下:

from keras.models import Sequential
from keras.layers import Dense
import numpy as np
from sklearn.model_selection import cross_val_score
from sklearn.model_selection import StratifiedKFold
from keras.wrappers.scikit_learn import KerasClassifier

# 构建模型
def create_model():
    #  构建模型
    model = Sequential()
    model.add(Dense(units=12,input_dim=8,activation='relu'))
    model.add(Dense(units=8,activation='relu'))
    model.add(Dense(units=1,activation='sigmoid'))

    #编译模型
    model.compile(loss='binary_crossentropy',optimizer='adam',metrics=['accuracy'])

    return model
seed = 7
# 设置随机种子
np.random.seed(seed)

#导入数据
datsets = np.loadtxt('pima-indians-diabetes.csv',delimiter=',')
x = datsets[:,0:8]
Y = datsets[:,8]
# 创建模型 for Scikit-Learn
model = KerasClassifier(build_fn=create_model,epochs=150,batch_size=10,verbose=0)
# 10折交叉验证
kfold = StratifiedKFold(n_splits=10,shuffle=True,random_state=seed)
results = cross_val_score(model,x,Y,cv=kfold)
print(results.mean())

执行代码可以得到10折交叉验证的准确度均值。

深度学习模型调参

前面的例子展示了如何使用Keras包装类,来使用Scikit-Learn的功能评估深度学习的模型。通过fit()函数提供参数的方式,来设置深度学习模型训练时的参数epochs和batch_size。在创建kerasClassfier包装类实例时,可以同时给build_fn函数传递参数,进而可以使用这些参数来定制模型的结构。
在构建深度学习模型时,如何配置一个最优模型一直是进行一个项目的重点。在机器学习中,可以通过算法自动调优这些配置参数。在这里将介绍一个例子,通过Keras的包装类,借助Scikit-Learn的网格搜索算法来评估神经网络模型的不同配置,并找到最佳评估性能的参数组合。creat_model()函数被定义为具有两个默认的参数(optimizer)和init()函数,这便于神经网络使用不同优化器和权重初始方案进行评估。创建模型后,定义要搜索的参数的值数组,包括优化器(optimizer)、权重初始化方案(init)、epochs和batch_size。
在Scikit-Learn中的GridSearchCV需要一个字典类型的字段作为需要调参的参数,默认采用3折交叉验证来评估算法,由于有4个参数需要进行调参,因此将产生4×3个模型。如果参数比价多,会生成比较多模型,因此需要大量的计算。也许这种方法在大数据量的情况下是不合适的,但是对少量数据实验是非常有效的方法。示例代码如下:

from keras.models import Sequential
from keras.layers import Dense
import numpy as np
from sklearn.model_selection import GridSearchCV
from keras.wrappers.scikit_learn import KerasClassifier
import time
start_time = time.process_time()
# 构建模型
def create_model(optimizer='adam',init='glorot_uniform'):
    # 构建模型
    model = Sequential()
    model.add(Dense(units=12,kernel_initializer=init,input_dim=8,activation='relu'))
    model.add(Dense(units=8,kernel_initializer=init,activation='relu'))
    model.add(Dense(units=1,kernel_initializer=init,activation='sigmoid'))
    # 编译模型
    model.compile(loss='binary_crossentropy',optimizer=optimizer,metrics=['accuracy'])
    return model

seed = 7
np.random.seed(seed)
# 导入数据
datasets = np.loadtxt('pima-indians-diabetes.csv',delimiter=',')
x = datasets[:,0:8]
Y = datasets[:,8]
# 创建模型 for Scikit-Learn
model = KerasClassifier(build_fn=create_model,verbose=0)

# 构建需要调参的参数
param_grid = {}
param_grid['optimizer'] = ['rmsprop','adam']
param_grid['init'] = ['glorot_uniform','normal','uniform']
param_grid['epochs'] = [50,100,150,200]
param_grid['batch_size'] = [5,10,20]

#调参
grid = GridSearchCV(estimator=model,param_grid=param_grid)
result = grid.fit(x,Y)

# 输出结果
print('Best: %f using %s' % (result.best_score_,result.best_params_))
means = result.cv_results_['mean_test_score']
stds = result.cv_results_['std_test_score']
params = result.cv_results_['params']

for mean,std,param in zip(means,stds,params):
    print('%f(%f) with: %r' %(mean,std,param))
end_time = time.process_time()
print("程序运行时间为:%d " % (end_time-start_time))

我用的笔记本是16年的联想i7,计算时间大概是半个小时左右。通常运行一次不一定能找到最优参数组合,当最优参数组合为参数列表的临界值时,需要再次配置参数重新执行。执行结果中的第一行输出,为通过网格搜索得到的最优参数。执行结果如下:

Best: 0.760417 using {'batch_size': 5, 'epochs': 150, 'init': 'normal', 'optimizer': 'adam'}
0.680990(0.006639) with: {'batch_size': 5, 'epochs': 50, 'init': 'glorot_uniform', 'optimizer': 'rmsprop'}
0.690104(0.019225) with: {'batch_size': 5, 'epochs': 50, 'init': 'glorot_uniform', 'optimizer': 'adam'}
0.692708(0.013279) with: {'batch_size': 5, 'epochs': 50, 'init': 'normal', 'optimizer': 'rmsprop'}
0.695312(0.014616) with: {'batch_size': 5, 'epochs': 50, 'init': 'normal', 'optimizer': 'adam'}
0.712240(0.017566) with: {'batch_size': 5, 'epochs': 50, 'init': 'uniform', 'optimizer': 'rmsprop'}
0.705729(0.001841) with: {'batch_size': 5, 'epochs': 50, 'init': 'uniform', 'optimizer': 'adam'}
0.704427(0.007366) with: {'batch_size': 5, 'epochs': 100, 'init': 'glorot_uniform', 'optimizer': 'rmsprop'}
0.708333(0.009207) with: {'batch_size': 5, 'epochs': 100, 'init': 'glorot_uniform', 'optimizer': 'adam'}
0.731771(0.013279) with: {'batch_size': 5, 'epochs': 100, 'init': 'normal', 'optimizer': 'rmsprop'}
0.721354(0.023510) with: {'batch_size': 5, 'epochs': 100, 'init': 'normal', 'optimizer': 'adam'}
0.720052(0.017566) with: {'batch_size': 5, 'epochs': 100, 'init': 'uniform', 'optimizer': 'rmsprop'}
0.738281(0.029232) with: {'batch_size': 5, 'epochs': 100, 'init': 'uniform', 'optimizer': 'adam'}
0.688802(0.037783) with: {'batch_size': 5, 'epochs': 150, 'init': 'glorot_uniform', 'optimizer': 'rmsprop'}
0.707031(0.039964) with: {'batch_size': 5, 'epochs': 150, 'init': 'glorot_uniform', 'optimizer': 'adam'}
0.744792(0.031304) with: {'batch_size': 5, 'epochs': 150, 'init': 'normal', 'optimizer': 'rmsprop'}
0.760417(0.028940) with: {'batch_size': 5, 'epochs': 150, 'init': 'normal', 'optimizer': 'adam'}
0.736979(0.021710) with: {'batch_size': 5, 'epochs': 150, 'init': 'uniform', 'optimizer': 'rmsprop'}
0.747396(0.017566) with: {'batch_size': 5, 'epochs': 150, 'init': 'uniform', 'optimizer': 'adam'}
0.687500(0.024080) with: {'batch_size': 5, 'epochs': 200, 'init': 'glorot_uniform', 'optimizer': 'rmsprop'}
0.725260(0.047343) with: {'batch_size': 5, 'epochs': 200, 'init': 'glorot_uniform', 'optimizer': 'adam'}
0.727865(0.012890) with: {'batch_size': 5, 'epochs': 200, 'init': 'normal', 'optimizer': 'rmsprop'}
0.731771(0.021236) with: {'batch_size': 5, 'epochs': 200, 'init': 'normal', 'optimizer': 'adam'}
0.753906(0.019918) with: {'batch_size': 5, 'epochs': 200, 'init': 'uniform', 'optimizer': 'rmsprop'}
0.744792(0.011201) with: {'batch_size': 5, 'epochs': 200, 'init': 'uniform', 'optimizer': 'adam'}
0.679688(0.013902) with: {'batch_size': 10, 'epochs': 50, 'init': 'glorot_uniform', 'optimizer': 'rmsprop'}
0.657552(0.028587) with: {'batch_size': 10, 'epochs': 50, 'init': 'glorot_uniform', 'optimizer': 'adam'}
0.712240(0.020752) with: {'batch_size': 10, 'epochs': 50, 'init': 'normal', 'optimizer': 'rmsprop'}
0.704427(0.006639) with: {'batch_size': 10, 'epochs': 50, 'init': 'normal', 'optimizer': 'adam'}
0.703125(0.011049) with: {'batch_size': 10, 'epochs': 50, 'init': 'uniform', 'optimizer': 'rmsprop'}
0.682292(0.021710) with: {'batch_size': 10, 'epochs': 50, 'init': 'uniform', 'optimizer': 'adam'}
0.695312(0.000000) with: {'batch_size': 10, 'epochs': 100, 'init': 'glorot_uniform', 'optimizer': 'rmsprop'}
0.708333(0.006639) with: {'batch_size': 10, 'epochs': 100, 'init': 'glorot_uniform', 'optimizer': 'adam'}
0.709635(0.015073) with: {'batch_size': 10, 'epochs': 100, 'init': 'normal', 'optimizer': 'rmsprop'}
0.722656(0.011500) with: {'batch_size': 10, 'epochs': 100, 'init': 'normal', 'optimizer': 'adam'}
0.716146(0.022628) with: {'batch_size': 10, 'epochs': 100, 'init': 'uniform', 'optimizer': 'rmsprop'}
0.701823(0.044690) with: {'batch_size': 10, 'epochs': 100, 'init': 'uniform', 'optimizer': 'adam'}
0.692708(0.006639) with: {'batch_size': 10, 'epochs': 150, 'init': 'glorot_uniform', 'optimizer': 'rmsprop'}
0.703125(0.017758) with: {'batch_size': 10, 'epochs': 150, 'init': 'glorot_uniform', 'optimizer': 'adam'}
0.713542(0.012890) with: {'batch_size': 10, 'epochs': 150, 'init': 'normal', 'optimizer': 'rmsprop'}
0.744792(0.023939) with: {'batch_size': 10, 'epochs': 150, 'init': 'normal', 'optimizer': 'adam'}
0.740885(0.030978) with: {'batch_size': 10, 'epochs': 150, 'init': 'uniform', 'optimizer': 'rmsprop'}
0.721354(0.010253) with: {'batch_size': 10, 'epochs': 150, 'init': 'uniform', 'optimizer': 'adam'}
0.717448(0.015733) with: {'batch_size': 10, 'epochs': 200, 'init': 'glorot_uniform', 'optimizer': 'rmsprop'}
0.684896(0.022628) with: {'batch_size': 10, 'epochs': 200, 'init': 'glorot_uniform', 'optimizer': 'adam'}
0.736979(0.033502) with: {'batch_size': 10, 'epochs': 200, 'init': 'normal', 'optimizer': 'rmsprop'}
0.742188(0.024080) with: {'batch_size': 10, 'epochs': 200, 'init': 'normal', 'optimizer': 'adam'}
0.736979(0.006639) with: {'batch_size': 10, 'epochs': 200, 'init': 'uniform', 'optimizer': 'rmsprop'}
0.742188(0.019401) with: {'batch_size': 10, 'epochs': 200, 'init': 'uniform', 'optimizer': 'adam'}
0.660156(0.011500) with: {'batch_size': 20, 'epochs': 50, 'init': 'glorot_uniform', 'optimizer': 'rmsprop'}
0.673177(0.001841) with: {'batch_size': 20, 'epochs': 50, 'init': 'glorot_uniform', 'optimizer': 'adam'}
0.678385(0.008027) with: {'batch_size': 20, 'epochs': 50, 'init': 'normal', 'optimizer': 'rmsprop'}
0.670573(0.041504) with: {'batch_size': 20, 'epochs': 50, 'init': 'normal', 'optimizer': 'adam'}
0.691406(0.011049) with: {'batch_size': 20, 'epochs': 50, 'init': 'uniform', 'optimizer': 'rmsprop'}
0.692708(0.009207) with: {'batch_size': 20, 'epochs': 50, 'init': 'uniform', 'optimizer': 'adam'}
0.680990(0.027126) with: {'batch_size': 20, 'epochs': 100, 'init': 'glorot_uniform', 'optimizer': 'rmsprop'}
0.673177(0.028940) with: {'batch_size': 20, 'epochs': 100, 'init': 'glorot_uniform', 'optimizer': 'adam'}
0.690104(0.018688) with: {'batch_size': 20, 'epochs': 100, 'init': 'normal', 'optimizer': 'rmsprop'}
0.708333(0.017566) with: {'batch_size': 20, 'epochs': 100, 'init': 'normal', 'optimizer': 'adam'}
0.717448(0.009744) with: {'batch_size': 20, 'epochs': 100, 'init': 'uniform', 'optimizer': 'rmsprop'}
0.726562(0.038670) with: {'batch_size': 20, 'epochs': 100, 'init': 'uniform', 'optimizer': 'adam'}
0.688802(0.023939) with: {'batch_size': 20, 'epochs': 150, 'init': 'glorot_uniform', 'optimizer': 'rmsprop'}
0.699219(0.013902) with: {'batch_size': 20, 'epochs': 150, 'init': 'glorot_uniform', 'optimizer': 'adam'}
0.704427(0.042353) with: {'batch_size': 20, 'epochs': 150, 'init': 'normal', 'optimizer': 'rmsprop'}
0.721354(0.016367) with: {'batch_size': 20, 'epochs': 150, 'init': 'normal', 'optimizer': 'adam'}
0.729167(0.013279) with: {'batch_size': 20, 'epochs': 150, 'init': 'uniform', 'optimizer': 'rmsprop'}
0.752604(0.030647) with: {'batch_size': 20, 'epochs': 150, 'init': 'uniform', 'optimizer': 'adam'}
0.683594(0.020915) with: {'batch_size': 20, 'epochs': 200, 'init': 'glorot_uniform', 'optimizer': 'rmsprop'}
0.682292(0.025582) with: {'batch_size': 20, 'epochs': 200, 'init': 'glorot_uniform', 'optimizer': 'adam'}
0.735677(0.029635) with: {'batch_size': 20, 'epochs': 200, 'init': 'normal', 'optimizer': 'rmsprop'}
0.705729(0.032578) with: {'batch_size': 20, 'epochs': 200, 'init': 'normal', 'optimizer': 'adam'}
0.729167(0.029463) with: {'batch_size': 20, 'epochs': 200, 'init': 'uniform', 'optimizer': 'rmsprop'}
0.740885(0.017566) with: {'batch_size': 20, 'epochs': 200, 'init': 'uniform', 'optimizer': 'adam'}
程序运行时间为:3687 
  • 1
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值