堆叠式神经网络模型及GUI可视化应用
收藏


Illustrations by Stas Yurev


作者:沂水寒城,CSDN博客专家,个人研究方向:机器学习、深度学习、NLP、CV

Blog: http://yishuihancheng.blog.csdn.net

由于工作和学习的缘故,陆陆续续接触到机器学习、深度学习相关的知识已经有好几年的时间了,从单一的元模型到复杂的模型再到集成学习模型,不同的学习任务类型所需要的模型也是不尽相同的。今天主要是介绍一种集成学习思想和深度学习相结合的应用实例,也是我在实际项目中实际搭建使用到的一种模型——堆叠式神经网络模型。

本文主要包括:集成学习简介、堆叠式神经网络模型实现、GUI可视化应用几个部分。

一、集成学习简介

集成学习的主要思想是利用一定的手段学习出多个分类器,而且这多个分类器要求是弱分类器,然后将多个分类器进行组合共同预测。核心思想就是如何训练处多个弱分类器以及如何将这些弱分类器进行组合。一般采用弱分类器的原因在于将误差进行均衡,因为一旦某个分类器太强了就会造成后面的结果受其影响太大,严重的会导致后面的分类器无法进行分类。常用的弱分类器可以采用误差率小于0.5的,比如说逻辑回归、SVM、神经网络。可以采用随机选取数据进行分类器的训练,也可以采用不断的调整错误分类的训练数据的权重生成新的分类器。集成学习原理示意图如下图所示:

集成学习是机器学习中一个非常重要且热门的分支,是用多个弱分类器构成一个强分类器,其哲学思想是“三个臭皮匠赛过诸葛亮”。一般的弱分类器可以由决策树,神经网络,贝叶斯分类器,K-近邻等构成。常见的集成学习策略主要包括:Bagging、Boosting、Stacking和Blending,对于初学者来说前两种思想或者是框架可能是会比较耳熟能详的,而后两种如果没有接触到的话可能会觉得比较陌生,我也是读了研究生以后才接触到Stacking和Blending的,思想还是比较好理解的,效果也是蛮不错的,这里简单温习一下这三种集成学习策略。

1、Bagging

Bagging的个体弱学习器的训练集是通过随机采样得到的。通过T次有放回的随机采样,我们就可以得到T个采样集,对于这T个采样集,我们可以分别独立的训练出T个弱学习器,再对这T个弱学习器通过集合策略来得到最终的强学习器。随机森林是Bagging的一个特化进阶版,所谓的特化是因为随机森林的弱学习器都是决策树。所谓的进阶是随机森林在Bagging的样本随机采样基础上,又加上了特征的随机选择,其基本思想没有脱离Bagging的范畴。Bagging原理示意图如下所示:

2、Boosting

Boosting算法的工作机制是首先从训练集用初始权重训练出一个弱学习器1,根据弱学习的学习误差率表现来更新训练样本的权重,使得之前弱学习器1学习误差率高的训练样本点的权重变高,使得这些误差率高的样本在后面的弱学习器2中得到更多的重视。然后基于调整权重后的训练集来训练弱学习器2.,如此重复进行,直到弱学习器数达到事先指定的数目T,最终将这T个弱学习器通过集合策略进行整合,得到最终的强学习器。Boosting系列算法里最著名算法主要有AdaBoost算法和GBDT提升树(boosting tree)系列算法。原理示意图如下所示:

3、Stacking

Stacking也是一种模型融合的方法。首先,直接用所有的训练数据对第一层多个模型进行k折交叉验证,这样每个模型在训练集上都有一个预测值,然后将这些预测值做为新特征对第二层的模型进行训练,stacking两层模型都使用了全部的训练数据。Stacking模型是指将多种分类器组合在一起来取得更好表现的一种集成学习模型。一般情况下,Stacking模型分为两层。第一层中我们训练多个不同的基础模型,然后再以第一层训练的各个模型的输出作为输入来训练第二层的模型,以得到一个最终的输出。

Stacking原理示意图如下图所示:

4、Blending

Blending设计思想与Stacking类似,对于一般的Blending,主要思路是把原始的训练集先分成两部分,比如70%的数据作为新的训练集,剩下30%的数据作为测试集。第一层我们在这70%的数据上训练多个模型,然后去预测那30%数据的label。在第二层里,我们就直接用这30%数据在第一层预测的结果做为新特征继续训练即可。从这里我们可以看到Stacking和Blending模型在构建过程中最明显的差别就是Stacking的两层训练都是用的全部数据,而Blending是使用的部分数据。

二、堆叠式神经网络模型实现

在我们以往的实验中,Stacking策略大都出现在了机器学习的任务里面,因为我们借助于一些集成学习思想可以有效地提升基分类器的性能,这也是我们希望看到的结果。

