树莓派开发日记:Python实现随机森林预测


前言

在机器学习领域,随机森林(Random Forest)因其卓越的预测性能和广泛的应用场景,成为数据科学家和算法工程师的“工具箱常客”。作为集成学习的经典算法,它通过构建多棵决策树并融合结果,有效平衡了模型的准确性与泛化能力,被广泛应用于金融风控、医疗诊断、环境预测等复杂场景


一、随机森林介绍

随机森林是一种基于集成学习思想的机器学习模型,通过组合多棵决策树的预测结果提升整体模型的准确性和泛化能力。其核心设计包含双重随机性与集体决策机制,以下是原理的深度解析:

1.核心设计思想

随机森林通过以下两个关键随机性实现模型多样性:

​数据随机性​(Bootstrap抽样)

每棵决策树从原始训练集中有放回地随机抽取N个样本​(N为原始数据集大小),形成差异化的训练子集。未被抽中的约36.8%样本称为袋外数据(OOB)​,可用于评估模型泛化误差。

​​特征随机性​(随机子空间)

在每棵树的节点分裂时,仅从全部M个特征中随机选择m个候选特征(m值通常采用如下式子 )

m = M 或 m = log ⁡ 2 M m = \sqrt{M} \quad \text{或} \quad m = \log_2 M m=M m=log2M

​从中选择最优分裂方式。这种设计打破特征间的强相关性,增强模型鲁棒性

​2. 算法构建流程

随机森林的构建过程可分为以下步骤:

​​​生成Bootstrap样本​

通过有放回抽样为每棵树生成独立训练集。

递归构建决策树​

对每个节点随机选择m个特征子集;
基于基尼指数​(分类)或均方误差​(回归)选择最优分裂点;
完全生长不剪枝,依赖随机性抑制过拟合

​​​ 集成预测结果​

​分类任务​:通过多数投票法(众数)确定最终类别;
​回归任务​:取所有树预测值的平均值

原理图如下:
随机森林原理图

3.数学原理与误差控制​

偏差-方差分解​

随机森林的总误差可分解为单棵树偏差、方差与噪声之和。通过集成多棵低相关性的树,显著降低方差项。
Var ∝ 单棵树方差 n \text{Var} \propto \frac{\text{单棵树方差}}{n} Varn单棵树方差

​特征重要性评估​

基于OOB误差或分裂时的基尼指数减少量,量化特征对预测的贡献度,支持可解释性分析

4. 核心优势与适用场景​

​​优势​

抗过拟合能力强,适合高维数据(如基因表达、图像特征),且可以自动处理缺失值与非平衡数据,支持并行计算

​​局限性​

对高稀疏数据(如文本)效果有限;模型解释性弱于单棵决策树

二、Python实现

1.引入库

代码如下(示例):

from sklearn.datasets import fetch_california_housing                               # 加载加州房价数据集
from sklearn.ensemble import RandomForestRegressor                                  # 用于构建随机森林回归模型
from sklearn.metrics import mean_squared_error, mean_absolute_error, r2_score       # 用于计算均方误差、平均绝对误差、绝对系数
from sklearn.model_selection import train_test_split                                # 用于将数据集随机划分为训练集和测试集
import joblib                                                                       # 用于模型持久化(保存/加载)和高效计算。
import numpy as np                                                                  # 科学计算基础库

2.构建模型

代码如下(示例):

class HousingPricePredictor:
	def __init__(self, n_estimators=100, max_depth=None, random_state=42):
        """初始化随机森林回归模型"""
        self.n_estimators = n_estimators             # 决策树数量
        self.max_depth = max_depth                   # 树深
        self.random_state = random_state             # 随机性
        self.model = RandomForestRegressor(
            n_estimators=self.n_estimators,
            max_depth=self.max_depth,
            random_state=self.random_state
        )
        self.feature_names = None  # 新增特征名称存储

核心参数详解:

参数作用调优建议
n_estimators控制决策树数量,增加树可提升模型稳定性(默认100)通常设置100-500,超过阈值后收益递减
max_depth限制树深防止过拟合,None表示不限制推荐从3开始逐步增加测试效果
random_state固定随机性,确保实验可复现调试阶段必设,生产环境可取消

其他可设置的重要参数:

参数作用
criterion=‘squared_error’默认使用均方误差作为分裂标准
min_samples_split=2内部节点分裂所需最小样本数
max_features=‘auto’分裂时考虑的最大特征数(默认为√n)

