机器学习集成算法:一文理解 随机森林(RandomForest) 模型使用以及参数含义
随机森林是机器学习领域最常用的算法之一,其算法构筑过程非常简单:在构建随机森林时,从提供的数据中随机抽样出不同的子集(这个过程不仅包括样本的随机抽取,还有特征的随机抽取),用于建立多棵不同的决策树,并按照 Bagging 的规则对单棵决策树的结果进行集成(其中回归任务采取平均值,分类任务则遵循少数服从多数的原则)。从原理上来看,随机森林的构造相对简单。但与单棵决策树相比,它学习能力更加强大、算法复
什么是随机森林?它的算法流程是怎样的?
它有哪些优缺点?它应该如何使用?参数都是什么含义?
集成学习上一篇文章: 机器学习集成算法:一文理解 Bagging 算法以及运用策略
一、什么是随机森林?
随机森林是机器学习领域最常用的算法之一,其算法构筑过程非常简单: 在构建随机森林时,从提供的数据中随机抽样出不同的子集(这个过程不仅包括样本的随机抽取,还有特征的随机抽取),用于建立多棵不同的决策树,并按照 Bagging 的规则对单棵决策树的结果进行集成(其中回归任务采取平均值,分类任务则遵循少数服从多数的原则)。
从原理上来看,随机森林的构造相对简单。但与单棵决策树相比,它学习能力更加强大、算法复杂度更高、又具备一定的抗过拟合能力,是从根本上来说比单棵决策树更优越的算法。这种优越性使得它在多种机器学习任务中表现出色。即便在深入了解机器学习的各种技巧之后,它依然是我们能够使用的强大的算法之一。在机器学习竞赛当中,随机森林往往是我们在中小型数据上会尝试的第一个算法。帮助我们快速地提供一个相对较好的基准模型,了解数据的基本模式和特征的重要性。
在实际应用中,随机森林的实现也非常方便。以 sklearn 库为例子,随机森林可以实现回归也可以实现分类。随机森林回归器由类 sklearn.ensemble.RandomForestRegressor
实现,随机森林分类器则有类 sklearn.ensemble.RandomForestClassifier
实现。我们可以像调用逻辑回归、决策树等其他 sklearn 中的算法一样来使用随机森林,其中回归森林的默认评估指标为 R2 (过时了),分类森林的默认评估指标为准确率。
随机森林的算法流程
我们以下面的伪代码为例,展示随机森林如何训练
输入:训练集 T,大小为 N,特征数目为 M,随机森林中树的数量为 K
输出:随机森林
随机森林 = 空集合 (# 这个集合里会放入 k 个 决策树)
for i from 1 to K do
从 T 中以有放回抽样的方式取样 N 次,形成新子训练集 D
随机选择 m 个特征,其中 m < M
使用 D 和 m 个特征学习出一个完整的决策树
将决策树加入随机森林
返回 随机森林
同样,我们以下面的伪代码为例,展示随机森林如何利用 bagging 得到结果
输入:测试样本 x,随机森林(包含 K 棵决策树)
输出:预测结果
预测结果列表 = 空列表
for 每棵决策树 in 随机森林 do
单棵树预测结果 = 决策树.predict(x)
将单棵树预测结果添加到预测结果列表
if 分类问题 then
预测结果 = 多数投票(预测结果列表)
else if 回归问题 then
预测结果 = 平均(预测结果列表)
返回 预测结果
随机森林的优点缺点
优点
- 擅长高维数据处理 :即使特征之间存在相关性或冗余,随机森林也能通过特征选择有效降低模型复杂度和过拟合风险。
- 并行训练 :随机森林中的每棵树可独立训练,借助并行计算可加速训练过程,使其在处理大规模数据集时表现出色。
- 得益于 bagging 集成算法 :在建造随机森林时,我们可以在内部相对准确地估算模型对新数据的预测误差,还能帮助估计数据中丢失的部分。即使数据集中有部分值缺失,随机森林也能通过分析其他数据点间的关系猜测缺失值,即使有大量资料丢失或面对不平衡的分类数据集,它也能维持较高准确度。
缺点
- 集成带来的黑盒特性 :随机森林的决策过程难以解释,具有一定的黑盒性。
- 计算复杂度与内存占用较大 :随机森林需存储和训练多棵决策树,尤其在树的数量较多时,容易遇到性能瓶颈。
- 对稀疏数据的处理能力有限 :在面对稀疏数据时,随机森林的处理效果不够理想。
- 在某些噪声较大的分类或回归问题上存在过拟合风险 :尽管随机森林通常对噪声有一定容忍度,但在噪声过多的特定问题中,仍可能出现过拟合情况。
无论怎样,确保随机森林不会过拟合是使用随机森林最关键的一件事情
二、随机森林的使用
以一个经典的、易于理解的数据集鸢尾花分类数据集(Iris)为例。按照加载数据、划分训练集和测试集、训练模型、进行预测、评估模型性能流程演示。
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 = 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)
# 创建随机森林分类器
rf_classifier = RandomForestClassifier(n_estimators=100, 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:.2f}")
三、随机森林的参数
参数的修改可以使随机森林变得更强大。比起经典机器学习算法逻辑回归、岭回归等,随机森林回归器的参数数量较多,因此我们可以将随机森林类的参数分为如下 3 大类别(按重要性排序)。
(1) 影响集成结构
n_estimators
在随机森林模型中,n_estimators
是森林中树木的数量,即弱评估器的数量(集成学习最重要的参数之一),在 sklearn 中默认 100,它是唯一一个对随机森林而言必填的参数。n_estimators 对随机森林模型的精确程度、复杂度、学习能力、过拟合情况、需要的计算量和计算时间都有很大的影响,因此 n_estimators 往往是我们在调整随机森林时第一个需要确认的参数。对单一决策树而言,模型复杂度由树结构(树深、树宽、树上的叶子数量等)与数据量(样本量、特征量)决定,而对随机森林而言,模型复杂度由森林中树的数量、树结构与数据量决定,其中树的数量越多,模型越复杂。
n_estimators
并非越大越好。n_estimators 越大时,模型的复杂程度上升,泛化能先增强再减弱(或不变),模型的学习能力越来越强,在训练集上的分数可能越来越高,过拟合风险越来越高,模型需要的算力和内存越来越多,模型训练的时间会越来越长 。在调整 n estimators 时,我们总是希望在模型效果与训练难度之间取得平衡,同时还需要使用交叉验证来随时关注模型过拟合的情况。
一般来说,个人电脑能够容忍的 n_estimators 数量大约在 200~1000 左右。实际上我们更希望在最优点的时候树的数量越少越好。
(2) 影响集成训练
boostrap
,oob_score
,max_samples
,max_features
四个参数是用来控制样本的随机抽取的。让我们想想决策树是如何进行分支的? 对每个特征决策树都会找到不纯度下降程度最大的节点进行分枝,因此原则上来说,只要给出数据一致、并且不对决策树进行减枝的话,决策树的结构一定是完全相同的。对集成算法来说,平均多棵相同的决策树的结果并没有意义,因此集成算法中每棵树必然是不同的树,Bagging 算法是依赖于随机抽样数据来实现这一点的。随机森林会从提供的数据中随机抽样出不同的子集,用于建立多棵不同的决策树,最终再按照 Bagging 的规则对众多决策树的结果进行集成。
bootstrap
参数的输入为布尔值,默认 True,控制是否在每次建立决策树之前对数据进行随机抽样。如果设置为 False,则表示每次都使用全部样本进行建树,如果为 True,则随机抽样建树。从语言的意义上来看 boostrap 可以指代任意类型的随机抽样,但在随机森林中它特指有放回随机抽样技术。(同时抽样技术又分为样本的随机抽样和特征的随机抽样)
oob_score
控制是否使用袋外数据进行验证,输入为布尔值,默认为False,如果希望使用袋外数据进行验证修改为True即可。
max_samples
控制抽样数据集的大小,通常来说,max_samples 是等于 m 的,也就是抽样数据集的大小与原数据集一致,但是如果原始数据集太大、或者太小,我们也可以自由调整 max_samples 的大小。
max_features
控制特征抽取的数量,在随机森林中 max_features 的用法与决策树中完全一致,其输入也与决策树完全一致。输入整数,表示每次分枝时随机抽取 max_features 个特征。输入浮点数,表示每次分枝时抽取 round(max_features * n_features)
个特征。输入“auto” 或者 None,表示每次分枝时使用全部特征。输入“sqrt”,表示每次分枝时使用 sqrt(n_features)
。输入"log2",表示每次分枝时使用 log2(n_features)
需要注意的是,无论对数据进行怎样的抽样,我们能够控制的都只是建立单棵树时的数据而已。在总数据量有限的情况下,单棵树使用的数据量越大,每一棵树使用的数据就会越相似,每棵树的结构也就会越相似,bagging 的效果难以发挥、模型也很容易变得过拟合。因此,当数据量足够时,我们往往会消减单棵树使用的数据量。同样的,当数据样本量足够大的时候(数万),变换随机数种子几乎不会对模型的泛化能力有影响,因此在数据量巨大的情况下,我们可以随意设置任意的数值。当数据量较小的时候,我们可以把随机数种子当做参数进行调整,但前提是必须依赖于交叉验证的结果。选择交叉验证结果中均值最高、方差最低的随机数种子,以找到泛化能力最强大的随机模式。
(3) 影响单个决策树
在集成算法当中,控制单个弱评估器的结构是一个重要的课题,因为单个弱评估器的复杂度/结果都会影响全局,其中单棵决策树的结构越复杂,集成算法的整体复杂度会更高,计算会更加缓慢、模型也会更加容易过拟合,因此集成算法中的弱评估器也需要被剪枝。随机森林回归器的弱评估器是回归树,因此集成评估器中有大量的参数都与弱评估器回归树中的参数重合。
这些参数在随机森林中的用法与默认值与决策树类 DecisionTreeRegressor
中完全一致,专门用于对决策树进行剪枝、控制单个弱评估器的结构。在这里,我们重点介绍下面的参数。
criterion
与feature_importances
criterion
是分枝标准,分类树可以选择信息熵/基尼系数,回归树中的 criterion 可以选择"squared_error”(平方误差),“absolute_error"(绝对误差)以及"poisson"(泊松偏差)。
其中平方误差比绝对误差更敏感(类似于信息熵比基尼系数更敏感),并且在计算上平方误差比绝对误差快很多。泊松偏差则是适用于一个特殊场景的: 当需要预测的标签全部为正整数时,标签的分布可以被认为是类似于泊松分布的。比如预测点击量、预测客户/离职人数、预测销售量等。
当我们选择不同的 criterion 之后,决策树的 feature_importances 也会随之变化,因为在 sklearn 当中 feature importances 是特征对 criterion 下降量的总贡献量,因此不同的 criterion 可能得到不同的特征重要性。
粗糙的讲,选择 criterion 的唯一指标就是最终的交叉验证结果–无论理论是如何说明的,我们只取令随机森林的预测结果最好的 criterion。
max_depth
最粗犷的剪枝方式,从树结构层面来看,对随机森林抗过拟合能力影响最大的参数。max_dqpth 的默认值为 None,也就是不限深度。因此当随机森林表现为过拟合时,选择一个小的 maxdepth 会很有效。同时如果设置的太小,那下面的剪枝精修参数可能发挥的效果就不会太大了。
max_leaf_nodes
,min_sample_split
,min_impurity_decrease
三个比 max_depth 更精细的减枝方式,限制叶子数量和分枝,既可以实现微调,也可以实现大刀阔斧的剪枝。max_leaf_nodes 的默认值为 None,即不限叶子数量。min_sample_split 的默认值为 2,等同于不限制分枝。min_impurity_decrease 最精细的减枝方式,可以根据不纯度下降的程度减掉相应的叶子。默认值为 0,因此是个相当有空间的参数。
精修参数实际手动调整是非常困难的,我们只需要知道是什么意思即可。后续使用如 Optuna 库,进行自动化调参即可
更多推荐
所有评论(0)