随机森林(Random Forest)是一种常用的集成学习方法,主要用于分类和回归任务。 它通过构建多个决策树,并将这些树的预测结果进行平均(回归)或投票(分类),来提高模型的准确性和鲁棒性。
1. 基本概念 #
-
决策树(Decision Tree)
在介绍随机森林之前,首先需要了解决策树。决策树是一种基于树状结构的模型,通过对特征进行条件判断,将数据分成不同的叶子节点,以实现分类或回归任务。
-
集成学习(Ensemble Learning)
集成学习是通过构建并结合多个模型来完成预测任务的方法。它的目标是通过整合多个弱学习器(例如决策树)的结果,提升整体模型的性能。
-
随机森林(Random Forest)
随机森林通过构建多个决策树来进行预测。每棵树都是在一个随机子样本(通过Bootstrap抽样)上训练的,同时在每个节点分裂时只考虑随机选择的一部分特征。
1.1. Bagging #
Bagging(Bootstrap Aggregating)是一种集成学习方法,通过对多个子样本分别训练模型,并将这些模型的结果进行综合,以提高最终模型的稳定性和准确性。
- Bootstrap Sampling
- 从原始数据集(大小为 n)中随机抽取一个样本,并将其放入子样本中。
- 将抽取的样本放回原始数据集,再次进行随机抽取。
- 重复以上过程,直到子样本的大小达到 n。
- Bagging(Bootstrap Aggregating)
- 使用 Bootstrap Sampling 从原始数据集生成多个子样本。
- 在每子样本上分别训练一个基模型(如决策树)。
- 对于类任务,通过对所有基模型的预测结果进行投票(多数表决)来决定最终分类结果。
- 对于归任务,通过对所有基模型的预测结果取平均值来得到最终的预测结果。
1.2 决策树 #
决策树是一种树状结构的模型,用于分类和回归任务。它通过对特征进行一系列的条件判断,将数据分成不同的叶子节点,从而实现对目标变量的预测。
决策树的构建过程包括选择最优特征进行分裂、确定分裂阈值、控制树的深度和宽度,以及通过剪枝避免过拟合。
1.2.1 特征选择 #
在每个节点分裂时,需要选择一个特征及其对应的分裂点(阈值)进行分裂。常用的特征选择标准有以下几种:
- 信息增益(Information Gain):
信息增益用于衡量特征在分裂数据时所带来的信息减少量。信息增益越大,表示分裂后子节点越纯净。
$$
\text{Information Gain} = \text{Entropy}(D) - \sum_{i} \frac{|D_i|}{|D|} \text{Entropy}(D_i)
$$
- 其中,\(D\) 是数据集,\(D_i\) 是按某特征分裂后的子集,\(\text{Entropy}(D)\) 是数据集的熵。
- 基尼不纯度(Gini Impurity):
- 基尼不纯度用于衡量数据集的纯净度。基尼不纯度越小,表示数据集越纯净。 $$ \text{Gini}(D) = 1 - \sum_{i=1}^{C} p_i^2 $$
- 其中,\(p_i\) 是类别 \(i\) 在数据集 D 中的比例。
- 信息增益比(Information Gain Ratio):
- 信息增益比通过对信息增益进行归一化,避免信息增益偏好于多值特征的问题。 $$ \text{Information Gain Ratio} = \frac{\text{Information Gain}}{\text{Split Information}} $$
- 其中,\(\text{Split Information}\) 是对特征分裂信息的度量。
1.2.2. 分裂阈值的确定 #
在决策树的每个节点,需要为连续型特征选择一个最佳分裂阈值。以下是常用的方法:
- 穷举搜索:
个连续型特征,将其取值按升序排列,并对每两个相邻值的中点作为候选阈值进行评估,选择使分裂后子节点最纯净的阈值。 - 二分法:
对于连续型特征,可以采用二分法快速找到最佳分裂阈值。
1.2.3. 深度和宽度 #
决策树的深度和宽度直接影响模型的复杂度和泛化能力:
-
树的深度(Tree Depth):
树的深度是从根节点到叶子节点的最长路径上的节点数。树的深度越大,模型越复杂,容易过拟合。常用的控制深度的方法包括设置最大深度(max_depth)和最小样本分裂数(min_samples_split)。 -
树的宽度(Tree Width):
树的宽度是每一层节点的数量。虽然宽度不是直接控制的,但通过控制分裂条件(如最小样本叶子数min_samples_leaf),可以间接影响树的宽度。 -
最小样本分裂数
- 控制每个节点分裂所需的最小样本数
- 定义:
- 当一个节点包含的样本数量小于 min_samples_split 时,该节点将不会再分裂。
- min_samples_split 的默认值通常为 2,这意味着每个节点只要包含至少两个样本,就有可能继续分裂。
- 作用:
- 控制决策树的生长,防止树过度生长(过拟合)。
- 通过增加 min_samples_split,可以减少树的复杂度,提升模型的泛化能力。
1.2.4. 剪枝(Pruning) #
剪枝是减少决策树复杂度、避免过拟合的技术。分为预剪枝和后剪枝:
-
预剪枝(Pre-pruning):
- 在树的构建过程中提前停止分裂。例如,限制最大深度、最小样本分裂数、最小样本叶子数等。
-
后剪枝(Post-pruning):
- 在树完全构建后,逐步移除不必要的节点。例如,通过交叉验证来评估每个节点的贡献,移除对模型性能没有显著提升的节点。
- 具体步骤描述:
- 完全生长决策树:
- 首先,不进行任何剪枝,让决策树完全生长,直到满足某个终止条件(如节点样本数少于 min_samples_split)。
- 交叉验证评估:
- 使用交叉验证技术,评估完全生长的决策树在验证集上的性能(如准确率、F1 分数、均方误差等)。
- 逐步剪枝:
- 从叶子节点开始,逐层向上,逐步剪去那些对模型性能贡献不大的节点。
- 对于每个待剪去的节点,暂时将其剪去,并再次进行交叉验证,评估剪枝后的模型性能。
- 性能对比:
- 如果剪枝后的模型性能(在验证集上的评估指标)没有显著下降,则保留该剪枝操作。
- 如果剪枝后的模型性能显著下降,则恢复该节点,不进行剪枝。
2. 随机森林 #
2.1. 构建过程 #
-
数据集采样:
- 使用 Bootstrap 方法从原始数据集随机采样生成多个子样本。
- 每个子样本的大小与原始数据集相同,但由于是有放回的抽样,某些样本可能会重复出现,而另一些样本可能没有被抽到。
-
构建决策树:
- 对于每个个子样本,构建一棵决策树。在每个节点分裂时,随机选择部分特征进行最优分裂。
-
模型预测:
- 对于分类任务,随机森林通过对所有树的预测结果进行投票来决定最终分类结果。
- 对于回归任务,随机森林通过对所有树的预测结果进行平均来决定最终回归值。
2.2. 优缺点 #
-
优点:
- 高准确性:结合多棵决策树的结果,随机森林通常比单一的决策树模型具有更高的预测准确性。
- 防止过拟合:通过随机子样本和随机特征选择,随机森林有效地降低了过拟合的风险。
- 处理高维数据:能够处理具有大量特征的数据集,并能有效处理缺失值。
-
缺点:
- 计算成本高:需要训练大量的决策树,因此训练过程可能比较耗时,特别是对于大规模数据集。
- 模型复杂性:模型由多棵决策树组成,可能导致模型过于复杂,不易于解释。
2.3. 随机森林的参数 #
n_estimators
:决策树的数量。树的数量越多,模型的性能越好,但训练时间也会增加。max_depth
:决策树的最大深度。限制树的深度可以防止过拟合。min_samples_split
:一个节点分裂所需的最小样本数量。控制每个内部节点(非叶子节点)分裂所需的最小样本数。通过增加该参数,可以减少树的分枝,降低树的复杂度。min_samples_leaf
:叶子节点所需的最小样本数量。通过增加该参数,可以防止树生成过小的叶子节点,从而减少过拟合。max_leaf_nodes
:限制树的最大叶子节点数。通过限制叶子节点的数量,可以防止树过度生长。例如:max_leaf_nodes=20
。max_features
:每个节点分裂时考虑的特征数量。可以是整数、浮点数或特定字符串(如sqrt
、log2
)。- 整数:如果
max_features
是一个整数,则每次分裂时考虑的特征数目是这个整数。 - 浮点数:如果
max_features
是一个浮点数(在0和1之间),则每次分裂时考虑的特征数目是特征总数的这个比例。例如,max_features=0.8
表示每次分裂时考虑特征总数的 80%。 auto
或None
:默认值,对于分类问题,max_features
等于sqrt(n_features)
,对于回归问题,max_features
等于n_features
。sqrt
:每次分裂时考虑的特征数目等于特征总数的平方根,max_features = sqrt(n_features)
。
- 整数:如果
3. Python 代码 #
import numpy as np
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, classification_report
# 加载数据集
data = load_iris()
X = data.data
y = data.target
# 拆分数据集
X_train, X_test, y_train, y_test = train_test_split(X,
y,
test_size=0.33,
random_state=42)
# 创建随机森林分类器
model = RandomForestClassifier(
n_estimators=100, # 决策树数量
max_features='sqrt', # 每个节点分裂时考虑的特征数量
max_depth=5, # 最大深度
min_samples_split=4, # 最小样本分裂数
min_samples_leaf=2, # 最小样本叶子数
random_state=42
)
model.fit(X_train, y_train)
# 预测
predictions = model.predict(X_test)
# 评估
accuracy = accuracy_score(y_test, predictions)
report = classification_report(y_test, predictions)
print(f"Accuracy: {accuracy}")
print("Classification Report:")
print(report)