机器学习实验二-集成学习

数据集

本实验采用的数据集是 WEBSPAM-UK2006 数据集, 数据集中包含1803个垃圾网站,4411个正常网站,每个网站有96个内容特征,有138个超链接标签。这138个超链接标签可以被分为五类:Degree-related features, PageRank-related features, TrustRank-related features, Truncated PageRank-related features, Supporter-related features

在本实验中,需要将数据集划分为4:1的训练集和测试集

实验任务

  • 比较由不同的基本分类器组成的不同的集成学习算法的性能
  • 至少需要包含Bagging 算法和 AdaBoost.M1算法
  • 至少需要使用SVM和Decision Tree两种基本分类器算法
  • 至少需要完成的算法组合为:Bagging + DTree, Bagging + SVM, AdaBoost.M1 + DTree, AdaBoost.M1 + SVM.

扩展任务

  • 尝试其他的基本分类器(K-NN, Naive Bayes…)
  • 分析不同的特征的影响(比如可以只使用内容特征,或者只使用链接特征,或者进行特征组合)
  • 考虑特征缩放(归一化)来提高性能
  • 数据集是不平衡的,如何克服

实验设计

基础分类器选取了SVM,Dtree, 和KNN

基础分类器采用了sklearn的包,由于KNN算法无法设置训练样本的权中,因此进行了如下组合:

  • Bagging + DTree
  • Bagging + SVM
  • Bagging + KNN
  • AdaBoost.M1 + DTree
  • AdaBoost.M1 + SVM.

实验结果

针对Bagging和AdaBoost.M1集成学习算法 分别使用SVM,Dtree,KNN等基本分类器进行组合后,并且设置了不同的训练集大小,迭代次数(分类器个数),测试后的总体结果如下:

集成算法基础算法迭代次数训练集大小准确率
BaggingSVM19940.886565
BaggingDecision Tree19940.824618
BaggingKNN19940.849558
AdaBoost.M1SVM19940.884956
AdaBoost.M1Decision Tree19940.847949
BaggingSVM219940.881738
BaggingDecision Tree219940.913113
BaggingKNN219940.881738
AdaBoost.M1SVM219940.862430
AdaBoost.M1Decision Tree219940.881738
BaggingSVM419940.913113
BaggingDecision Tree419940.900241
BaggingKNN419940.884151
AdaBoost.M1SVM419940.896219
AdaBoost.M1Decision Tree419940.901046
BaggingSVM2119880.895414
BaggingDecision Tree2119880.902655
BaggingKNN2119880.885760
AdaBoost.M1SVM2119880.873693
AdaBoost.M1Decision Tree2119880.881738
BaggingSVM2139760.895414
BaggingDecision Tree2139760.901046
BaggingKNN2139760.897828
AdaBoost.M1SVM2139760.901850
AdaBoost.M1Decision Tree2139760.901046

由上表可以得出结论:对于本数据集,Bagging算法和AdaBoost算法的算法性能大致相同,组合基础算法时,KNN+性能最差,Dtree+性能最好,不过在迭代次数较少时SVM的性能较好,迭代次数增加、训练集增加时Dtree+的准确率上升较快

分析和讨论

数据预处理问题

在不对数据进行归一化处理的时候,SVM的Bagging算法表现极差,只能达到

对于SVM,Dtree, KNN三个基础分类器,进行特征归一化与否的分类效果如下所示:

是否归一化分类器准确率
SVM0.735318
DTree0.875302
KNN0.781979
SVM0.914722
DTree0.876106
KNN0.899437

可以得出结论:归一化操作对SVM,KNN等算法而言及其重要,这是因为这类分类器是利用两点间的距离计算两点间的差异,当各个特征的维度差异较大时对其分类效果影响较大,因此需要进行归一化,而这些也直接影响了集成学习算法的准确率,如下表所示

不进行归一化处理

集成算法基础算法迭代次数训练集大小准确率
BaggingSVM219940.714401
BaggingDecision Tree219940.896219
BaggingKNN219940.764280
AdaBoost.M1Decision Tree219940.894610

(不归一化处理时,SVM在训练集上做测试时几乎会是完全正确,即出现了过拟合,这时AdaBoost算法无法进行下去,故无数据)

进行归一化处理

集成算法基础算法迭代次数训练集大小准确率
BaggingSVM219940.905873
BaggingDecision Tree219940.907482
BaggingKNN219940.893001
AdaBoost.M1SVM219940.872888
AdaBoost.M1Decision Tree219940.901046

可以发现,在不进行归一化处理时,对于基于SVM和KNN两种基本算法的Bagging和AdaBoost集成学习算法表现均较差,而进行了归一化处理之后,其算法准确率则大幅提高(注意,单个算法的准确率较高是因为训练时采用了全训练集,而集成学习的训练集只采用了20%的训练集,因此可能稍有偏差)而DTree的结果并无比较大的差异

由这个对比可以感受到特征归一化对部分分类器的重要性

SVM的参数设置

在实验过程中发现使用SVM算法 + AdaBoost.M1算法时会出现每轮迭代时会出现分类效果越来越差的情况,通过打印预测结果发现,其对训练集的预测会循环出现全0和全1,即这一轮迭代会将每一个测试数据分类为sapm,下一轮迭代时会将每一个测试数据分类为normal, 这样会导致最终的训练结果准确率为69%,反复调试发现是sklearn.svm.SVC参数设置问题

