集成学习(Ensemble Learning)作为一种流行的机器学习,它通过在数据集上构建多个模型,并集成所有模型的分析预测结果。常见的集成学习算法包括:随机森林、梯度提升树、Xgboost等。
多个模型集成的模型叫做集成评估器(ensemble estimator),其中的每个模型叫做基评估器(base estimator)。以基评估器的集成方式角度出发,集成算法可分为:装袋法(Bagging
)、提升法(Boosting
)与堆叠法(Stacking
)。其中Bagging
方法与boosting
方法是最为常见的两种集成方式,它们的原理图如下所示:
Bagging
方法的核心思想:构建多个相互独立的评估器,然后根据平均或多数表决原则来决定集成评估器的结果,其中典型的代表就是随机森林模型。Boosting
方法的核心思想:其评估其是相关的,即按照一定的顺序依次构建集成评估器。进而结合弱评估器的力量逐步提升集成器的评估能力,最终得到一个强评估器。常见的提升法模型有Adaboosting
与提升树模型。随机森林作为一种典型的Bagging集成算法,其所有基评估器都是决策树,由分类树组成的森林叫做随机森林分类器,而由回归树构成的森林叫做随机森林回归器。
2.1 基于sklearn
的随机森林分类算法实现示例
sklearn
中的随机森林分类算法API为sklearn.ensemble.RandomForestClassifier
,其常用的参数如下所示:
from sklearn.ensemble import RandomForestClassifier
rfc = RandomForestClassifier(
n_estimators = 100, # 随机森林中树木的数量
criterion = "gini", # 不纯度的衡量指标
max_depth = 5, # 每棵树的最大深度
min_samples_leaf = 10, # 某个节点在分枝后的每个子节点都必须包含的最少样本数
min_samples_split = 10, # 某个节点必须包含最少的样本数
max_features = "sqrt", # 分枝时的特征个数
min_impurity_decrease = 1e-3 # 信息增益的大小
)
通过sklearn
库可以很容易地实现随机森林分类算法,首先给出一个随机森林分类算法实现示例,可以结合2.2 随机森林分类函数的重要参数与2.3 随机森林分类函数的重要属性与接口两个部分理解代码。
为了体现出随机森林算法的优越性,同时实现随机森林算法与决策树算法两种模型,并最终比较两者的预测性能。使用sklearn.ensemble.RandomForestClassifier
实现随机森林分类算法与决策数算法主要步骤如下所示:
实现代码如下所示:
from sklearn.ensemble import RandomForestClassifier
from sklearn.tree import DecisionTreeClassifier
from sklearn.model_selection import train_test_split
from sklearn.datasets import load_wine
# 1. 导入需要的数据集并将其划分为训练集与测试集
wine = load_wine()
X_train, X_test, y_train, y_test = train_test_split(
wine.data, wine.target, test_size=0.3
)
# 2. 分类算法实例化、训练与预测性能评价
clf = DecisionTreeClassifier() # 决策树实例化
rfc = RandomForestClassifier() # 随机森林实例化
# 模型的训练与性能评价
clf = clf.fit(X_train, y_train) # 决策树模型训练
rfc = rfc.fit(X_train, y_train) # 随机森林模型训练
# 性能评价
score_clf = clf.score(X_test, y_test) # 决策树性能评价结果
score_rfc = rfc.score(X_test, y_test) # 随机森林性能评价结果
# 3. 输出两个模型的预测结果
print("单个决策树的分类预测结果:{}\n".format(score_clf),
"随机森林分类预测结果:{}\n".format(score_rfc))
由此可以看出随机森林算法的预测精度明显高于单个决策树的预测精度。
2.2 随机森林分类函数的重要参数
sklearn
中随机森林分类算法API的主要参数包括两类:基评估器的参数与集成评估器参数。
如下表所示,基评估器的主要参数与决策树相同:
参数 | 描述 |
---|---|
criterion | 不纯度的衡量指标,常用的包括gini与entropy两种方法 |
max_depth | 每棵树的最大深度,超过最大深度的树枝都会被剪掉 |
min_samples_leaf | 某个节点在分枝后的每个子节点都必须包含至少min_samples_leaf个训练样本,否则就不进行分枝操作 |
min_samples_split | 某个节点必须包含至少min_samples_split个训练样本,该节点才进行分枝操作 |
max_features | 指定分枝时需要考虑的特征个数,超过限制的特则和那个都会被舍弃,默认为总特征个数开方取整 |
min_impurity_decrease | 限制信息增益的大小,信息增益小于设定数值,则不进行分枝操作 |
只需要关注随机森林中树木的数量n_estimators
参数即可。通常来说,这个参数对随机森林模型的精确性影响是单调的,n_estimators
越大,模型的效果往往越好。但是相应的,任何模型都有决策边界,n_estimators
达到一定的程度之后,随机森林的精确性往往不在上升或开始波动,并且,n_estimators
越大,需要的计算量和内存也越大,训练的时间也会越来越长。
基于2.1部分的代码,下面研究随机森林中树木的数量n_estimators
参数对模型性能的影响。下面绘制随机森林n_estimators
的学习曲线,代码如下所示:
from sklearn.model_selection import cross_val_score
import matplotlib.pyplot as plt
rfc_performance = [] # 存放随机森林预测结果
# 绘制随机森林中树木的数量n_estimators的学习曲线
for i in range(100):
rfc = RandomForestClassifier(
n_estimators=i+1,
n_jobs=-1
) # 实例化随机森林分类模型
# 下面使用10折交叉验证方法对随机森林进行训练与性能评价
rfc_score = cross_val_score(
rfc, wine.data, wine.target, cv=10
).mean()
rfc_performance.append(rfc_score) # 存放不同决策树个数的预测结果
# 绘制学习曲线
plt.figure(figsize=[10,4])
plt.plot(range(1,101), rfc_performance)
plt.show()
由n_estimators
参数的学习曲线可以看出,随机森林的分类算法随着n_estimators
的增加性能也逐渐增加,但是当其增加到一定数量后就出现所谓的决策边界,即围绕这一个分类精度小幅度随机振荡。
2.3 随机森林分类函数的重要属性与接口
属性 | 作用 |
---|---|
.estimators_ | 用来查看随机森林中所有树的列表 |
oob_score_ | 袋外得分。由于随机森林使用的有放回的抽样方式,这会导致有一些数据在训练过程中不会被选中,称这些数据为袋外数据。由于袋外数据没有被模型用来训练,我们可以使用他们作为测试数据集。因此我们可以使用oob_score_这个属性得到袋外数据的模型评价结果作为模型的性能指标 |
.feature_importances_ | 返回特征的重要性 |
接口 | 作用 |
---|---|
fit | 模型的训练 |
predict | 输入观测值,返回预测标签 |
score | 输入观测值与目标值,返回他们模型的预测精度 |
predict_proba | 返回每个测试样本被分到对应的每一类标签的概率,标签有几个分类就有几个概率 |
apply | 返回该样本在这棵树所在的叶子节点的索引 |
✨ 在机器学习中,使用泛化误差(Genelization Error)作为衡量模型在位置数据上的准确率的指标。为了得到理想的模型,通常我关注如下三个方面即可:
随机森林算法的调参过程可以很方便地通过sklearn.model_selection.GridSearchCV
方法来实现,其编程细节可参考第四部分的实例部分。
基于乳腺癌数据集的随机森林的分类算法的实现主要包括如下几个步骤:
n_estimators
的学习曲线绘制。由于决策树数量n_estimators
对随机森林分类模型具有重要的影响,所以首先需要研究其对模型性能的影响,以确定决策树数量超参数的决策边界;sklearn.model_selection.GridSearchCV
对其他超参数依次进行网格搜索。# 1. 导入必要的库与数据集
from sklearn.datasets import load_breast_cancer
from sklearn.ensemble import RandomForestClassifier
from sklearn.model_selection import GridSearchCV, cross_val_score
import matplotlib.pyplot as plt
import pandas as pd
import numpy as np
data = load_breast_cancer()
# 2. 随机森林分类模型的实例化、模型训练及决策树数量的学习曲线绘制
# 绘制随机森林模型决策树数量`n_estimator`的学习曲线
performance_score = [] # 存放不同决策树个数的模型预测性能
for i in range(0,200,10):
rfc = RandomForestClassifier(
n_estimators=i+1,
n_jobs=-1,
) # 随机森林分类模型实例化
score = cross_val_score(
rfc, data.data, data.target, cv=10
).mean() # 对模型进行训练与交叉验证
performance_score.append(score)
# 输出最大的预测结果及其标签
print(
max(performance_score),
(performance_score.index(max(performance_score))*10)+1
)
# 绘制学习曲线
plt.figure(figsize=[10, 4])
plt.plot(range(1,201,10), performance_score)
绘制的n_estimators
学习曲线如下所示:
由此,可以确定对于n_estimators
的决策边界处于[30 75]
之间,在此基础上进而对其他超参数依次进行网格搜索。
接着结合n_estimators
的决策边界[30 75]
,对随机森林中每个决策树的最大深度超参数max_depth
进行网格搜索,代码如下所示:
# 3. 进而对其他超参数进行网格搜索
# 随机森林中每个决策树的最大深度超参数`max_depth`的网格搜索
param_grid = {
"n_estimators": [*np.arange(30, 71, 5)],
'max_depth': [*np.arange(1, 21, 1)]
}
rfc = RandomForestClassifier() # 实例化一个随机森林分类模型
GS = GridSearchCV(rfc, param_grid, cv=10) # 实例化一个网格搜索对象
GS.fit(data.data, data.target) # 进行网格搜索
# 查看最优的参数组合及预测精度结果
# 返回最佳超参数组合
print("\n最佳的超参数组合:\n", GS.best_params_)
# 返回最佳的模型评价结果
print("\n最佳的分类评价结果:\n", GS.best_score_)
代码执行结果如下图所示:
由此可以看出决策树数量n_estimators
的最佳数量为
,且随机森林中每个决策树的最大深度超参数max_depth
最佳层数为
。为了便于优化过程,后续再对其他超参数进行优化时可以确定这两个超参数的具体值。
在上面的基础上对其他超参数进行网格搜索,进行最大特征超参数max_features
的网格搜索,本文的调参只是示例,读者完全可以按照自己的理解对其他参数或者每个参数范围进行自定义调整。
代码如下所示:
# 使用`sklearn.model_selection.GridSearchCV`对其他超参数依次进行网格搜索
param_grid = {
"max_features": [*np.arange(5, 21, 1)],
"min_samples_leaf": [*np.arange(1, 21, 2)],
"criterion": ("gini", "entropy")
}
rfc = RandomForestClassifier(
n_estimators=45,
max_depth=16
)
GS = GridSearchCV(rfc, param_grid, cv=10) # 实例化一个网格搜索对象
GS.fit(data.data, data.target) # 进行网格搜索
# 查看最优的参数组合及预测精度结果
# 返回最佳超参数组合
print("\n最佳的超参数组合:\n", GS.best_params_)
# 返回最佳的模型评价结果
print("\n最佳的分类评价结果:\n", GS.best_score_)
执行结果如下所示:
由此,可以看出通过调参,模型预测精度由原来的96.8%提升到97%。