在深度学习里面,能否将Stacking应用到模型中呢?答案是可以的,在之前的预测系统中,我曾尝试基于Stacking和Keras实现了堆叠式的神经网络模型,取得了不错的预测效果,今天就来简单介绍一下这个模型。

这里我们先来看一个由3个基神经网络模型构成的网络模型结构图:

这个结构图还是很能直观说明问题的,这是一种典型的集成学习策略,只不过这里的基分类器不再是弱分类器,而变成了神经网络模型了。

模型具体实现代码如下:

1.def stackingNN(ns=1000,nf=4,nc=4,num=5,ratio=0.3,epochs=500,flag='classify',  
2.               saveDir='models/',model_path='model_graph.png'):  
3.    ''''' 
4.    集成神经网络模型 
5.    '''  
6.    if flag=='classify':  
7.        X,y=make_classification(n_samples=ns,n_features=nf,n_redundant=0,  
8.                                n_classes=nc,n_informative=2,random_state=22,  
9.                                n_clusters_per_class=1,scale=100)  
10.    else:  
11.        X,y=make_blobs(n_samples=ns,centers=nc,n_features=nf)  
12.    y=to_categorical(y)  
13.    trainX,testX,trainy,testy=train_test_split(X,y,test_size=ratio,random_state=42)  
14.    generateBaseNN(X,y,num=num,ratio=ratio,epochs=epochs,saveDir=saveDir)  
15.    models=load_all_models(num,saveDir)  
16.    stackedModel=define_stacked_model(models,classes=nc,model_path=model_path)  
17.    stackedModel=fit_stacked_model(stackedModel,trainX,trainy,epochs=epochs)  
18.    yhat=predict_stacked_model(stackedModel,testX)  
19.    yhat=argmax(yhat,axis=1)  
20.    y_true=backOneHotLabel(testy.tolist())  
21.    y_pre=yhat.tolist()  
22.    acc=calAccuracyScore(y_true,y_pre)  
23.    print('StackingKerasModel Accuracy: %.3f' % acc)  

其中:

ns:表示样本数量
nf:表示样本特征维数
nc:表示类别数量
num:表示基神经网络模型数量
ratio:表示测试数据占比
epochs:模型训练的迭代次数
flag:任务类型【分类/聚类】
saveDir:基训练模型保存路径
model_path:堆叠式神经网络模型的结构图
接下来重点看一下模型中关键节点的代码实现:

1、基模型生成代码实现如下:

1.def generateBaseNN(X,y,num=5,ratio=0.3,epochs=500,saveDir='models/'):  
2.    ''''' 
3.    生成基分类器神经网络模型 
4.    '''
  
5.    if not os.path.exists(saveDir):  
6.        os.makedirs(saveDir)  
7.    for i in range(num):  
8.        X_train,X_test,y_train,y_test=train_test_split(X,y,  
9.                                      test_size=ratio,random_state=42)  
10.        classes=len(y_train[0])  
11.        model=fit_model(X_train,y_train,classes=classes,epochs=epochs)  
12.        filename=saveDir+'/model_'+str(i+1)+'.h5'  
13.        model.save(filename)  
2、单个基模型训练拟合代码实现如下:
1.def fit_model(trainX,trainy,classes=3,epochs=500):  
2.    ''''' 
3.    模型训练拟合 
4.    '''
  
5.    model=Sequential()  
6.    col=trainX.shape[1]  
7.    model.add(Dense(512,input_dim=col,activation='relu'))  
8.    model.add(Dense(classes,activation='softmax'))  
9.    model.compile(loss='categorical_crossentropy',optimizer='adam',  
10.                  metrics=['accuracy'])  
11.    model.fit(trainX,trainy,epochs=epochs,verbose=0)  
12.    return model  
3、模型堆叠式结构实现代码如下:
1.def define_stacked_model(models,classes=3,model_path='model_graph.png'):  
2.    ''''' 
3.    定义堆叠式模型结构 
4.    '''
  
5.    for i in range(len(models)):  
6.        model=models[i]  
7.        for layer in model.layers:  
8.            layer.trainable=False  
9.            layer.name='ensemble_'+str(i+1)+'_'+layer.name  
10.    ensemble_visible=[model.input for model in models]  #输入层  
11.    ensemble_outputs=[model.output for model in models]  #输出层  
12.    merge=concatenate(ensemble_outputs)  
13.    hidden=Dense(512,activation='relu')(merge)  
14.    output=Dense(classes,activation='softmax')(hidden)  
15.    model=Model(inputs=ensemble_visible,outputs=output)  
16.    plot_model(model,show_shapes=True,to_file=model_path)  #m模型结构可视化  
17.    model.compile(loss='categorical_crossentropy',optimizer='adam',  
18.                  metrics=['accuracy'])  
19.    return model  
4、堆叠式模型训练预测代码实现如下:
1.def fit_stacked_model(model,dataX,datay,epochs=300):  
2.    ''''' 
3.    拟合堆叠式模型 
4.    '''
  
