机器学习详解(18):随机森林原理及代码实现

随机森林是一种常用的监督学习算法,适用于回归和分类任务。它通过集成多个决策树模型,提高预测的准确性和稳定性,是应对单棵决策树易过拟合、对数据敏感等缺点的有效改进方式。作为一种集成方法,随机森林利用有标签的数据进行训练,并结合多个树的预测结果做出最终判断。

1 介绍

1.1 原理

随机森林通过组合多棵决策树来进行预测。森林中的每棵树都在数据的一个随机子样本上进行训练,并在每次划分节点时只考虑部分随机选取的特征。每棵树就像一个“专家”,独立做出分类判断。最终结果通过多数投票决定哪一类为最终预测(如果是回归任务,则取所有树预测值的平均)。

如下图所示,有一组由n棵树组成的森林,我们看前5棵,其中4棵判断为“猫”,1棵判断为“狗”,那最终结果就是“猫”。每棵树走的判断路径可能不同,因此预测也各有差异。

illustration of how random forest classification works

随机森林的工作流程如下:

  1. Bootstrap抽样:每棵树都会获得一个独立的训练子集,该子集是通过对原始数据进行有放回的随机抽样生成的。这意味着某些数据点可能重复出现,而另一些则未被使用。
    • 目的是让每棵树看到的数据不同,模型更有多样性,防止所有树都长得一样
  2. 随机特征选择:在进行节点划分时,每棵树只考虑所有特征中的一个随机子集(通常是总特征数的平方根)。
  3. 构建树模型:每棵树仅基于自己的Bootstrap样本和随机选择的特征集不断分裂节点,直到满足停止条件(如节点纯度或最小样本数)。
  4. 最终预测:所有决策树共同参与最终预测。对于分类任务,采用多数投票结果作为输出;对于回归任务,计算所有树预测值的平均作为最终结果。

1.2 例子

这里用一个实例解释一下Bootstrap抽样和随机特征选择:

假设你有一个小型的图像分类数据集,总共有 10张图片,每张图像已经贴好标签(猫或狗):

图片编号标签
1
2
3
4
5
6
7
8
9
10

我们从这10张图中,随机地、有放回地抽取10张样本,可能得到如下这个“子训练集”:

抽样顺序选中的图片编号标签
12
25
32
47
59
61
74
82
910
103

你会发现:

  • 图片2出现了 3次
  • 图片6、8 没有出现
  • 这就是这棵树的训练集,具有随机性和重复性

除了样本不同,每棵树在分裂每个节点时,还只考虑部分特征,这就是“随机特征选择”。假设我们对每张图像提取了如下特征:

特征编号特征名含义说明
F1耳朵高度猫高、狗低
F2毛发密度猫密、狗疏
F3眼睛间距猫眼近、狗眼远
F4嘴巴宽度狗嘴宽、猫嘴窄
F5尾巴弯曲度猫尾巴更弯
F6身体长度狗身体更长

在每次节点分裂时,并不会考虑全部6个特征,而是随机选取其中一部分(比如2个)。

例如某次分裂只选中了 [F2, F4],那本节点只能在这两个中选择“最佳分裂特征”。这会导致每棵树的结构更加不一样,进一步增强多样性。

1.3. OOB(Out-of-Bag)

由于 Bootstrap 是有放回抽样,大约有36.8%的样本不会被采样到某棵树中,这些样本就叫作袋外样本(Out-of-Bag)。这些袋外样本可以被用来评估该棵树的性能,相当于内置了“交叉验证”的效果。

在随机森林中,每个样本通常不会出现在所有树的训练集中。由于采用了 Bootstrap 抽样,有些样本在某棵树中被选中用于训练,而在其他树中则未被使用。对于这些“未见过该样本”的树,我们可以利用它们对该样本进行预测,并将预测结果与真实标签进行对比,计算预测的准确率或误差。最后,对所有样本在其对应“未见过的树”上的预测误差取平均,就得到了随机森林的OOB(Out-of-Bag)估计误差

这种方法的最大优势在于,它不需要额外划分验证集,就可以获得模型在未见数据上的泛化能力评估。在数据集较小的场景中尤其有用,不会浪费宝贵的训练数据,同时还能提供稳定、有效的模型性能参考。

