简介随机森林多输入回归预测是机器学习中常用且稳健的建模方法适合需要同时处理多个自变量与单一因变量关系的工程、金融、生物医学等场景。该资源面向MATLAB用户及想要掌握RF回归建模的中级学习者提供一套可直接运行的完整源码与配套数据可快速理解从数据预处理、Bootstrap抽样、特征随机选择到多棵决策树集成预测的完整流程。压缩包内共7个文件涵盖1个m主程序、1个Excel数据集、1个Word说明文档及4个PNG结果图整体大小约360KB结构精简便于对照学习。目前已有5096人浏览学习说明该示例具备较强的参考价值。通过主脚本可查看数据读取、模型训练、预测评估等关键实现步骤并可借助图形结果分析特征重要性、残差分布和拟合效果。文档对随机森林原理与回归评估指标进行了说明适合作为课程设计、论文实验或入门实践的参考资料便于读者快速复现并迁移到自己的数据集上。1. 随机森林多输入回归预测MATLAB 里为什么先别急着上神经网络做多输入回归预测先别急着搭 BP 神经网络。样本量只有几百条、特征又带共线性时MATLAB 里的随机森林往往更早给出稳定结果。它不需要归一化不假设数据分布训练完还能直接输出特征重要度这几条特性让随机森林回归模型成了快速验证预测假设的首选。所谓多输入回归预测就是一行样本对应多个特征和一个目标值随机森林靠装袋采样加特征随机抽样集成决策树取平均天然适合这种输入输出关系不明朗的任务。这篇文章把数据准备、训练测试集划分、fitrensemble 与 TreeBagger 两套建模源码、参数调优、R² 和 RMSE 计算、特征重要度到模型保存整条链路拆开讲代码拼接起来就是完整源码不依赖第三方工具箱R2019b 以上版本可直接运行。适合手里已有多列输入和一列目标值、想在 MATLAB 里快速拿到随机森林回归预测结果的人也适合被 BP 网络训练时间困扰、想先确认树模型精度的工程师。全文围绕回归场景展开不涉及分类。2. 随机森林多输入回归预测的数据准备从 CSV 到 MATLAB 训练集2.1 多输入数据的标准组织特征矩阵与目标向量随机森林在 MATLAB 里可以吃 double 矩阵也可以吃 table。多输入回归预测的标准摆放方式是每一行一个样本前面若干列是输入特征最后一列是目标值。比如 5 个输入维度、800 条样本原始数据就是一个 800×6 的矩阵前 5 列记作 X第 6 列记作 Y。动手训练之前先确认这个约定后面的 fitrensemble 调用和数据划分全都依赖它。如果手上暂时没有现成数据可以用这段代码生成一份带非线性关系的测试数据先把流程完整跑通再替换成自己的数据% 生成测试数据5 个特征 1 个目标写入 CSV rng(42); X rand(800, 5); Y 2*X(:,1) - 1.5*X(:,2).^2 sin(X(:,3)) 0.05*randn(800,1); writematrix([X Y], sample_data.csv);Y 的表达式里同时有线性项、平方项和正弦项再叠加一个小幅噪声正好考验随机森林对非线性回归关系的拟合能力。rng(42) 保证每次生成的 X 和 Y 完全一致复现实验时不会出现数据漂移。读回 CSV 时readmatrix 和 readtable 的选择取决于你是否需要保留变量名% 无表头纯数值文件readmatrix 直接返回 double 矩阵 data readmatrix(sample_data.csv); X data(:, 1:end-1); Y data(:, end); % 带表头文件readtable 保留变量名便于画图和特征标注 T readtable(sample_data_with_header.csv); featureNames T.Properties.VariableNames(1:end-1); X T{:, 1:end-1}; Y T{:, end};readmatrix 对纯数值文件最快遇到文本表头会自动跳过但不会保留名字readtable 则把列名存在 VariableNames 里。后文用 oobPermutedPredictorImportance 给特征排序时没有名字对照就只能看到一堆索引所以即使源文件无表头我也建议手工维护一份 featureNames 元胞数组featureNames {temp, pressure, flow, vibration, speed};2.1.1 样本量的最低要求随机森林对样本量的需求不像深度学习那么贪婪但回归树的叶子节点需要有足够样本做平均。经验值是样本量不少于特征数的 5 到 10 倍最少 200 条起步。样本太少时单次划分的测试集 R² 方差很大这时候不要急着下结论改用第 4 章的交叉验证来汇报泛化误差。2.2 训练集与测试集划分randperm 与固定随机种子数据划分这一步最常踩的坑是不设随机种子。随机森林训练本身就要做大量有放回抽样如果数据集划分也没锁随机性两次运行同一段代码R² 差出 0.1 都很正常排错根本无从下手。rng(42); % 固定随机种子保证划分可复现 idx randperm(size(X, 1)); % 打乱样本序号 nTrain round(0.8 * size(X, 1)); Xtrain X(idx(1:nTrain), :); Ytrain Y(idx(1:nTrain)); Xtest X(idx(nTrain1:end), :); Ytest Y(idx(nTrain1:end));randperm 返回打乱后的行号前 80% 做训练、后 20% 做测试。固定 rng(42) 之后无论重复多少次划分结果都一致调参时横向对比模型才有意义。想用更规范的交叉验证结构可以换成 cvpartitioncv cvpartition(size(X, 1), HoldOut, 0.2); Xtrain X(training(cv), :); Ytrain Y(training(cv)); Xtest X(test(cv), :); Ytest Y(test(cv));cvpartition 的好处是支持 KFold 选项后面调参时能直接传给 fitrensemble 的 CVPartition 参数保证每次实验用的是同一样本分组。HoldOut 划分适合最终评估阶段KFold 适合调参阶段。同一个测试集不要反复用来做模型选择否则测试集信息会渗入决策过程最终报告的 R² 会虚高。我实际项目里的习惯是先用 5 折交叉验证选参数参数定下来后再用 HoldOut 的测试集做一次性最终评估。2.3 缺失值与类别特征随机森林对输入数据的隐性要求fitrensemble 配合默认的 templateTree 遇到 NaN 通常会直接报错所以训练前必须处理缺失值。最常见做法是按列均值填充for j 1:size(X, 2) colMean mean(X(:, j), omitnan); X(isnan(X(:, j)), j) colMean; end均值填充会略微压缩该列方差如果某一列缺失比例超过 30%填充不如直接删掉这一列特征。离散型类别特征不要随手编码成 0、1、2 塞进数值矩阵MATLAB 的随机森林原生支持类别型特征正确做法是转 categorical 后用 table 训练T readtable(sample_data.csv); T.WorkMode categorical(T.WorkMode); % WorkMode 是类别列 rfModel fitrensemble(T, Y, ... Method, Bag, ... CategoricalPredictors, WorkMode);量纲差异在随机森林里不是问题分裂只依赖特征值的阈值比较不需要归一化。但如果某一列的数量级比其他列高出好几个数量级先怀疑是脏数据不要指望模型自适应消化。数据情况处理方式说明数值缺失列均值填充缺失超 30% 建议删列类别特征categorical() 转换配合 CategoricalPredictors量纲差异大不处理分裂基于阈值比较列顺序与训练时保持一致predict 按列位置匹配3. MATLAB 随机森林建模完整源码fitrensemble 与 TreeBagger 两条路径3.1 fitrensemble当前主流的随机森林回归建模接口fitrensemble 是 Statistics and Machine Learning Toolbox 里做集成学习的标准入口。构建随机森林的关键是 Method 选 BagLearners 用 templateTree 定义单棵回归树的结构。rng(42); t templateTree(MinLeafSize, 5); % 叶节点最小样本数 rfModel fitrensemble(Xtrain, Ytrain, ... Method, Bag, ... NumLearningCycles, 300, ... Learners, t);训练过程分两步templateTree 先定义单棵树的分裂约束fitrensemble 再通过 Bagbootstrap aggregating把多棵树组装成随机森林。Method 为 Bag 时每棵树从训练集有放回抽样同时每个分裂节点只随机抽取部分特征寻找最佳切分点这正是随机森林区别于普通装袋的核心。训练完成后 rfModel 是 RegressionBaggedEnsemble 对象直接传给 predict 就能对新样本打分。MinLeafSize 控制树的复杂度。决策树不剪枝时叶子节点可能只剩一两个样本训练集拟合得很好但测试集方差极大。MinLeafSize 限制叶子节点至少包含的样本数值越大树越浅、模型越平滑。几百条样本的多输入回归任务从 5 开始调范围 1 到 20 都常见样本量上千时可以放大到 10 以上训练速度会明显变快。如果 X 是普通 double 矩阵类别特征已单独拆出可以用列号索引或逻辑向量指定 CategoricalPredictors% 逻辑向量长度必须与特征列数一致 isCategorical [false, true, false, false, false]; rfModel fitrensemble(Xtrain, Ytrain, ... Method, Bag, ... CategoricalPredictors, isCategorical);这里顺序对应的是输入矩阵的列位置不是特征名字。写错列的后果是模型把类别编码当成连续值去切分训练不报错但预测精度会下降排查起来比较隐蔽。另外观察训练集和测试集的指标差距也能判断树是否足够随机森林的训练误差会随树数量趋近一个下界测试误差先降后平。如果两者之间始终隔着一大截优先怀疑是某个特征泄露了目标信息而不是树不够多。3.2 TreeBagger老接口反而更好观察袋外误差TreeBagger 是比 fitrensemble 更早的接口多输入回归的调用方式如下rf TreeBagger(300, Xtrain, Ytrain, ... Method, regression, ... MinLeafSize, 5, ... OOBPrediction, on, ... NumPredictorsToSample, ceil(size(Xtrain, 2) / 3));TreeBagger 第一个位置参数直接是决策树数量Method 必须显式写成 regression。NumPredictorsToSample 控制每个分裂节点随机抽样的特征数回归任务一般取特征总数的三分之一。OOBPrediction 设为 on 后训练过程同步计算袋外误差训练完立刻能画曲线判断当前树数量是否够用figure; plot(oobError(rf)); xlabel(树的数量); ylabel(袋外均方误差);曲线还在明显下降说明树不够继续加到进入平台期为止。这是 TreeBagger 在调试阶段最顺手的地方fitrensemble 里要拿 oobLoss 得重新训练才能得到类似曲线。两个接口的选择参考下表对比项fitrensembleTreeBagger树数量入口NumLearningCycles 参数第一个位置参数袋外误差oobLoss 需重新评估训练时同步记录交叉验证KFold 原生支持需手动划分自动调参OptimizeHyperparameters不支持预测接口predict(模型, X)predict(模型, X)3.3 完整源码骨架数据、训练、预测三段式拼接把前面几段代码连起来就是一份可运行的完整源码结构上分成数据、训练、预测三段每一段都可以单独替换成前面讲过的变体%% 段 1数据准备 data readmatrix(sample_data.csv); X data(:, 1:end-1); Y data(:, end); rng(42); idx randperm(size(X, 1)); nTrain round(0.8 * size(X, 1)); Xtrain X(idx(1:nTrain), :); Ytrain Y(idx(1:nTrain)); Xtest X(idx(nTrain1:end), :); Ytest Y(idx(nTrain1:end)); %% 段 2训练随机森林 t templateTree(MinLeafSize, 5); rfModel fitrensemble(Xtrain, Ytrain, ... Method, Bag, ... NumLearningCycles, 300, ... Learners, t); %% 段 3预测与保存 Ypred predict(rfModel, Xtest); save(rfModel.mat, rfModel);这段骨架里没有任何第三方函数R2019b 以上的 MATLAB 自带运行环境就能跑通。predict 不接受含 NaN 的行新数据进来之前要做和训练数据完全相同的缺失值填充和类型转换。如果训练时用了 table预测时也要构造同结构的 table列名不要求一致但列数和顺序必须相同。4. 随机森林回归预测调参NumLearningCycles、MinLeafSize 与评估指标随机森林回归算法在 MATLAB 里的参数集中在 fitrensemble 的 Name-Value 对中但真正影响多输入回归预测结果的只有四类。逐个理解它们的含义比盲目套默认值有效得多。4.1 决定回归精度的四个核心参数参数作用默认值推荐范围NumLearningCycles决策树数量越多越稳定100100~1000MinLeafSize叶节点最小样本数控制过拟合11~20NumPredictorsToSample每个分裂节点随机抽样的特征数约 p/3p 为特征数sqrt(p) ~ p/3Surrogate代理分裂处理训练数据里的缺失值off无缺失保持 off树数量从 100 加到 1000精度提升通常不到 0.01训练时间却接近线性增长所以先按 300 跑通再看 OOB 曲线决定是否加树。MinLeafSize 与样本量强相关样本量小于 500 时1 和 5 的差距可能很明显样本量大于 5000 时这个参数的影响会被树数量稀释。NumPredictorsToSample 默认约 p/3特征维度很高且存在大量冗余时下调到 sqrt(p) 附近能让每棵树更随机抑制过拟合。Surrogate 平时不用动它是在特征缺失时找替代分裂变量用的开启后训练时间成倍增加只有生产数据天然带缺失且不愿填充时才值得打开。4.2 R²、RMSE 与 MAE三个回归指标一次算齐回归预测的评估不能只看一个数。R² 表示模型解释的方差比例RMSE 对大误差敏感MAE 反映平均绝对偏差三个指标放一起才能判断误差是分散的还是集中在个别样本上。Ypred predict(rfModel, Xtest); SSres sum((Ytest - Ypred).^2); SStot sum((Ytest - mean(Ytest)).^2); R2 1 - SSres / SStot; RMSE sqrt(mean((Ytest - Ypred).^2)); MAE mean(abs(Ytest - Ypred)); fprintf(R2 %.4f, RMSE %.4f, MAE %.4f\n, R2, RMSE, MAE);如果 R² 不错但 RMSE 明显大于 MAE说明大部分样本预测尚可少数样本误差很大重点排查这些异常样本是不是落在了训练数据没有覆盖的取值区间。反过来 R² 很低、RMSE 和 MAE 接近说明模型整体偏移先检查目标值 Y 是否需要 log 变换或者存在量纲问题再考虑调参。画真实值与预测值的对比图是判断系统偏差最直接的手段figure; plot(Ytest, o); hold on; plot(Ypred, -); legend(真实值, 预测值, Location, best); xlabel(样本序号); ylabel(目标值);如果预测曲线整体滞后于真实曲线多半是特征里缺少时间相关变量。如果只是个别尖峰没预测到那是随机森林分段常数输出的固有局限。散点图呈现漏斗形、预测值越大误差越大时说明目标变量存在异方差可以对 Y 做对数变换后再训练预测时用 exp 还原随机森林对目标值的单调变换是敏感的。4.3 网格搜索加交叉验证参数组合自动筛选MinLeafSize 和树数量对结果的影响不是独立的小 MinLeafSize 需要更多树来稳定方差。所以调参至少两两组合一起搜fitrensemble 支持直接传 KFold 做交叉验证minLeafList [1 5 10 20]; numTreesList [100 300 500]; for ml minLeafList for nt numTreesList t templateTree(MinLeafSize, ml); mdl fitrensemble(Xtrain, Ytrain, ... Method, Bag, ... NumLearningCycles, nt, ... Learners, t, ... KFold, 5); cvRMSE sqrt(kfoldLoss(mdl, Mode, individual)); fprintf(MinLeaf%3d, Trees%4d, CV-RMSE%.4f ± %.4f\n, ... ml, nt, mean(cvRMSE), std(cvRMSE)); end endkfoldLoss 的 Mode 设为 individual 时返回每一折的损失mean 和 std 一起看。只看均值容易选到方差极大的参数组合模型换个数据段精度就崩。网格搜索选出最优参数后用全量训练集重训一份最终模型再对测试集做一次独立评估不要把交叉验证的结果直接当成测试集结论。提示两个参数组合的均值相近时选 std 更小的那个部署稳定性比单点精度更重要。12 组参数打印出来之后建议把这 12 行记录成表格对比或者把 mean 和 std 存进矩阵用 heatmap 画一张参数响应面图树数量放横轴、MinLeafSize 放纵轴、颜色表示 CV-RMSE最优区域一眼就能看出来。如果参数空间更大、单次训练时间更长可以直接交给贝叶斯优化rfModel fitrensemble(Xtrain, Ytrain, ... Method, Bag, ... OptimizeHyperparameters, {NumLearningCycles, MinLeafSize}, ... HyperparameterOptimizationOptions, struct( ... MaxObjectiveEvaluations, 30, ... AcquisitionFunctionName, expected-improvement));样本量小时网格搜索十几分钟就能跑完结果还好向同事解释贝叶斯优化更适合特征上百维、单次训练就要几分钟的大数据集。自动调参返回的模型已经用最优参数训练过可以直接用于预测但建议把优化过程选出的参数值打印出来存档方便复现和向别人说明最终模型是怎么来的。5. 特征重要度排序与模型保存随机森林回归预测的交付技巧5.1 用 oobPermutedPredictorImportance 做特征筛选fitrensemble 训练出的随机森林可以用 oobPermutedPredictorImportance 计算袋外置换重要度。原理是逐个打乱袋外样本的某一列特征观察预测误差的增幅增幅越大说明模型越依赖这个输入。imp oobPermutedPredictorImportance(rfModel); [~, order] sort(imp, descend); for k 1:min(10, numel(order)) fprintf(%2d. %s : %.4f\n, k, featureNames{order(k)}, imp(order(k))); end重要度排序有两个实际用途。一是直接定位哪些输入对回归目标影响最大给业务方提供可解释依据二是做特征筛选把重要度接近零的特征删掉重训精度通常持平但训练时间和过拟合风险都下降。筛选后重训前务必重新核对 featureNames 与新数据矩阵的列对应关系排序索引错位是这类操作里最常见的低级错误。注意TreeBagger 对应的方法是 predictorImportance(rf)两者计算口径不完全一致横向对比不同模型时不要混用指标。5.2 模型保存、加载与批量预测随机森林模型可以直接存成 .mat 文件换会话或交给下游时不需要重新训练save(rf_model.mat, rfModel); loaded load(rf_model.mat); newPred predict(loaded.rfModel, newX);批量预测多个 CSV 文件时predict 的输入列数必须与训练时完全一致。如果训练时用了 table 并指定了 CategoricalPredictors预测时也要构造同类型 table最常见的报错是训练集删过列、新数据没删维度对不上。把预测结果落成 CSV 是交付的标准收尾result table(Ytest, Ypred, ... VariableNames, {Actual, Predicted}); result.AbsError abs(result.Actual - result.Predicted); writetable(result, rf_predictions.csv);如果训练时开了 KFold保存下来的对象会带着折内模型和交叉验证中间产物.mat 文件体积明显偏大。部署前用 compact 压缩成正式交付模型compactModel compact(rfModel); save(rf_model_compact.mat, compactModel);compact 会去掉训练数据引用和交叉验证信息文件体积通常能缩到原来的十分之一左右predict 数值结果完全不变。用 compactModel 接替 rfModel 时预测接口不需要任何改动下游调用方只认 .mat 文件名和 predict 的返回值。本文还有配套的精品资源点击获取