3.导入数据

代码如下(示例):

    def load_data(self):
        """加载房价数据并拆分为训练集和测试集"""
        data = fetch_california_housing()
        self.feature_names = data.feature_names  # 存储特征名称
        X_train, X_test, y_train, y_test = train_test_split(
            data.data, data.target,
            test_size=0.3,
            random_state=self.random_state
        )
        return X_train, X_test, y_train, y_test

train方法通过fit()函数使用训练集数据(X_train特征矩阵和y_train目标值)训练预定义的随机森林回归模型,完成多棵决策树的集成学习;

参数作用默认值示例值
data.data特征矩阵(20640行×8列)-每个样本包含8
data.target目标变量(房价中位数)-数值范围0.15-5.0(单位:10万美元)
test_size测试集比例0.250.3表示30%数据作为测试集(约6192个样本)
random_state随机种子None42确保每次划分结果一致
shuffle是否打乱数据True默认启用 保证数据随机性
stratify分层抽样依据None常用于分类任务的类别平衡

数据流示例:

原始数据集(20640个样本)
train_test_split分割
├── 训练集:14448个样本(70%)
└── 测试集:6192个样本(30%)

4.模型的训练与评估

代码如下(示例):

    def train(self, X_train, y_train):
        """训练模型并输出训练过程数据"""
        self.model.fit(X_train, y_train)

    def evaluate(self, X_test, y_test):
        """评估模型性能并输出详细结果"""
        predictions = self.model.predict(X_test)

        # 新增多项评估指标
        mse = mean_squared_error(y_test, predictions)
        mae = mean_absolute_error(y_test, predictions)
        r2 = r2_score(y_test, predictions)

        print("\n=== 模型验证结果 ===")
        print(f"测试集样本数量: {len(X_test)}")
        print(f"均方误差(MSE): {mse:.2f}")
        print(f"平均绝对误差(MAE): {mae:.2f}")
        print(f"决定系数(R²): {r2:.2f}")

        return mse

evaluate方法则通过predict()对测试集(X_test)进行房价预测,并计算均方误差(MSE)、平均绝对误差(MAE)、决定系数(R²)三项核心指标。其具体意义如下:

评估指标数学公式核心特点
MSE 1 n ∑ i = 1 n ( y i − y i ^ ) 2 \frac{1}{n}\sum_{i=1}^{n}(y_i - \hat{y_i})^2 n1i=1n(yiyi^)2放大异常误差影响,单位与目标变量平方一致
MAE 1 n ∑ i = 1 n ∣ y i − y i ^ ∣ \frac{1}{n}\sum_{i=1}^{n} | y_i - \hat{y_i} | n1i=1nyiyi^直观解释误差绝对值,与目标变量单位相同
1 − ∑ i = 1 n ( y i − y i ^ ) 2 ∑ i = 1 n ( y i − y ˉ ) 2 1 - \frac{\sum_{i=1}^{n}(y_i - \hat{y_i})^2}{\sum_{i=1}^{n}(y_i - \bar{y})^2} 1i=1n(yiyˉ)2i=1n(yiyi^)2解释模型对数据变异的捕获能力,无量纲

5.模型持久化(模型保存)

    def save_model(self, filename="rf_model.pkl"):
        """保存模型到本地"""
        joblib.dump(self.model, filename)
        print(f"\n=== 模型已保存至 {filename} ===")

通过joblib.dump()方法将训练完成的随机森林模型(self.model)序列化并保存到本地文件,默认存储为当前目录下的rf_model.pkl文件

6.显示特征重要性

    def show_feature_importance(self):
        """显示特征重要性"""
        if self.feature_names is None:
            return

        importances = self.model.feature_importances_
        indices = np.argsort(importances)[::-1]

        print("\n=== 特征重要性排序 ===")
        for idx in indices:
            print(f"{self.feature_names[idx]:<10} {importances[idx]:.4f}")

该段代码对特征重要性进行降序排列生成索引序列,最后通过格式化字符串循环输出特征名称及其重要性值,实现关键特征的贡献度排序展示,为特征选择与模型可解释性分析提供量化依据

7.完整代码

from sklearn.datasets import fetch_california_housing
from sklearn.ensemble import RandomForestRegressor
from sklearn.metrics import mean_squared_error, mean_absolute_error, r2_score
from sklearn.model_selection import train_test_split
import joblib
import numpy as np