1
2
3
4
5
6
sklearn.svm.SVC(C=1.0, cache_size=200, class_weight=None, coef0=0.0,
decision_function_shape='ovr', degree=3, gamma='auto',
kernel='rbf',
max_iter=-1, probability=False, random_state=None,
shrinking=True,
tol=0.001, verbose=False)

SVC的参数C代表了其惩罚参数,相当于惩罚松弛变量,松弛变量接近0时,即对误分类的惩罚增大,趋向于对训练集全分对的情况,这样对训练集测试时准确率很高,但泛化能力弱。默认为1时,训练时加上了各样本参数时则会对其训练效果产生极大影响,最终导致分类错误率增加,将其设置为300之后则效果变好。

算法表现差异分析

将上述测试结果按照准确率进行排序结果如下:

集成算法基础算法迭代次数训练集大小准确率
BaggingDecision Tree19940.824618
AdaBoost.M1Decision Tree19940.847949
BaggingKNN19940.849558
AdaBoost.M1SVM219940.86243
AdaBoost.M1SVM2119880.873693
BaggingSVM219940.881738
BaggingKNN219940.881738
AdaBoost.M1Decision Tree219940.881738
AdaBoost.M1Decision Tree2119880.881738
BaggingKNN419940.884151
AdaBoost.M1SVM19940.884956
BaggingKNN2119880.88576
BaggingSVM19940.886565
BaggingSVM2119880.895414
BaggingSVM2139760.895414
AdaBoost.M1SVM419940.896219
BaggingKNN2139760.897828
BaggingDecision Tree419940.900241
AdaBoost.M1Decision Tree419940.901046
BaggingDecision Tree2139760.901046
AdaBoost.M1Decision Tree2139760.901046
AdaBoost.M1SVM2139760.90185
BaggingDecision Tree2119880.902655
BaggingDecision Tree219940.913113
BaggingSVM419940.913113

可以发现,综合表现最好的是Bagging + Dtree算法,平均来看,Bagging集成方法优于AdaBoost算法,这与经验相悖,分析可能的原因是:实验时未考虑各特征的权重问题,每个特征的计算方法不同,归一化时并没有考虑这一点,这些可能使得当AdaBoost算法专注于那些分错的样本时其实违背了数据的特征规律。

Bagging算法和AdaBoost算法有什么区别

Bagging

算法流程:

给定一个大小为n的训练集D,Bagging算法从中均匀、有放回地选出T个大小为n1的子集Di,作为新的训练集。在这m个训练集上使用分类、回归等算法,则可得到m个模型,再通过取平均值、取多数票等方法,即可得到Bagging的结果

算法特点:

Bagging要求基分类器的学习算法不稳定,也就是当数据发生小变化时,训练的分类器会产生很大不同,依次来增加基分类器的多样性,使得分类系统更加稳定,泛化能力更强。

AdaBoost

算法流程

AdaBoost方法是一种迭代算法,在每一轮中加入一个新的弱分类器,直到达到某个预定的足够小的错误率。
每一个训练样本都被赋予一个权重,表明它被某个分类器选入训练集的概率。
如果某个样本点已经被准确地分类,那么在构造下一个训练集中,它被选中的概率就被降低;
相反,如果某个样本点没有被准确地分类,那么它的权重就得到提高。
通过这样的方式,AdaBoost方法能“聚焦于”那些较难分(更富信息)的样本上。

在具体实现上,最初令每个样本的权重都相等,
对于第k次迭代操作,我们就根据这些权重来选取样本点,进而训练分类器Ck。
然后就根据这个分类器,来提高被它分错的的样本的权重,并降低被正确分类的样本权重。
然后,权重更新过的样本集被用于训练下一个分类器Ck[2]。整个训练过程如此迭代地进行下去。

算法特点

  • 具有较低的泛化误差(low generalization)
  • 不容易出现overfiting(过拟合)现象

算法差异

Bagging算法的训练集是从原数据集中有放回的抽样得到的(原数据集的一部分),每个基分类器是相互独立的,并列的。因为每个基分类器训练方法独立且相同,所以最后分类器等权重投票。

而在Boosting算法中,基分类器是依次训练的,因为分错的点在接下来的训练时会更加的被侧重,也就是说,每个基分类器的训练都是建立在之前基分类器的表现基础之上的。最后分类器加权投票。

通常来说,基分类器不稳定时,Bagging算法的表现会比较好,大多数情况下AdaBoost算法表现较好,但是也容易出现过拟合的情况,比如说本次实验中(【SVM的参数设置】一节所述),当基分类器为SVM时,若C参数设置为1时,则会出现最终分类准确率仅为69%的情况

什么样的组合最好,为什么

进行相应的参数调整之后,各个算法组合之间的差异并不是特别大,不过Bagging + Dtree的稳定性应该是最高的,其效果也最好,实际上Bagging + SVM的效果也比较好,此次测试SVM效果劣于Dtree可能是SVC的参数设置不够好

代码说明:

  • ContentNewLinkAllSample.csv : 原始数据
  • README.md : 说明文档
  • base_cls.py : 基础分类器的分类效果测试, python base_cls.py即可运行
  • ensemble.py : 集成学习算法
  • main.py : 测试程序
  • share.py : 一些配置函数

参考资料

  1. 曾刚,李宏.一个基于现实世界的大型Web参照数据集——UK2006 Datasets的初步研究[J].企业技术开发(学术版),2009,28(5):16-17,31.

  2. SVM: Weighted samples http://scikit-learn.org/stable/auto_examples/svm/plot_weighted_samples.html

打赏