5.    X=[dataX for _ in range(len(model.input))]  
6.    model.fit(X,datay,epochs=epochs,verbose=0)  
7.    return model  
8.   
9.  
10.def predict_stacked_model(model,dataX):  
11.    ''''' 
12.    堆叠式模型预测 
13.    '''
  
14.    X=[dataX for _ in range(len(model.input))]  
15.    return model.predict(X,verbose=0)  

整体的实现上没有太难的地方,需要注意的就是单个模型训练拟合和整体模型融合的时候是有差别的。只要理解这里的创建思想就没有什么问题了。

三、GUI可视化应用

到此,就进入到我们本文的最后一部分内容了,GUI可视化应用,也就是将整个模型的搭建、训练、预测等完整流程以界面的形式展现出来。毕竟命令行的启动形式看起来并不是那么地直观,所以这里做了一个简单的界面应用。

这里具体的代码实现如下所示:

1.def stackingNNDemo():  
2.    ''''' 
3.    堆叠式神经网络模型GUI应用 
4.    '''
  
5.    my_cool_parser=Parser(description=u'堆叠式神经网络模型GUI应用')  
6.    my_cool_parser.add_argument(  
7.        "ns",metavar=u'输入样本数据集数量:',  
8.        help="0-INF",default='2000')  
9.    my_cool_parser.add_argument(  
10.        "nf",metavar=u'输入样本数据特征维数:',  
11.        help="0-INF",default='5')  
12.    my_cool_parser.add_argument(  
13.        "nc",metavar=u'输入样本数据集类别数量:',  
14.        help="0-INF",default='3')  
15.    my_cool_parser.add_argument(  
16.        "num",metavar=u'输入基神经网络模型数量:',  
17.        help="0-INF",default='5')  
18.    my_cool_parser.add_argument(  
19.        "ratio",metavar=u'测试集数据占比:',  
20.        help="0.2-0.4",default='0.3')  
21.    my_cool_parser.add_argument(  
22.        "epochs",metavar=u'输入神经网络模型迭代次数:',  
23.        help="0-INF",default='10')  
24.    my_cool_parser.add_argument(  
25.        "flag",metavar=u'输入数据集类型:',  
26.        help="classify|cluster",choices=['classify','cluster'],default='classify')  
27.    my_cool_parser.add_argument(  
28.        "path",metavar=u'输入存储路径:',  
29.        choices=['baseModel/','result/'],default='result/')  
30.    my_cool_parser.add_argument(  
31.        "pic",metavar=u'输入模型结果图路径:',  
32.        choices=['stackedModel.png','structure.png'],default='structure.png')  
33.    args=my_cool_parser.parse_args()  
34.    ns=int(args.ns)  
35.    nf=int(args.nf)  
36.    nc=int(args.nc)  
37.    num=int(args.num)  
38.    ratio=float(args.ratio)  
39.    epochs=int(args.epochs)  
40.    flag=args.flag  
41.    saveDir=args.path  
42.    model_path=args.pic  
43.    stackingNN(ns=ns,nf=nf,nc=nc,num=num,ratio=ratio,epochs=epochs,  
44.               flag=flag,saveDir=saveDir,model_path=model_path)  
45.    print('Finished!!!')  

完整项目结构如下:

这里,我们没有使用自己的数据集,数据来源于sklearn的随机生成模块,如果需要使用自己的数据集可以写一个简单的数据集加载函数就可以了。stackingNNDemo模块负责模型的搭建,GUI模块负责界面的编写,start.bat是windows下可执行的脚本,双击即可启动,效果如下图所示:

这里我们直接使用默认参数,点击start按钮,执行界面如下图所示:

执行结束界面如下图所示:

从上图的结果输出中,我们看到模型测试结果达到了91.8%的准确度,我们使用到的数据只有2000条,还是不错的结果。

我们实验中使用到了5个基础模型,下面是生成的基神经网络模型的详细信息:

整体的模型结构如下图所示:

到这里,今天的内容差不多就结束了,个人水平有限,可能讲解的过程中会有错误,欢迎交流指导。本文从简单的原理介绍开始到代码实现,个人觉得还是很详细的一份实现说明了,感兴趣的话可以亲自实践一下。

赞 赏 作 者



Python中文社区作为一个去中心化的全球技术社区,以成为全球20万Python中文开发者的精神部落为愿景,目前覆盖各大主流媒体和协作平台,与阿里、腾讯、百度、微软、亚马逊、开源中国、CSDN等业界知名公司和技术社区建立了广泛的联系,拥有来自十多个国家和地区数万名登记会员,会员来自以工信部、清华大学、北京大学、北京邮电大学、中国人民银行、中科院、中金、华为、BAT、谷歌、微软等为代表的政府机关、科研单位、金融机构以及海内外知名公司,全平台近20万开发者关注。


▼ 点击成为社区注册会员          「在看」一下,一起PY!

官方公众号