0%

集成学习实验

实验目的

  1. 熟悉和掌握集成学习的基本原理
  2. 熟悉和掌握集成学习的并行策略,Bagging与随机森林解决复杂分类问题
  3. 熟悉和掌握集成学习的串行策略,Boosting与Adaboost解决复杂分类问题
  4. 了解和掌握第三方机器学习库Scikit-learn中的模型调用

实验要求

  1. 采用Python、Matlab等高级语言进行编程,推荐优先选用Python语言
  2. 本次实验可以直接调用Scikit-learn、PyTorch等成熟框架的第三方实现
  3. 代码可读性强:变量、函数、类等命名可读性强,包含必要的注释

实验原理

概念

集成学习(Ensemble learning)通过构建并结合多个学习器来完成学习任务,有时也被称为多分类器系统、基于委员会的学习等,集成学习通常可以获得比单一学习模型更好的泛化性。

基本结构

先产生多个“个体学习器”,也叫做“基学习器”,再用某种策略将它们结合起来,集成中只包含同种类型的个体学习器叫做同质,包含不同类型的个体学习器叫做异质。要获得好的集成就应该找到“好而不同”的个体学习器,这就是集成学习的研究核心。

Boosting

Boosting是一簇可将弱学习器提升为强学习器的算法。其工作机制为:
先从初始训练集训练出一个基学习器
再根据基学习器的表现对样本分布进行调整,使得先前的基学习器做错的训练样本在后续收到更多的关注
然后基于调整后的样本分布来训练下一个基学习器;如此重复进行,直至基学习器数目达到实现指定的值T,或整个集成结果达到退出条件
然后将这些学习器进行加权结合。

AdaBoost

AdaBoost是Boosting中的经典算法,其主要应用于二分类问题。
Adaboost 算法采用调整样本权重的方式来对样本分布进行调整,即提高前一轮个体学习器错误分类的样本的权重,而降低那些正确分类的样本的权重,这样就能使得错误分类的样本可以受到更多的关注,从而在下一轮中可以正确分类,使得分类问题被一系列的弱分类器“分而治之”。对于组合方式,AdaBoost采用加权多数表决的方法,具体地,加大分类误差率小的若分类器的权值,减小分类误差率大的若分类器的权值,从而调整他们在表决中的作用。

随机森林

随机森林(Random Forest,简称RF)是Bagging集成学习方法的一个扩展变体。随机森林以决策树作为Bagging集成学习的基学习器,与经典的决策树不同,随机森林在构建决策树模型的时候不是在所有的属性上去选择最优划分属性,而是在数据集属性的一个随机子集上进行最优划分属性的选择。由于基学习器的训练数据以及特征属性都不完全相同,随机森林构造的基学习器具有较大的差异,使得随机森林不仅简单、计算开销小,而且在很多实际任务中展现出强大的性能。

实验内容

数据集准备

  1. 利用sklearn生成非线性数据(用于主体实验数据)
    1
    2
    from sklearn.datasets import make_moons
    x, y = make_moons(n_samples=1000, noise=0.4, random_state=0)
  • 生成的数据按照按照3:1切分训练集与测试集
  • 数据切分的随机种子调成0(即random_state=0)
  1. 利用sklearn自带.的Iris数据集(主要完成随机森林的特征可视化)

基于不同分类器的集成学习(仅在make_moons数据集上实现)

  1. 利调用sklearn中的knn,logistic回归和高斯朴素贝叶斯三种分类器
  2. 模型分别学习make_moons训练集中的数据
  3. 自己编程实现基于多数投票的集成选择(不得使用sklean实现)
  4. 尝试采用sklean中的VotingClassifier实现基于“硬投票”和“软投票”的分类

结果展示:

  • 分别展示三种分类器的分类结果以及手写多数投票的集成实验结果
  • 展示基于硬投票和软投票集成的分类结果

基于Bagging的随机森林算法实现

  1. 尝试基于sklearn中的BaggingClassifier和DecisionTreeClassifier构建随机森林,并实现make_moons数据集的分类
  2. 尝试基于sklearn中的RandomForestClassifier构建随机森林,并利用feature_importances_分析属性的重要性(属性的重要性可在make_moons和iris数据集中分别尝试)
    结果展示:
  • 分别展示两种构造随机森林方法在make_moons测试集上的分类结果
  • 展示随机森林对make_moons和iris特征重要性的比例

基于Boosting的算法实现

  1. 尝试基于sklearn中的AdaBoostClassifier实现make_moons数据集的分类
  2. 尝试基于sklearn中的GradientBoostingClassifier实现make_moons数据集的分类

结果展示:分别展示两种boosting方法在make_moons测试集上的分类结果