2 代码实例

现在我们通过使用 sklearn 中的 RandomForestClassifier,对 possum.csv 数据集进行性别分类预测。

possum.csv 是一个关于袋貂(possum)的生物测量数据集,包含多个物理特征(如体长、尾长、耳长等),目标是预测袋貂的性别(male / female)。

数据准备

import pandas as pd

df = pd.read_csv("possum.csv")
df.sample(5, random_state=44)

在这里插入图片描述

为了避免训练时出错,我们先去除包含缺失值的样本行。

df = df.dropna()

删除那些不必要的列,然后将特征数据和标签数据分别存储在不同的变量中:

X = df.drop(["case", "site", "Pop", "sex"], axis=1)
y = df["sex"]
  • case:这是每只袋貂的编号,相当于一个唯一标识符。它对分类任务没有实际意义,反而可能引入噪声。
  • site:表示采样地点编号,是一个离散数字(如 1、2、3),它本质上是一个“类别”变量,而不是袋貂本身的生理特征。
  • Pop:代表袋貂所属的族群(例如“Vic”或“other”),它可能与性别有一定相关性,但本身是类别型变量,我们当前主要关注数值型特征作为输入。

训练模型

from sklearn.model_selection import train_test_split
X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.3, random_state=44)
from sklearn.ensemble import RandomForestClassifier
rf_model = RandomForestClassifier(n_estimators=50, random_state=44)
rf_model.fit(X_train, y_train)

首先划分数据集,将 70% 的数据用于训练,30% 用于测试。接着使用 50 棵树构建森林;设置随机种子保证实验可重复,最后使用 .fit() 方法训练模型。

预测测试集结果

predictions = rf_model.predict(X_test)
predictions

输出:

在这里插入图片描述

预测概率输出

返回的是每个样本属于每个类别(例如 male/female)的概率值,适用于需要概率输出的场景(比如做阈值判断)。

rf_model.predict_proba(X_test)

输出:

特征重要性分析

我们来查看一下每个特征在决策过程中起到的重要程度,返回一个与特征顺序对应的数组。

importances = rf_model.feature_importances_
columns = X.columns
i = 0

while i < len(columns):
    print(f"The importance of feature '{columns[i]}' is {round(importances[i] * 100, 2)}%.")
    i += 1

输出:

在这里插入图片描述

模型表现

from sklearn.metrics import accuracy_score, classification_report
predictions = rf_model.predict(X_test)
print("accuracy:", accuracy_score(y_test, predictions))
print(classification_report(y_test, predictions))

输出:

在这里插入图片描述

可以看出模型的表现并不理想:

  • 模型倾向预测为男性:召回率高达 0.82,说明模型更擅长找出男性;
  • 对于女性识别能力差:召回率仅 0.36,表示很多实际是女性的样本被错分成了男性;
  • 不平衡预测倾向:虽然样本数还算均衡(f:14, m:17),但模型判断偏向一方,说明可能受到某些特征主导影响。

改进

由于这里只是简单介绍一下随机森林的例子,就不进一步优化模型了,以下是一些可能得改进模型的方法:

  1. 增加树数量:试试 n_estimators=100 或更多,让模型更稳定。
  2. 特征工程:检查是否某些特征对性别没有帮助,或可以做归一化、组合、去除异常值等操作。
  3. 样本增强:如果数据量较小,可以考虑扩充样本,或使用 SMOTE 等方法增强少数类。
  4. 调参优化:尝试调整 max_depth、min_samples_leaf、class_weight 等参数。
  5. 尝试其他模型:对比逻辑回归、SVM 等看看是否能更好捕捉模式。

3 总结

随机森林是一种基于决策树的集成学习算法,通过引入样本和特征的双重随机性,构建多棵彼此独立的树模型,并以投票或平均的方式输出最终结果。这种方法不仅提升了模型的泛化能力,还有效减少了过拟合风险。它在处理高维数据、评估特征重要性以及应对复杂非线性关系方面具有明显优势。尽管在小数据集上可能表现受限,但通过合理调参与特征工程,随机森林依然是一种强大且易用的机器学习工具。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

tilblackout

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值