
简介这份资源是面向环境科学、数据分析方向的学生与科研人员的MATLAB决策树空气质量分析源码包可用于构建AQI等级分类预测模型适合课程设计、毕业设计及小论文写作等场景。压缩包共150个文件约14.21MB包含58个m脚本文件、51张jpg结果图、14个mat数据文件以及pdf说明文档、xlsx与xls数据表、fig图形文件、docx论文文档和md说明等覆盖从数据处理、模型训练到结果可视化的完整流程。资源中附带多份论文文档与决策树结构图、ROC曲线图等便于读者对照理解建模思路与评估方法。目前已有51人学习下载适合希望快速上手MATLAB分类算法、完成空气质量分析课题的初学者与进阶学习者参考。1. 从一份 MATLAB 决策树源码说起空气质量数据到底该怎么建模手里拿到一份「matlab基于决策树的空气质量分析源码.zip」多数人的第一反应是解压、打开、点运行然后盯着命令行窗口等结果。但真正决定这份源码能不能用、结果可不可信的不是代码写得多花哨而是你有没有搞清楚它到底在解决一个什么形态的问题。空气质量分析在工程上通常不是单纯的回归预测而是把 AQI 等级、污染等级、是否超标这类离散标签分出来这就天然适合决策树分类器。它输出的是一棵可以打印、可以讲给非技术同事听的规则树而不是一个黑匣子权重矩阵这一点在环保、园区监测、城市看板这类场景里非常关键。这份源码适合三类人一是做课程设计或毕设、需要一套能跑通全流程的 MATLAB 工程二是做环境数据方向、想快速验证特征重要性的从业者三是已经会 Python 的 sklearn 决策树、但需要在 MATLAB 生态里复现同样逻辑的工程师。它解决的核心诉求是把一份带时间戳和多污染因子列的监测数据变成一棵可解释的分类树并给出准确率、混淆矩阵和特征重要性。接下来我会按「数据怎么进、树怎么长、参数怎么调、坑在哪」的顺序把这类源码的落地路径拆开讲清楚让你拿到手就能改、改完就敢用。2. 空气质量数据进决策树之前特征工程与标签定义2.1 为什么原始监测表不能直接喂给 fitctree常见的空气质量原始数据长这样一行是一个小时或一天列包含 PM2.5、PM10、SO2、NO2、CO、O3、温度、湿度、风速、气压外加一个 AQI 值或等级。很多人直接把所有数值列丢进fitctree结果准确率虚高但一换数据就崩。问题出在两点一是标签泄漏AQI 本身就是由这些污染物算出来的用它当特征等于作弊二是量纲差异CO 常在 0.5 到 5 之间PM2.5 能到几百决策树虽然对量纲不敏感但分裂点搜索会被大数值列主导导致树偏向某几个特征。我一般会先做三件事把 AQI 数值按国标阈值离散成「优、良、轻度污染、中度污染、重度及以上」五类作为标签把与标签强相关的原始 AQI 列从特征里剔除对风速、温度这类气象列做缺失值填充。下面这段是典型的预处理骨架可以直接套。% 读取监测数据假设第一列是时间最后一列是AQI数值 raw readtable(air_quality.csv); % 按AQI阈值离散化标签阈值参考常用分级 aqi raw.AQI; label strings(height(raw),1); label(aqi 50) 优; label(aqi 50 aqi 100) 良; label(aqi 100 aqi 150) 轻度污染; label(aqi 150 aqi 200) 中度污染; label(aqi 200) 重度及以上; % 构造特征矩阵剔除AQI本身和时间列 featNames {PM25,PM10,SO2,NO2,CO,O3,Temp,Humidity,WindSpeed}; X raw(:, featNames); % 缺失值用列中位数填充避免删除整行丢样本 for i 1:width(X) col X{:,i}; col(isnan(col)) median(col,omitnan); X{:,i} col; end这段代码的逻辑是先离散标签再切特征最后填缺失。参数上AQI 阈值不是随便定的不同地区标准略有差异你要按自己数据来源的分级口径改。median(...,omitnan)是关键直接median遇到 NaN 会返回 NaN整列就废了。特征名列表要和表头严格对应MATLAB 的 table 列名大小写敏感写错一个就报未定义变量。2.2 特征筛选用相关性先砍一轮再交给树决策树自己能做特征选择但不代表你可以把所有列都塞进去。特征太多会让树过拟合尤其样本量只有几百到几千条时。我的习惯是先算一遍特征与标签的互信息或简单相关性把明显无关的列去掉再让树去挑。MATLAB 里可以用fscmrmr做最小冗余最大相关排序也可以用corr看数值相关。下面这段给出一个可复现的筛选流程。% 把标签转成类别型供特征排序函数使用 Y categorical(label); % 用MRMR算法给特征打分排序 [idx, scores] fscmrmr(X, Y); % 打印排序结果人工确认保留哪些 for i 1:numel(idx) fprintf(%s: %.4f\n, featNames{idx(i)}, scores(i)); end % 保留得分前6的特征作为最终输入 topK 6; Xsel X(:, idx(1:topK));fscmrmr返回的idx是按重要性从高到低排的特征索引scores是对应得分。参数topK怎么定没有绝对标准我一般看得分曲线的拐点前几个得分断崖式下降就取断崖前。样本少于 500 条时我会更保守取 4 到 5 个特征。这一步做完后面建树会稳很多也更容易解释。3. 用 fitctree 建一棵能解释的空气质量分类树3.1 最小可运行建树命令与参数含义MATLAB 里做决策树分类的主函数是fitctree它对应 Python sklearn 的DecisionTreeClassifier。一份典型源码里最核心的就是这一行但参数怎么设决定了树是「能用」还是「能用且可信」。先看最小可运行版本。% 划分训练集和测试集固定随机种子保证可复现 rng(42); cv cvpartition(Y, HoldOut, 0.3); Xtrain Xsel(training(cv), :); Ytrain Y(training(cv)); Xtest Xsel(test(cv), :); Ytest Y(test(cv)); % 训练决策树设置分裂准则和最小叶节点样本数 tree fitctree(Xtrain, Ytrain, ... SplitCriterion, gdi, ... MinLeafSize, 5, ... MaxNumSplits, 30, ... Prune, on); % 在测试集上预测 Ypred predict(tree, Xtest); % 输出混淆矩阵和准确率 cm confusionmat(Ytest, Ypred); acc sum(diag(cm)) / sum(cm(:)); fprintf(测试集准确率: %.4f\n, acc);逐项说参数。SplitCriterion选gdi是基尼指数也是 sklearn 默认想换成信息增益用deviance。MinLeafSize控制叶节点最少样本数设太小树会疯狂生长设太大树欠拟合5 到 20 是常见区间样本上千可以放到 10 以上。MaxNumSplits限制分裂次数相当于给树戴了个紧箍咒30 到 100 之间按特征数调。Prune设为on会做代价复杂度剪枝这是防过拟合最省事的一招。rng(42)不是装饰不固定种子每次划分不同你没法复现别人的准确率。3.2 查看树结构、规则导出与特征重要性建完树不看结构等于白建。决策树最大的价值就是可解释MATLAB 提供了几个直接可用的查看方式。view(tree)会弹出图形化树view(tree,Mode,graph)更清晰。想在命令行看文本规则用predict配合fitctree的CutPoint信息或者直接导出为代码。% 图形化查看树结构 view(tree, Mode, graph); % 查看特征重要性基于分裂带来的误差下降 imp predictorImportance(tree); bar(imp); xticklabels(featNames(idx(1:topK))); ylabel(重要性得分); % 导出树为可读的if-else规则文本 txt fitctree(Xtrain, Ytrain).view(Mode,text);predictorImportance返回每个特征的累计误差下降数值越大越重要。注意它和fscmrmr的排序不一定完全一致前者是树内部视角后者是统计视角两个都看能交叉验证。导出的文本规则可以直接贴进报告比如「PM2.5 小于 75 且 O3 小于 160 判为良」这种规则在业务沟通里比准确率数字更有说服力。3.3 交叉验证别拿单次划分的准确率当结论单次 HoldOut 划分的准确率波动可能有好几个百分点尤其是样本不均衡时。靠谱的做法是做 k 折交叉验证看均值和方差。MATLAB 里crossval一行就能做。% 5折交叉验证评估模型泛化能力 cvmodel crossval(tree, KFold, 5); loss kfoldLoss(cvmodel); fprintf(5折交叉验证平均误差: %.4f\n, loss); % 若要看每折准确率 accs zeros(5,1); for k 1:5 accs(k) 1 - kfoldLoss(cvmodel, Fold, k); end disp(accs);kfoldLoss默认返回分类误差1 减它就是准确率。如果 5 折准确率标准差超过 0.05说明模型不稳定要么样本太少要么特征噪声大要么类别极不均衡。这时候别急着调树参数先回去看数据。4. 避坑与排查这类源码最容易翻车的五个地方4.1 准确率 0.99 但一换数据就废现象在自己数据上跑出接近 1 的准确率换一份同城市不同月份的监测数据准确率掉到 0.6 以下。原因标签泄漏AQI 或某个由标签直接推导的列被当成了特征树只是学会了复读标签。解决逐列检查特征与标签的相关性任何相关系数超过 0.95 的列都要怀疑AQI 本身、空气质量等级文本列必须剔除。4.2 类别不均衡导致少数类全被吞现象混淆矩阵里「重度及以上」这一类召回率接近 0全被预测成「良」。原因空气质量数据里优良天数远多于重污染天数决策树默认按整体误差最小分裂会牺牲少数类。解决在fitctree里加Prior, empirical或手动设先验也可以用Weights给少数类加权更彻底的做法是对少数类过采样后再训练。4.3 缺失值填充方式选错引入虚假规律现象填充后模型在训练集表现很好但特征重要性排序里「湿度」异常靠前业务上说不通。原因用均值填充时如果缺失不是随机的比如仪器故障集中在高污染时段填充值会制造出与标签的伪相关。解决先统计缺失模式缺失比例超过 30% 的列直接弃用剩余缺失用中位数或前向填充并在报告里注明填充策略。4.4 树太深规则多到没法解释现象view出来的树有几十层导出规则上百条业务方根本看不懂。原因MinLeafSize设得太小、没开剪枝树把噪声也学进去了。解决把MinLeafSize提到 10 以上开启Prune,on并用MaxNumSplits限制规模如果还嫌大改用fitcensemble的 Bagged Trees单棵树规模可控且整体更稳。4.5 中文标签在混淆矩阵里显示成乱码现象confusionmat或confusionchart输出的类别名是方框或问号。原因MATLAB 默认字体对中文支持不好或者标签用了 string 但没转 categorical。解决把标签统一转成categorical并在绘图前设置set(groot,defaultAxesFontName,SimHei)导出图片时用exportgraphics指定分辨率避免截图糊掉。5. 把这份源码用出进阶价值从单棵树到可交付分析报告单棵决策树跑通只是起点。真正让这份源码在项目里站住脚的是把它变成一个可复现、可对比、可解释的分析流程。我一般会做三件事第一把决策树和随机森林、提升树放一起对比用同一套交叉验证口径看准确率和稳定性的差距。MATLAB 里fitcensemble的Bag和AdaBoostM2方法各跑一遍对比kfoldLoss如果集成方法只比单树高一个百分点那单树的可解释性优势就值得保留。第二把特征重要性做成可交付的图表。predictorImportance的柱状图加上fscmrmr的排序表两张图放一起业务方一眼能看出哪些污染因子是主因。这里有个细节重要性得分要归一化到 0 到 1否则不同模型之间没法比。第三把树规则导出成业务能用的判定逻辑。下面这段把树转成结构体再拼成规则文本方便贴进报告或转成 SQL 条件。% 递归提取树的分裂规则生成可读文本 function rules extractRules(node, tree, featNames, prefix) if isempty(node) rules {}; return; end if tree.IsLeaf(node) rules {sprintf(%s %s, prefix, string(tree.NodeClass(node)))}; return; end f featNames{tree.CutPredictorIndex(node)}; thr tree.CutPoint(node); leftPrefix sprintf(%s%s %.2f AND , prefix, f, thr); rightPrefix sprintf(%s%s %.2f AND , prefix, f, thr); rules [extractRules(tree.Children(node,1), tree, featNames, leftPrefix), ... extractRules(tree.Children(node,2), tree, featNames, rightPrefix)]; end这段递归函数的逻辑是遇到叶节点就输出「条件 类别」遇到分裂节点就按特征和阈值拼左右分支条件。参数上tree.CutPredictorIndex给的是特征索引要映射回特征名CutPoint是分裂阈值。跑完你会得到一组 if-else 规则可以直接交给做数据看板或预警系统的同事。最后说个我自己的习惯每次拿到一份新源码我不会直接改它的主脚本而是先复制一份把数据读取路径、标签定义、特征列表这三处单独拎出来做成配置区跑通基线后再动模型参数。这样即使调参调崩了也能一键回到能跑的版本。决策树这东西参数不多但每个都影响解释性宁可慢一点也别让树长成一团没法讲的乱麻。希望帮到你。本文还有配套的精品资源点击获取