Machine Learning 17 模型优化--集成算法
Posted yuzaihuan
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Machine Learning 17 模型优化--集成算法相关的知识,希望对你有一定的参考价值。
有时提升一个模型的准确度很困难,尝试所有曾学习过的策略和算法,但模型的正确率并没有改善。
前面介绍的算法中,每种算法都有不同的适用范围,可以把多种机器学习算法组合在一起,这时提高算法准确度的有效方法之一。
接下来介绍如何通过scikit-learn来实现集成算法,包括:
- 装袋(Bagging)算法:先将训练集分离成多个子集,然后通过各个子集训练多个模型
- 提升(Boosting)算法:训练多个模型并组成一个序列,序列中的每一个模型都会修正前一个模型的错误
- 投票(Voting)算法:训练多个模型,并采用样本统计来提高模型的准确度
在这里只介绍相关算法,采用Pima Indians数据集,并用10折交叉验证来分离数据,再通过相应的评估矩阵来评估算法模型。
装袋算法
是一种提高分类准确性的算法,通过给定组合投票的方式获得最优。
如人生病了,去n个医院看了n个医生,每个医生都给你开了药房,最后哪个药方出现的次数最多,就说明这个药方越有可能是最优解。这也是袋装算法的思想。
下面介绍三种袋装模型:
- 装袋决策树(Bagged Decision Trees)
- 随机森林(Random Forest)
- 极端随机树(Extra Trees)
1 装袋决策树
在数据有很大的方差时非常有效。
下面在scikit-learn中通过BaggingClassifier实现分类与回归树算法,本例中实现了100棵决策树
1 #装袋决策树 2 from pandas import read_csv 3 from sklearn.model_selection import KFold 4 5 from sklearn.model_selection import cross_val_score 6 from sklearn.ensemble import BaggingClassifier 7 from sklearn.tree import DecisionTreeClassifier 8 9 10 filename=‘/home/aistudio/work/pima_data1.csv‘ 11 names=[‘preg‘,‘plas‘,‘pres‘,‘skin‘,‘test‘,‘mass‘,‘pedi‘,‘age‘,‘class‘] 12 data=read_csv(filename,names=names) 13 #将数据分为输入数据和输出数据 14 array=data.values 15 x=array[:,0:8] 16 y=array[:,8] 17 num_folds=10 18 seed=7 19 kfold=KFold(n_splits=num_folds,random_state=seed) 20 21 cart=DecisionTreeClassifier() 22 num_tree=100 23 model=BaggingClassifier(base_estimator=cart,n_estimators=num_tree,random_state=seed) 24 25 result=cross_val_score(model,x,y,cv=kfold) #10折交叉验证 26 print(result.mean()) #打印正确率
0.770745044429255
这个结果与上一次的分类与回归树的结果(0.7004272043745728,13节,审查分类算法)比较,发现结果有了很大的提升。
2 随机森林
用随机的方式建立一个森林,森林有很多决策树,而且每一棵决策树之间是没有来联系的。得到森林之后,当有一个新的样本进入的时候,就让森林中的每一棵决策树分别进行判断,看看这个样本应该属于哪一类,再看看哪一类被选择最多,就预测这个样本为哪一类。
在建立每一棵决策树的过程中,有两点要注意:采样与完全分裂。首先是两个随机采样的过程,随机森林对输入的数据要进行行,列采样。对行采样采用有放回的方式,也就是在采样得到的样本集合中可能有重复的样本。假设输入样本为N个,也就是在采样得到的样本集合中可能有重复的样本。假设输入
的样本为N个,那么采样样本也为N个。这样在训练的时候,每棵树的输入样本都不是全部的样本,就相对不容易出现过拟合。
然后进行列采样,从M个feature中选出m个(m<<M)。之后再对采样之后的数据使用完全分裂的方式建立决策树,这样决策树的某一个叶子节点要么无法继续分裂,要么所有样本都指向同一个分类。
一般很多决策树算法有一个重要的步骤--剪枝,但这里不这样做,因为之前的两个随机采样过程保证了随机性,所以不剪枝也不会出现过拟合。
这中算法得到的随机森林中的每一棵决策树都是很弱的,但是将他们组合起来就会很厉害。可以这样比喻:每一棵决策树就是一个精通某一个领域的专家,这样在随机森林中就有了很多不同领域的专家,对于一个新的问题(新的数据输入),可以从不同的角度去看待,最终由各个专家投票得到结果。
这种算法在scikit-learn中实现的类是RandomForestClassifier。
1 #随机森林 2 from pandas import read_csv 3 from sklearn.model_selection import KFold 4 5 from sklearn.model_selection import cross_val_score 6 from sklearn.ensemble import RandomForestClassifier 7 8 9 filename=‘/home/aistudio/work/pima_data1.csv‘ 10 names=[‘preg‘,‘plas‘,‘pres‘,‘skin‘,‘test‘,‘mass‘,‘pedi‘,‘age‘,‘class‘] 11 data=read_csv(filename,names=names) 12 #将数据分为输入数据和输出数据 13 array=data.values 14 x=array[:,0:8] 15 y=array[:,8] 16 num_folds=10 17 seed=7 18 kfold=KFold(n_splits=num_folds,random_state=seed) 19 20 cart=DecisionTreeClassifier() 21 num_tree=100 #实现100棵随机森林 22 max_feature=3 23 model=RandomForestClassifier(n_estimators=num_tree,random_state=seed, max_features=max_feature) 24 25 result=cross_val_score(model,x,y,cv=kfold) #10折交叉验证 26 print(result.mean()) #打印正确率
0.7733766233766234
极端随机树
与随机森林相似,但有两个主要的区别:
- 随机森林应用的是Bagging模型,而极端随机树是使用所有的训练样本得到每棵决策树,也就是的每棵决策树应用的是相同的全部训练样本(一个是部分样本,一个全部)
- 随机森林是在一个随机子集内得到最优分叉特征属性,而极端随机树是完全随机的选择分叉特征属性,从而实现对决策树进行分叉(一个最优,一个随机)
在scikit-learn中实现的类是ExtraTreesClassifier。下面的实例是实现100棵树和7个随机特征的极端随机树。
1 #极端随机树 2 from pandas import read_csv 3 from sklearn.model_selection import KFold 4 5 from sklearn.model_selection import cross_val_score 6 from sklearn.ensemble import ExtraTreesClassifier 7 8 9 filename=‘/home/aistudio/work/pima_data1.csv‘ 10 names=[‘preg‘,‘plas‘,‘pres‘,‘skin‘,‘test‘,‘mass‘,‘pedi‘,‘age‘,‘class‘] 11 data=read_csv(filename,names=names) 12 #将数据分为输入数据和输出数据 13 array=data.values 14 x=array[:,0:8] 15 y=array[:,8] 16 num_folds=10 17 seed=7 18 kfold=KFold(n_splits=num_folds,random_state=seed) 19 20 num_tree=100 #实现100棵随机森林 21 max_features=7 22 model=ExtraTreesClassifier(n_estimators=num_tree,random_state=seed, max_features=max_features) 23 24 result=cross_val_score(model,x,y,cv=kfold) #10折交叉验证 25 print(result.mean()) #打印正确率
0.762987012987013
提升算法
提升算法是一种用来提高弱分类算法准确度的方法,这种方法先构造一个预测函数系列,然后以一定的方式将它们组合成一个预测函数。
提升算法也是一种提高任意给定学习算法准确度的方法,是一种集成算法,通过对样本集的操作获得样本子集,之后用弱分类算法在样本子集上训练生成一系列基分类器。
提升算法将这n个基分类器进行加权融合,产生最后的结果分类器。
在这n个基分类器中,每个分类器的识别率不一定很高,但他们联合后的结果有很高的识别率。
下面是两个非常常见的用于机器学习的提升算法:
- AdaBoost
- 随机梯度提升(Stochastic Gradient Boosting)
AdaBoost
是一种迭代算法,针对同一个训练机训练不同的弱分类器,然后把这些弱分类器集合起来,构成一个最强的最终分类器。
其算法本身是通过改变数据分布来实现的,它根据每次训练集中每个样本的分类是否正确,以及上次总体分类的准确率,来确定每个样本的权值。
它将修改过权值的新数据集送给下层分类器进行训练,再将每次训练得到的分类器融合起来,作为最后的决策分类器。
使用Adaboost分类器可以排除一些不必要的训练数据特征,并放在关键的训练数据上面。
在scikit-learn中实现的类是AdaBoostClassifier。
1 #AdBoost 2 from pandas import read_csv 3 from sklearn.model_selection import KFold 4 5 from sklearn.model_selection import cross_val_score 6 from sklearn.ensemble import AdaBoostClassifier 7 8 9 filename=‘/home/aistudio/work/pima_data1.csv‘ 10 names=[‘preg‘,‘plas‘,‘pres‘,‘skin‘,‘test‘,‘mass‘,‘pedi‘,‘age‘,‘class‘] 11 data=read_csv(filename,names=names) 12 #将数据分为输入数据和输出数据 13 array=data.values 14 x=array[:,0:8] 15 y=array[:,8] 16 num_folds=10 17 seed=7 18 kfold=KFold(n_splits=num_folds,random_state=seed) 19 20 num_tree=30 #实现30棵随机森林 21 model=AdaBoostClassifier(n_estimators=num_tree,random_state=seed) 22 23 result=cross_val_score(model,x,y,cv=kfold) #10折交叉验证 24 print(result.mean()) #打印正确率
0.760457963089542
随机梯度提升
随机梯度提升发(GBM)基本思想:要找到函数的最大值,最好的办法就是沿着该函数的梯度方向。梯度算子总是指向函数值增长最快的方向。
由于梯度提升算法在每次更新数据集时都要遍历整个数据集,计算复杂度较高,于是有了一个改进算法----随机梯度提升算法:该算法一次只用一个样本点来更新回归系数,极大的改善了算法的计算复杂度。
在scikit-learn中实现的类是GradientBoostingCalssifier。
1 #随机梯度提升 2 from pandas import read_csv 3 from sklearn.model_selection import KFold 4 5 from sklearn.model_selection import cross_val_score 6 from sklearn.ensemble import GradientBoostingClassifier 7 8 9 filename=‘/home/aistudio/work/pima_data1.csv‘ 10 names=[‘preg‘,‘plas‘,‘pres‘,‘skin‘,‘test‘,‘mass‘,‘pedi‘,‘age‘,‘class‘] 11 data=read_csv(filename,names=names) 12 #将数据分为输入数据和输出数据 13 array=data.values 14 x=array[:,0:8] 15 y=array[:,8] 16 num_folds=10 17 seed=7 18 kfold=KFold(n_splits=num_folds,random_state=seed) 19 20 num_tree=100 #实现30棵随机森林 21 model=GradientBoostingClassifier(n_estimators=num_tree,random_state=seed) 22 23 result=cross_val_score(model,x,y,cv=kfold) #10折交叉验证 24 print(result.mean()) #打印正确率
0.7669002050580999
投票算法
投票算法(Voting)是一个非常简单的多个机器学习的集成算法。通过创建两个或多个算法模型,利用投票算法将这些算法包装起来,计算各个子模型的平均预测状况。
在实际应用中,可以对每个子模型的预测结果增加权重,以提高算法的准确度。
在scikit-learn中不提供加权算法。
在scikit-learn中实现类是VotingClassifier。
1 #投票算法 2 from pandas import read_csv 3 from sklearn.model_selection import KFold 4 5 from sklearn.model_selection import cross_val_score 6 from sklearn.ensemble import VotingClassifier 7 from sklearn.tree import DecisionTreeClassifier 8 from sklearn.svm import SVC 9 from sklearn.linear_model import LogisticRegression 10 11 filename=‘/home/aistudio/work/pima_data1.csv‘ 12 names=[‘preg‘,‘plas‘,‘pres‘,‘skin‘,‘test‘,‘mass‘,‘pedi‘,‘age‘,‘class‘] 13 data=read_csv(filename,names=names) 14 #将数据分为输入数据和输出数据 15 array=data.values 16 x=array[:,0:8] 17 y=array[:,8] 18 num_folds=10 19 seed=7 20 kfold=KFold(n_splits=num_folds,random_state=seed) 21 cart=DecisionTreeClassifier() 22 23 models=[] 24 model_logistic=LogisticRegression() 25 models.append((‘logistic‘,model_logistic)) 26 model_cart=DecisionTreeClassifier() 27 models.append((‘cart‘,model_cart)) 28 model_svc=SVC() 29 models.append((‘svc‘,model_svc)) 30 31 ensemble_model=VotingClassifier(estimators=models) 32 33 result=cross_val_score(ensemble_model,x,y,cv=kfold) #10折交叉验证 34 print(result.mean()) #打印正确率
0.7394907723855092
以上是关于Machine Learning 17 模型优化--集成算法的主要内容,如果未能解决你的问题,请参考以下文章
Coursera在线学习---第十节.大规模机器学习(Large Scale Machine Learning)
Machine learning for improved image-based wavefront sensing
Optimization and Machine Learning(优化与机器学习)
Ng第十七课:大规模机器学习(Large Scale Machine Learning)