集成学习(Ensemble Learning)是机器学习中的一种思想,它通过多个模型的组合形成一个精度更高的模型,参与组合的模型称为弱学习器(Weak Learner)。再预测时使用这些弱学习器模型联合进行预测;训练时需要用训练样本集依次训练出这些弱学习器。随机森林和Boosting算法都是集成学习的典型实现。
11.1随机森林
随机森林由多棵决策树组成。在数据结构中森林由多棵树组成,这里沿用了此概念。对于分类问题,一个测试样本会送到每一棵树中进行预测,然后投票,得票最多的类为最终分类结果。对于回归问题,随机森林的预测输出是所有决策树输出的均值。
11.1.1随机抽样
Bootstrap抽样是一种数据抽样方法。抽样是指从一个样本数据集中随机选取一些样本,形成新的数据集。在这里有两种选择:有放回抽样和无放回抽样。有放回抽样是指一个样本被抽中之后会放回去,在下次抽样时还有机会被抽中。对于无放回抽样,一个样本被抽中之后就从抽样集中去除,下次不会再参与抽样,因此,一个样本最多只会被抽中一次。Bootstrap使用的是有放回抽样。
Bootstrap抽样的做法是在有n个样本的集合中有放回地抽取n个样本。在这个新的数据集中原始样本集中的一个样本可能会出现多次,也可能不出现。假设样本集中有n个样本,每次抽中其中任何一个样本的概率都为1/n,一个样本在每次抽样中没被抽中的概率为1-1/n。由于是有放回抽样,每次抽样都是相互独立的,因此,对连续n次抽样,一个样本没被抽中的概率为:
11.1.2 Bagging算法
在日常生活中人们会遇到这样的情况:对一个决策问题,如果一个人拿不定主意,可以组织多个人来集体决策。例如,如果要判断一个病人是否患有某种疑难疾病,可以组织一批医生来会诊。会诊的做法是让每个医生做出一个判断,然后收集他们的判断结果进行投票,得票最多的那个诊断结果作为最终的结果。这种思想在机器学习领域的应用就是集成学习算法。
在Bootstrap抽样的基础上可以构造出Bagging(Bootstrap Aggregation)算法。这种方法对训练样本集进行多次Bootstrap抽样,用每次抽样形成的数据集训练一个弱学习器模型,得到多个独立的弱学习器,最后用它们的组合进行预测。训练流程如下:
循环,对
对训练样本集进行Bootstrap抽样,得到抽样后的训练样本集
用抽样得到的样本集训练一个模型
结束循环
输出模型组合
其中,T为弱学习器的数量。上面的算法是一个抽象的框架,没有指明每个弱学习器模型的具体形式。如果弱学习器是决策树,即为随机森林。
11.1.3训练算法
随机森林在训练时依次训练每一棵决策树,每棵树的训练样本都是从原始训练集中进行随机抽样得到。在训练决策树的每个节点时所用的特征也是随机抽样得到的,即从特征向量中随机抽出部分特征参与训练。随机森林对训练样本和特征向量的分量都进行了随机采样。
在这里决策树的训练算法与我们前面介绍的决策树训练过程基本相同,唯一不同的是这里训练决策树的每个节点时只使用随机抽取的部分特征分量。
样本的随机抽样可以用均匀分布的随机数构造,如果有个训练样本,只需要将随机数变换到区间[0,-1]即可。每次抽取样本时生成一个该区间内的随机数,然后选择编号为该随机数的样本。对特征分量的采样是无放回抽样,可以用随机洗牌的方式实现。
因为有了这些随机性,随机森林可以在一定程度上消除过拟合。对样本进行采样是必须的,如果不进行采样,每次都用完整的训练样本集训练出来的多棵树都是相同的。训练每一棵决策树时都有部分样本未参与训练,可以在训练时利用这些没有被选中的样本做测试,统计它们的预测误差,这称为包外误差。
实验结果表明,增加决策树的数量,包外误差会下降,这给我们提供了一种确定决策树数量的思路,可以通过观察包外误差来决定何时终止训练,当包外误差稳定了之后停止训练。
11.2 Boosting算法
Boosting(提升)算法也是一种集成学习算法。它由多个弱学习器组成,预测时用每个弱学习器分别进行预测,然后投票得到结果;训练时依次训练每个弱学习器,在这里采用了与随机森林不同的策略,不是对样本进行独立的随机抽样构造训练集,而是重点关注被前面的弱分类器错分的样本。
AdaBoost算法的全称是自适应提升(Adaptive Boosting),是Boosting算法的一种实现版本,是一种用于分类问题的算法,它用弱分类器的线性组合来构造强分类器。弱分类器的性能不用太好,仅比随机猜测强就可以,依靠它们可以构造出一个非常准确的强分类器。下面我们将对AdaBoost算法进行详细介绍。
11.2.1 强分类器与弱分类器
强分类器的计算公式为:
其中,x为输入向量,F(x)为强分类器, 为弱分类器, 为弱分类器的权重,T为弱分类器的数量。对于二分类问题,弱分类器的输出值为+1或-1,分别对应正样本或负样本。分类时的判定规则为:
强分类器的输出值也为+1或-1,同样对应于正样本或负样本。若分类器和它们的权重通过训练得到。之所以叫弱分类器是因为它们的精度不用太高,对于二分类问题,只要保证准确率大于0.5即可,即比随机猜测强,随机猜测也有0.5的准确率。
11.2.2 训练算法
训练时,依次训练每一个弱分类器,并得到它们的权重值。在这里,训练样本带有权重值,初始时所有样本的权重相等,在训练过程中,被前面的弱分类器错分的样本会加大权重,反之会减小权重,这样接下来的弱分类器会更加关注这些被错分的样本。弱分类器的权重值根据它的准确率构造,精度越高的弱分类器权重越大。给定个训练样本 ,其中, 是特征向量, 是类别标签,其值为+1或-1.训练算法的流程如下。
初始化样本权重值,所有样本的初始权重相等:
循环,对 依次训练每个弱分类器:
训练一个弱分类器 ,并计算它对训练样本集的错误率
计算弱分类器的权重:
更新所有样本的权重:
其中, 为归一化因子,它是所有样本的权重之和:
结束循环
最后得到强分类器:
根据计算公式,错误率低的弱分类器权重更大。沿用前面医生集体会诊的例子,如果在之前的诊断中医生的技术更好,对病人情况的判断更准确,那么可以加大他在此次会诊时的说话分量(即权重)。弱分类器在训练样本集上的错误率计算公式为:
因为在训练集上弱分类器的正确率大于0.5,所以有:
因此,弱分类器的权重大于0。弱分类器的错误率小于0.5是可以保证的,因为如果准确率小于0.5,只需要将弱分类器的输出反号即可。对于被弱分类器正确分类的样本,有:
对于被弱分类器错误分类的样本,有:
如果不考虑归一化因子 ,样本权重更新公式可以简化为:
由于:
样本权重更新公式可以进一步简化为:
被上一个弱分类器错误分类的样本本轮权重会增大,正确分类的样本本轮权重会减小,训练下一个弱分类器时算法会更加关注在上一轮中被错分的样本。这类似于人们日常生活中的做法:一个学生在每次考试之后会调整他的学习重点,本次考试做对的题目下次不再重点学习,而对于做错的题目下次要重点学习,以期待提高考试成绩。给样本加权重是有必要的,如果样本没有权重,每个弱分类器的训练样本是相同的,训练出来的弱分类器也是相同的,这样训练多个弱分类器没有意义。AdaBoost算法的核心思想就是关注之前被错分的样本,准确率高的弱分类器有更大的权重。
弱分类器模型可以选择决策树或逻辑回归等。强分类器是弱分类器的线性组合,如果弱分类器是线性函数,无论怎样组合,强分类器依然是线性的,因此,应该选择非线性模型作为弱分类器。
11.3实验程序
11.3.1随机森林
from sklearn.datasets import load_iris
from sklearn.model_selection import train_test_split
from sklearn.ensemble import RandomForestClassifier
from sklearn.metrics import accuracy_score
# 加载Iris数据集
iris = load_iris()
X = iris.data # 特征数据
y = iris.target # 目标值(标签)
# 划分训练集和测试集
X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.3, random_state=42)
# 创建RandomForestClassifier模型
rf_classifier = RandomForestClassifier(n_estimators=5, random_state=42)
# 训练模型
rf_classifier.fit(X_train, y_train)
# 使用测试集进行预测
y_pred = rf_classifier.predict(X_test)
# 计算并打印准确率
accuracy = accuracy_score(y_test, y_pred)
print(f"Accuracy: {accuracy:.2f}")
11.3.2 AdaBoost算法
# 导入必要的库
from sklearn.datasets import load_iris
from sklearn.model_selection import train_test_split
from sklearn.tree import DecisionTreeClassifier
from sklearn.ensemble import AdaBoostClassifier
from sklearn.metrics import accuracy_score
# 加载Iris数据集
iris = load_iris()
X = iris.data
y = iris.target
# 划分数据集为训练集和测试集
X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.3, random_state=42)
# 初始化DecisionTreeClassifier
base_clf = DecisionTreeClassifier(max_depth=1)
# 使用AdaBoostClassifier,设置弱分类器为DecisionTreeClassifier
ada_clf = AdaBoostClassifier(estimator=base_clf, n_estimators=5)
# 训练模型
ada_clf.fit(X_train, y_train)
# 在测试集上进行预测
y_pred = ada_clf.predict(X_test)
# 计算并打印准确率
accuracy = accuracy_score(y_test, y_pred)
print(f"Accuracy: {accuracy:.2f}")
代码下载地址:
通过百度网盘分享的文件:集成学习
链接:https://pan.baidu.com/s/1XXX1vNuYp-yn1eCHHgnkEw
提取码:9tkk
参考文献
雷明. 机器学习——原理、算法与应用.清华大学出版社.