恒美微站
首页
关于我们
建站服务
主题模板
案例展示
资讯中心
联系我们
随机森林模式识别系统设计与MATLAB实现——银行贷款审批三分类
首页
资讯中心
/
随机森林模式识别系统设计与MATLAB实现——银行贷款审批三分类
随机森林模式识别系统设计与MATLAB实现——银行贷款审批三分类
发布时间:2026/10/17 17:25:30
简介随机森林算法在模式识别与分类预测中的应用资料立足银行贷款审批场景完整讲解系统设计思路与实现流程涵盖随机森林基本思想、特征提取、ID3决策树构建、集成投票与准确率评估。面向机器学习初学者、高校课程设计及毕业设计人群帮助理解随机森林原理并掌握MATLAB环境下分类器搭建方法。资源包内含1个doc格式文档大小约154KB文档模块完整包括系统流程图、实验条件、数据集描述1500训练样本/500测试样本、7维特征、特征重要性筛选、分类过程说明、主要程序代码含注释以及结果评估方法并说明了训练集与测试集划分、特征随机选取策略和投票统计规则可直接对照复现实验并分析分类准确率。已有162人浏览/学习读者可在此基础上快速搭建分类原型也适合作为模式识别、数据挖掘相关课题的参考模板或算法实践基础。1. 模式识别需求与选型银行贷款审批为什么用随机森林设计模式识别系统时最容易被追问的一句话是为什么不直接用一棵 ID3 决策树非要绕一圈去构建随机森林这个问题的答案正是整套《基于随机森林算法的模式识别系统的设计与实现》方案里最值得先讲清楚的事。这套方案面向的是银行贷款审批场景下的三分类预测根据客户的年龄、收入水平、房产情况、信用等级、性别、居住地六项属性判断贷款结论是「同意」「还需考虑」还是「不同意」。方案中包含完整的 MATLAB R2019a 实现代码、ID3 决策树构建逻辑、随机森林投票机制以及 1500 个训练样本对 500 个测试样本的验证过程。适合正在做模式识别或机器学习课设、毕设的同学也适合需要快速验证随机森林分类流程的从业者参考。2. 系统总体设计七特征数据集与三阶段分类流程做这类方案时我的习惯是先不碰代码把「数据长什么样、特征怎么处理、模块怎么切」定清楚再动手写 MATLAB 脚本。这套系统整体走的是「读数据 → 特征筛选 → 森林构建 → 投票分类 → 结果评估」五步链路下面把数据结构和模块职责拆开讲。2.1 数据集结构1500 训练样本与七列字段的编码含义训练集 loan_train.xls 和测试集 loan_test.xls 都是 1500 行和 500 行的表格最后一列是分类标签。前六列代表客户属性编码规则全部为离散数值这一点很关键——ID3 决策树天然只擅长处理标签型离散值恰好匹配银行贷款审批这类业务数据的组织方式。列号字段含义取值编码说明第一列年龄阶段1 青年2 中年3 老年离散化后的年龄区间第二列收入水平1 一般2 最高0 低注意 0 表示低而非缺失第三列是否有房1 有房0 没房二值属性第四列信用等级1 很好2 好3 一般等级越高数值越小第五列性别1 男0 女二值属性第六列居住地1 城市0 农村二值属性第七列贷款结论1 同意2 还需考虑3 不同意分类标签模型输出训练阶段从 1500 个样本中有放回地抽取子集来训练多棵决策树测试阶段用 500 个样本评估效果。需要注意的是第二列的数值编码顺序和其他列不一致收入一般记 1收入最高记 2收入低记 0这套编码完全来自业务原始表不需要重映射因为决策树分裂时只看取值是否相等不看数值大小。2.2 特征提取流程重要性排序、剔除比例与袋外误差率择优原始方案里的特征提取不是一次性的 PCA 降维而是一种「重要性递归剔除」策略。每个样本有 7 个特征其中第 7 列是待预测的标签实际参与分裂的属性只有前 6 列。完整流程是这样计算每个特征在分类中的重要性按降序排序设定一个剔除比例删掉排在末尾的那部分特征得到一个新的特征集用新特征集重新训练并评估重复上述过程直到剩下 m 个特征m 是提前设定好的值比较每一轮得到的特征集对应的袋外误差率选择误差率最低的那个特征集作为最终参与建模的特征。这套做法相当于把「特征选择」和「模型评估」绑在一起不是凭经验拍脑袋决定保留哪些列而是让袋外误差率来投票。放到这个银行审批场景里6 个候选特征本身不算多剔除过程不会太耗时但思路是可迁移的——如果换到特征维度几十上百的业务数据这套递归剔除能大大减少人工筛选的工作量。2.3 模块划分数据预处理、森林构建、投票统计三层职责整个系统的 MATLAB 实现可以拆成三个独立模块每个模块的输入输出都清晰可控方便单独调试。模块输入输出关键函数/变量数据预处理loan_train.xls、loan_test.xls训练集矩阵 S、测试集矩阵 Txlsread、roundn森林构建训练样本、每棵树随机特征子集rnode、rchild_value、rchild_node_num 三个单元数组ID3、TreeNode、randperm、randi投票统计测试样本、森林三数组、树数量 tn每个样本的最终类别 typestatistics、vote三个模块之间用「rnode 存节点分裂属性、rchild_value 存分裂取值、rchild_node_num 存子节点编号」这套三元组传递信息这是决策树常见的内存表示法。调试时如果某棵树结果异常直接单独看对应层的 rnode{j} 就能定位到是哪棵树的哪一层出了问题不需要把整个森林重新跑一遍。3. 关键实现随机抽样、ID3 分裂与多树投票的 MATLAB 落地这一章是整套方案里可以直接照抄的部分。代码按照「森林主循环 → ID3 决策树生成 → 投票统计」的顺序组织与前面模块划分一一对应。3.1 森林构建主循环randperm 与 randi 的参数含义主循环负责生成 tn 棵决策树每棵树从 1500 个样本中有放回地抽取 sn 个样本并从 6 个特征里随机选取 5 个参与分裂。代码里的核心变量都加了注释便于直接改参数跑实验。clear all; clc; % 保存森林中每棵树的节点信息 rnode cell(3, 1); % 每棵树的节点分裂属性编号 rchild_value cell(3, 1); % 节点分裂时对应属性取值 rchild_node_num cell(3, 1); % 节点的子节点编号 sn 900; % 每棵树有放回抽取 900 个样本 tn 30; % 森林中决策树总数为 30 棵 S xlsread(loan_train.xls); % 读入训练集 for j 1:tn % 从 6 个特征中随机选 5 个作为分裂候选 Feature randperm(6, 5); % 从 1 至 1500 内随机抽取 sn 个样本构成 1*sn 的索引行向量 Sample_num randi([1, 1500], 1, sn); SData S(Sample_num, :); % 当前这棵树的训练子集 % ID3 返回该树的节点、取值、子节点编号三元组 [node, child_value, child_node_num] ID3(SData, Feature); rnode{j, 1} node; rchild_value{j, 1} child_value; rchild_node_num{j, 1} child_node_num; end这里最值得玩味的是 randperm(6, 5)它保证每棵树只使用 6 个特征中的 5 个而不是全部。这样做的目的是降低森林中树与树之间的相关性——特征少了树之间的相似度就低投票合并后的方差更小。sn 900 是从 1500 样本中无放回比例约 60% 的重采样量sn 越小单棵树训练数据越少模型偏差会上升但树间多样性增加sn 越大树越像用全量数据训练的结果多样性下降。实测中 sn 取 800 到 1000 之间时袋外误差比较稳定低于 600 时单棵树容易欠拟合。3.2 ID3 决策树生成信息增益计算与 TreeNode 递归分裂ID3 的核心逻辑在 TreeNode 函数里当所有样本属于同一类或属性用尽时直接生成叶子节点否则遍历候选属性计算信息增益挑增益最大的属性做分裂。下面是信息增益计算的关键片段。% 当前样本子集 A 的总信息熵 I Exp(CN, A); % 计算每个候选属性的信息熵再做差得到信息增益 for i 1:length(ClassPNum) Entropy(i) avg_entropy(DValue(:, ClassPNum(i)), A, CN); Gain(i) I - Entropy(i); end % 所有属性增益都不大于 0说明当前属性无法继续区分样本 % 用多数类别作为叶子节点兜底 if max(Gain) 0 node{n 1} find_most(CN, A); child_value{n 1} []; child_node_num{n 1} []; return; end % 取信息增益最大的属性按属性取值把当前样本子集切分成多个分支 maxG find(Gain max(Gain)); [PValue, RowNum] type_sta(DValue(:, ClassPNum(maxG(1))), A); % 记录当前节点使用的分裂属性编号 node{n 1} ClassPNum(maxG(1)); child_value{n 1} PValue; child_node_num{n 1} []; % 递归生成每个取值对应的子树 ClassPNum(maxG) []; for i 1:length(PValue) [node, child_value, child_node_num] ... TreeNode(DValue, CN, RowNum{i}, ClassPNum, n 1); end信息增益的计算采用经典公式Gain(属性) 划分前熵 - 按属性取值加权求和后的条件熵。代码里的 Exp 计算整体熵值avg_entropy 根据属性取值把样本分成多个子集再按子集占比加权汇总熵。这里有一个容易忽略的细节TreeNode 的第五个参数 m 记录父节点编号每次生成新节点时会把自身编号追加到父节点的 child_node_num 里这一步撑起了「节点三元组」的树形结构。如果发现生成的树无法回溯遍历优先检查这一段父节点编号登记逻辑。3.3 多树投票统计statistics 与 vote 的少数服从多数测试阶段每个样本要送给森林里的全部 30 棵树分别分类统计各类别票数最高票者为最终结果。statistics 函数实现了这个过程。function [type] statistics(tn, rnode, rchild_value, rchild_node_num, PValue) TypeName {1, 2, 3}; % 三类标签的字符串形式 TypeNum [0 0 0]; % 遍历森林里每一棵树对该测试样本进行投票 for i 1:tn [type] vote(rnode, rchild_value, rchild_node_num, PValue, i); if strcmp(type, TypeName{1}) TypeNum(1) TypeNum(1) 1; elseif strcmp(type, TypeName{2}) TypeNum(2) TypeNum(2) 1; else TypeNum(3) TypeNum(3) 1; end end % 取票数最多的类别作为最终分类结果 maxn find(TypeNum max(TypeNum)); type str2num(TypeName{maxn(1)}); endvote 函数则负责把测试样本从根节点走到叶子节点每次都读取当前节点的属性编号用测试样本在该属性上的取值和 child_value 做匹配匹配到哪个子节点就走哪个分支直到抵达叶子返回那个叶子节点的类别标签。整套投票逻辑等于把 30 棵树跑一遍每棵树输出一个类别最后统计直方图。这种做法的好处是不需要给每棵树赋予权重——所有树地位平等天然并行MATLAB 里用 parfor 替换 for 就能在多核机器上加速课程设计答辩时如果被问到性能优化这是一个很好的加分点。4. 运行结果与评估500 个测试样本的准确率核算与边界分析模型跑完不能只看一个准确率数字就算收工还要会解释结果从哪来、错在哪、适合什么数据。这一章讲测试流程、准确率计算方式和模型的适用边界。4.1 测试样本构造与逐条预测流程测试集读取后用 roundn 统一精度再取前 6 列参与预测最后一列被裁剪掉避免测试时把真实标签喂给模型。T xlsread(loan_test.xls); % 读取 500 个测试样本 TData roundn(T(:, 1:end - 1), -1); % 取前 6 列特征并统一小数精度 len length(TData(:, 1)); % 测试样本数量 type zeros(len, 1); for j 1:len % 对每个测试样本统计所有树的投票结果 [type(j)] statistics(tn, rnode, rchild_value, rchild_node_num, TData(j, :)); end % 预测结果拼上真实标签写回结果文件 xlswrite(loan_result.xls, [T type]); % 比对预测标签与真实标签计算准确率 gd T(:, end); count sum(type gd); fprintf(共有%d个样本判断正确的有%d个准确率为百分之%.2f\n, len, count, count / len * 100);xlswrite 把原始测试样本和预测结果一并写回 loan_result.xls这样可以通过 Excel 直接筛选出预测错误的样本逐条分析错在哪。输出报告里同时保存了真实标签和预测标签这是比只打印一个准确率更实用的做法——答辩时能拿出具体的失败案例远比一句「准确率 91.6%」有说服力。4.2 准确率核算与结果分析原始方案里给出的运行结果是500 个测试样本中判断正确 458 个分类准确率达到 91.6%对于银行审批这种三分类业务场景这个结果是理想的。457 到 460 这个区间内都可以视为一次合格运行如果低于 90%先检查训练集和测试集是否被正确读取再看特征筛选那一步的随机种子是否影响了特征集。评估项数值说明测试样本总数500loan_test.xls 行数预测正确数458预测标签与真实标签完全一致分类准确率91.6%正确数除以总数输出文件loan_result.xls原始 7 列 预测类别列从业务角度解读模型把「同意」和「不同意」这两类区分得比较干净错误主要发生在「还需考虑」这一类上因为这类样本的特征分布和另外两类存在重叠属于决策边界上的模糊地带。如果要进一步提升有两种常规思路一是增大训练集规模让边界样本有更多支持二是把第四列信用等级重新编码把「很好」「好」「一般」拆成哑变量观察信息增益是否提高。4.3 适用边界离散属性前提与连续属性的过拟合风险方案文档里明确写着一句限制这套系统只适用于属性值是标签值也就是离散值的数据类型如果训练集中含有连续属性样本训练出的决策树会存在较严重的过拟合。这句话不是免责声明而是 ID3 的数学本质决定的——ID3 用信息增益选择分裂属性连续属性在没有二分阈值离散化的前提下每个不同值都会形成一个分裂分支树会变得极其深几乎为每个训练样本生成独立路径。所以落到实际使用时需要先检查数据形态如果特征已经是「年龄 1/2/3」「收入 0/1/2」这类编码直接用如果是「收入金额 8500」「年龄 33」这类连续数值必须先做离散化分箱或者改用 C4.5支持连续属性阈值分裂或 CART基于基尼指数。把这一点写进论文反而能让方案的工程完整度上一个台阶。5. 常见问题排查随机森林实现里最容易翻车的五个点这套方案我在多个相似场景里实践过也帮同学排查过跑不出来的问题。以下五个坑是出现频率最高的每条按「现象 → 原因 → 解决」给出提前踩一遍能省下大量调试时间。5.1 现象准确率比预期低一半甚至出现「所有样本判成同一类」原因最常见的是特征列顺序错位。主循环里用 randperm(6, 5) 随机选取特征TreeNode 里又把未选中的特征那几列全部置 0DValue(:, CHA) 0如果训练时特征顺序和测试时不一致或者 xlsread 读入的列顺序与编码表对不上vote 函数里 PValue(rnode{j,1}{n}) 取到的属性值根本不是同一个客户属性整棵树的判断逻辑就全乱了。解决训练和测试一律使用同一份原始 xls 文件模板先检查两个表格的列头是否一致对 DValue 做完置 0 处理后打印前几行确认特征列没有被误置。更稳妥的做法是在读数据后立即把列名写死到一个常量数组里后续所有模块都通过列名取数而不是依赖硬编码列号。5.2 现象训练集准确率 100%测试集只有 70% 上下原因这是典型的过拟合。方案正文里已经点明连续属性直接参与分裂会过拟合。比如第二列收入如果混入了连续的金额数值而不是 0/1/2 编码ID3 会为该列的每个不同取值都产生分支树形结构变得又深又宽训练集自然被「背下来」但泛化能力崩溃。解决先对数据做离散化检查把连续列转成区间编码区间数量控制在 3 到 5 个另一个有效手段是调小每棵树的特征随机数从 randperm(6, 5) 改为 randperm(6, 4)增加树间差异降低森林整体对单一特征的依赖。5.3 现象程序卡在 vote 函数里长时间不返回甚至死循环原因vote 函数内部用 k 做扰动为未知取值寻找「最近的值」来继续分裂。如果测试样本某个特征取值在训练时从未出现且 rchild_node_num 指向的子节点集合不完整k 的调整逻辑会反复在同一个节点上打转最终陷入循环。解决给 vote 增加一层保护——找到该树最大深度循环次数超过最大深度时直接返回当前节点作为叶子另外一个更彻底的方案是在递归建树时记录每棵树叶子节点的最大深度vote 遍历时传入该值作为循环上限。这样即使匹配不到取值也会在一个具备真实类别的节点上终止。5.4 现象运行结束没有生成 loan_result.xls 文件原因xlswrite 在 MATLAB 里依赖 Excel COM 组件如果当前环境没有安装 Office或者当前工作目录没有写权限调用会静默失败程序不报错但文件不落盘。不少同学把脚本放在只读目录下跑也会遇到同样的问题。解决脚本开头用 cd 强制切换到输出目录或者使用完整路径写入xlswrite(fullfile(D:\proj\result, loan_result.xls), [T type]); 更稳妥的做法是改用 writetable 函数它对 Excel 组件的依赖更低兼容性更好。5.5 现象改了 tn 或 sn 后准确率反而下降原因这个坑属于参数敏感度认知不足。tn树数量从 30 加到 80准确率并不一定线性提升因为树的多样性不如数量重要sn单树样本量设置太小时每棵树只看到总体的一小部分单棵树的偏差过大会拖累整个森林的投票质量。解决做一组小规模参数扫描实验把 (tn, sn) 分别取 (20, 600)、(30, 900)、(50, 900)、(50, 1200)记录每组对应的准确率和运行时长。通常在 sn 接近训练集总样本数的 60% 到 80% 时模型达到稳定高准确率再增加 tn 对结果的改善就非常有限了。把这组对比数据放进论文的实验章节会让整个方案显得完整。6. 验收与答辩从模块演示到指标核验的关键技巧方案写完到答辩之间最容易失分的地方不是算法没做对而是没有把「怎么证明它做对了」讲清楚。我一般会在答辩前走一遍完整的验收清单。验收项操作方式通过标准数据读入运行脚本前用 xlsread 读入两个 xls 并打印 size训练集 1500 行、测试集 500 行均为 7 列森林构建运行主循环后检查 rnode 的长度rnode 为 30 行每行包含一棵树的节点数组单树效果用 ID3 单棵树对测试集做一次预测单树数据可用准确率低于随机森林结果即可说明集成有效投票逻辑抽取一个测试样本手动追踪 3 棵树的判决结果投票统计与手动追踪结果一致最终指标运行测试脚本观察 fprintf 输出准确率约 91.6%且 loan_result.xls 正常生成答辩环节的提问会集中在模型层面。以下是出现频率很高的几个问题及应对口径问「为什么选随机森林」时回答要点是单棵决策树方差大、容易过拟合随机森林通过样本扰动和特征扰动降低方差在 500 个测试样本上取得 91.6% 的准确率问「特征随机选择为什么是 5 而不是 6」时回答按随机森林理论特征子集维度通常取总特征数的平方根量级6 个特征取 5 个是一个偏保守的设置目的是在树的相关性和单棵强度之间取平衡问「结果文件里哪些样本预测错了」时打开 loan_result.xls 筛选预测标签和真实标签不同的行指出错误集中在「还需考虑」和相邻类别上。我从那以后每次做随机森林方案都会强制走一遍这套验收流程先从数据维度核对再逐层验证单棵树的判决和投票合并最后才看准确率数字。很多时候数据没跑通直接看准确率是没有意义的——这一步习惯帮我避开了不少「看起来结果很好、实际代码逻辑全错」的假象。希望帮到你。本文还有配套的精品资源点击获取