class HousingPricePredictor:
    def __init__(self, n_estimators=100, max_depth=None, random_state=42):
        """初始化随机森林回归模型"""
        self.n_estimators = n_estimators
        self.max_depth = max_depth
        self.random_state = random_state
        self.model = RandomForestRegressor(
            n_estimators=self.n_estimators,
            max_depth=self.max_depth,
            random_state=self.random_state
        )
        self.feature_names = None  # 新增特征名称存储

    def load_data(self):
        """加载房价数据并拆分为训练集和测试集"""
        data = fetch_california_housing()
        self.feature_names = data.feature_names  # 存储特征名称
        X_train, X_test, y_train, y_test = train_test_split(
            data.data, data.target,
            test_size=0.3,
            random_state=self.random_state
        )
        return X_train, X_test, y_train, y_test

    def train(self, X_train, y_train):
        """训练模型并输出训练过程数据"""
        self.model.fit(X_train, y_train)

    def evaluate(self, X_test, y_test):
        """评估模型性能并输出详细结果"""
        predictions = self.model.predict(X_test)

        # 新增多项评估指标
        mse = mean_squared_error(y_test, predictions)
        mae = mean_absolute_error(y_test, predictions)
        r2 = r2_score(y_test, predictions)

        print("\n=== 模型验证结果 ===")
        print(f"测试集样本数量: {len(X_test)}")
        print(f"均方误差(MSE): {mse:.2f}")
        print(f"平均绝对误差(MAE): {mae:.2f}")
        print(f"决定系数(R²): {r2:.2f}")

        return mse

    def save_model(self, filename="rf_model.pkl"):
        """保存模型到本地"""
        joblib.dump(self.model, filename)
        print(f"\n=== 模型已保存至 {filename} ===")

    def show_feature_importance(self):
        """显示特征重要性"""
        if self.feature_names is None:
            return

        importances = self.model.feature_importances_
        indices = np.argsort(importances)[::-1]

        print("\n=== 特征重要性排序 ===")
        for idx in indices:
            print(f"{self.feature_names[idx]:<10} {importances[idx]:.4f}")


if __name__ == "__main__":
    predictor = HousingPricePredictor(n_estimators=100, max_depth=10)
    X_train, X_test, y_train, y_test = predictor.load_data()

    # 训练流程
    predictor.train(X_train, y_train)

    # 评估流程
    mse = predictor.evaluate(X_test, y_test)


    predictor.show_feature_importance()
    predictor.save_model()

运行结果
在这里插入图片描述

8.模型调用

def predict_new_data(model_path="rf_model.pkl"):
    """加载已保存模型进行新数据预测"""
    # 加载训练好的模型
    loaded_model = joblib.load(model_path)

    # 获取特征名称(需与训练时一致)
    data = fetch_california_housing()
    feature_names = data.feature_names

    # 构造新样本数据(示例数据)
    new_samples = np.array([
        [3.8462, 52.0, 5.323529, 1.083333, 565.0, 2.194444, 37.85, -122.25],  # 示例1
        [2.5769, 25.0, 3.846154, 0.961538, 322.0, 2.555556, 34.05, -118.24]  # 示例2
    ])

    # 执行预测
    predictions = loaded_model.predict(new_samples)

    # 输出带特征解释的预测结果
    print("\n=== 新数据预测结果 ===")
    for i, (sample, pred) in enumerate(zip(new_samples, predictions)):
        print(f"\n样本{i + 1}特征明细:")
        for name, value in zip(feature_names, sample):
            print(f"{name:<15}: {value:.4f}")
        print(f"预测房价: ${pred * 100000:.2f}")  # 假设目标变量单位是10万美元

if __name__ == "__main__":
	predict_new_data()

运行结果
在这里插入图片描述

总结

随机森林凭借其独特的双重随机性(数据Bootstrap抽样与特征子集选择)和集成学习机制,在机器学习领域展现出强大的预测能力与稳定性。通过构建多棵低相关性的决策树并融合结果,该算法有效平衡了模型的准确性与泛化能力,尤其适用于高维数据、非平衡数据集等复杂场景。本文以加州房价预测为案例,完整演示了从数据加载、模型训练到评估优化的全流程。引用时只需要改输入数据集以及训练参数既可、

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值