实验代码和结果

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
import numpy as np
from sklearn.model_selection import train_test_split
from sklearn.datasets import make_moons
from sklearn.datasets import load_iris
from sklearn.neighbors import KNeighborsClassifier
from sklearn.linear_model import LogisticRegression
from sklearn.naive_bayes import GaussianNB
from sklearn.ensemble import VotingClassifier
from sklearn.metrics import accuracy_score
x, y = make_moons(n_samples=1000, noise=0.4, random_state=0)
X_train,X_test,y_train,y_test=train_test_split(x,y,train_size=0.75,test_size=0.25,random_state=0)
knn = KNeighborsClassifier() #实例化KNN模型
knn.fit(X_train, y_train) #放入训练数据进行训练
pk=knn.predict(X_test)
lstr=LogisticRegression()
lstr.fit(X_train,y_train)
pl=lstr.predict(X_test)
gnb=GaussianNB()
gnb.fit(X_train,y_train)
pg=gnb.predict(X_test)
pre=(pk+pl+pg)/3
count=0
for i in range(len(pre)):
if(pre[i]<0.5): pre[i]=0
else:pre[i]=1
print("KNN分类准确率:",accuracy_score(y_test,pk))
print("logistic regression分类准确率:",accuracy_score(y_test,pl))
print("高斯朴素贝叶斯分类准确率:",accuracy_score(y_test,pg))
print("手写投票测试准确率:" + str(accuracy_score(y_test,pre)))
voting_clf = VotingClassifier(estimators=[
('knn', knn),
('lstr', lstr),
('gnb', gnb),
], voting='hard')
voting_clf.fit(X_train,y_train)
vh=voting_clf.predict(X_test)
votings = VotingClassifier(estimators=[
('knn', knn),
('lstr', lstr),
('gnb', gnb),
], voting='soft')
votings.fit(X_train,y_train)
vs=votings.predict(X_test)
print("硬投票测试准确率:" + str(accuracy_score(y_test,vh)))
print("软投票测试准确率:" + str(accuracy_score(y_test,vs)))

from sklearn.datasets import load_iris
from sklearn.ensemble import VotingClassifier
from sklearn.metrics import accuracy_score
from sklearn.tree import DecisionTreeClassifier
from sklearn.ensemble import BaggingClassifier
from sklearn.ensemble import RandomForestClassifier
iris=load_iris()
Xi=iris.data
Xi=Xi[0:100]
yi=iris.target
yi=yi[0:100]
Xi_train,Xi_test,yi_train,yi_test=train_test_split(Xi,yi,train_size=0.75,test_size=0.25,random_state=0)
x, y = make_moons(n_samples=1000, noise=0.4, random_state=0)
X_train,X_test,y_train,y_test=train_test_split(x,y,train_size=0.75,test_size=0.25,random_state=0)
clf = DecisionTreeClassifier()
rfc1 = BaggingClassifier(clf,n_estimators=50)
rfc1.fit(X_train,y_train)
pr=rfc1.predict(X_test)
rfc2=RandomForestClassifier(n_estimators=50)
rfc2.fit(X_train,y_train)
pr2=rfc2.predict(X_test)
rfc3=RandomForestClassifier(n_estimators=50)
rfc3.fit(Xi_train,yi_train)
pr3=rfc3.predict(Xi_test)
print("BaggingClassifier的准确率:",accuracy_score(y_test,pr))
print("RandomForestClassifier的准确率:",accuracy_score(y_test,pr2))
feai=rfc2.feature_importances_
print("特征的重要性:",feai)

make moon的结果:

alt text

iris的结果:

alt text

1
2
3
4
5
6
7
8
adb = AdaBoostClassifier(n_estimators=100)
grb=GradientBoostingClassifier(n_estimators=100)
adb.fit(X_train,y_train)
grb.fit(X_train,y_train)
pa=adb.predict(X_test)
pg=grb.predict(X_test)
print("AdaBoostClassifier的准确率为",accuracy_score(y_test,pa))
print("GradientBoostingClassifier的准确率为",accuracy_score(y_test,pg))

alt text

小结或讨论

集成方法有很多种,一种叫做bagging,bagging的思想是,我把我的数据做一点微小的调整,就得到了一个跟原来不一样的数据集,我就能多训练一个模型出来,模型的数量多了,解释力自然就增强了。比如说我原来有100个人的数据,其中有两个分别叫Tony和Lily,我把Tony这条数据删掉,用Lily的数据来替换,这样就得到了一个跟原来不一样的船新的数据集,这个过程叫做Bootstrap

每一个Bootstrap数据集都能用来训练一次模型,所以我们重复这个过程,比如重复1000次,一次是Tony替代Cici,一次是Ivy替代Yuki,这样每一次都是不一样的数据,也就可以训练1000次,得到了1000个决策树,我们把这1000个决策树打包到一起作为我们最终的模型,这个打包就叫做bagging

一般我们会把bagging跟随机森林一起叠加使用,在数据点的处理上,我们使用bagging来创造许多组(比如说1000组)bootstrap数据,对于每一组数据,我们使用随机森林来训练模型,最后再把所有模型的预测结果bagging起来

第二种集成的方法是boosting,boosting跟bagging一样都属于集成的思想,本质上都是训练很多模型,用数量堆积出质量。还是举1000个model,100个variable的例子,bagging是训练1000个等价的模型,比如说用随机森林,这些模型都是同样随机从100个里面选10个variable出来训练,每一个模型之间是同一级别的、互不干扰的

但boosting的思路和bagging不同,boosting里每一个模型都是基于上一个模型来进行优化,它的核心思想是训练1000个模型,每一个模型在上一个模型的基础上再好一点点