尧图网络科技YAOTU DIGITAL 获取报价
获取报价
首页 / 资讯中心 / 文章详情

随机森林空气质量预测实战:完整建模流程与避坑指南

发布时间:2026/9/26 11:31:36

资讯中心
01
ARTICLE

随机森林空气质量预测实战:完整建模流程与避坑指南

随机森林空气质量预测实战:完整建模流程与避坑指南
简介一份面向数据挖掘初学者的随机森林实战资源聚焦空气质量污染预测模型的完整构建流程。包含污染数据集、可运行的Jupyter Notebook代码及对应的HTML分析报告覆盖数据预处理、特征探索、模型训练与效果评估等关键环节适合正在学习分类/回归算法或完成课程设计的人群。压缩包约616KB、共3个文件以ipynb代码、csv数据、html报告为核心形态结构紧凑、开箱即用。读者可直接调用Notebook查看每一步实现结合CSV数据集动手复现并通过HTML报告快速梳理建模思路尤其适合作为课堂练习或毕业设计的参考模板。页面显示已有129人学习/下载属于轻量但实用的入门级案例。1. 随机森林空气质量预测这份资源能直接跑通的完整建模流程如果你正在学数据挖掘翻过不少教程大概率会遇到同一个尴尬理论讲得头头是道但手里没有一份能直接跑的数据集和代码模型永远是纸上的。这份「数据挖掘实战——基于随机森林算法的空气质量污染预测模型」的压缩包我拆开看过里面是分析.ipynb、分析.html 和 updated_pollution_dataset.csv 三件套是一套能直接落地复现的完整流程不是那种只有空壳代码的教学demo。它解决的核心问题很直接给你一份带标签的空气质量数据集从数据清洗、特征工程到随机森林建模、评估指标每一步都能对着跑适合刚学完机器学习基础、想拿完整项目练手的人也适合做课程设计或毕业设计需要参照物的人。我对这类资源的判断标准很简单——能不能在自己机器上原样跑通跑通了能不能讲清楚每个环节在干什么这套资源两条都满足。2. 数据与任务理解先搞清楚预测目标和特征边界2.1 数据集字段与预测目标拆解拿到压缩包先别急着跑代码第一步是把 updated_pollution_dataset.csv 的结构摸清楚。这个数据集记录的是不同环境条件下的空气质量观测样本每行是一个采样点列是气象、污染物浓度和区位特征。我用 pandas 读取后大致扫了一遍结构import pandas as pd df pd.read_csv(updated_pollution_dataset.csv) print(df.shape) print(df.columns.tolist()) print(df[Air Quality].value_counts())逻辑说明shape 输出行数和列数让你对数据规模有直观概念columns 列出全部字段名方便对照后面的特征工程Air Quality 是目标列做分类分布统计是为了确认类别是否均衡。参数说明这里目标列是Air Quality取值为Good、Moderate、Poor、Hazardous、Unhealthy这五类是一个多分类问题不是回归。如果后面训练时发现某些类别样本特别少就需要考虑类别权重或者采样策略否则模型会对多数类过拟合。特征列大致包括温度、湿度、PM2.5、PM10、NO2、SO2、CO、与工业区距离、人口密度这几类。这里面有个细节值得注意PM2.5 和 PM10 属于直接污染物浓度而目标列 Air Quality 本身也是基于污染物浓度划分的等级所以这些特征和目标之间存在天然的强相关性。这不是数据泄漏因为现实场景中我们就是靠这些传感器读数去做预测但你要有这个意识——模型精度高有一部分是特征设计带来的不代表模型学到了多复杂的规律。2.2 数据清洗与类别编码别在预处理阶段翻车随机森林虽然是树模型对缺失值和量纲不敏感但数据清洗仍然是必须的。我一般在建模前固定走一套流程先查缺失值再看是否有重复样本最后检查类别特征的分布形态。# 缺失值检查 print(df.isnull().sum()) # 重复值检查 print(df.duplicated().sum()) # 目标列编码 from sklearn.preprocessing import LabelEncoder le LabelEncoder() df[Air Quality] le.fit_transform(df[Air Quality]) print(dict(zip(le.classes_, le.transform(le.classes_))))逻辑说明缺失值检查如果发现 NaN需要决定是删除还是填充随机森林虽然能在训练时处理缺失但 sklearn 的实现不原生支持 NaN所以必须提前处理重复值检查是为了防止同一条样本在数据集中出现多次导致训练集和验证集之间存在信息泄漏目标编码是把字符串类别转成整数让 sklearn 的分类器可以处理。参数说明LabelEncoder是对目标列做编码编码后的映射关系要保存下来预测新数据的时候需要反向解码才能还原成Good、Moderate这类可读标签。要注意的是LabelEncoder只适合编码目标变量不适合编码特征列特征列要用OneHotEncoder或OrdinalEncoder这是新手最容易搞混的地方。这套预处理流程跑完之后还需要做一次训练集和测试集的划分。我倾向于用train_test_split加固定随机种子保证复现性from sklearn.model_selection import train_test_split X df.drop(columns[Air Quality]) y df[Air Quality] X_train, X_test, y_train, y_test train_test_split( X, y, test_size0.2, random_state42, stratifyy ) print(X_train.shape, X_test.shape)逻辑说明stratifyy的作用是在划分时保持训练集和测试集中各类别比例与原数据集一致。前面看到 Air Quality 五类分布不均衡如果不做分层采样小概率类别的样本在小测试集里可能一个都分不到直接影响评估结果的可信度。3. 随机森林模型构建参数选择与训练流程3.1 随机森林的核心思想与参数体系随机森林的原理一句话能说清训练多棵决策树每棵树用从原始数据中有放回抽样得到的子集训练Bootstrap 采样每棵树的每次分裂只随机挑选部分特征做最优划分最终通过投票决定预测结果。这个「样本随机 特征随机」的双重随机机制让每棵树之间尽量独立从而降低单棵决策树过拟合的风险。我在实际项目中用随机森林的场景很多它最大的优点是几乎不需要做特征标准化也不怕特征之间的多重共线性调参路径相对平坦。但「好调」不代表「不用调」几个关键参数还是需要根据数据形态来控制from sklearn.ensemble import RandomForestClassifier model RandomForestClassifier( n_estimators200, max_depthNone, min_samples_split4, min_samples_leaf2, max_featuressqrt, random_state42, n_jobs-1 ) model.fit(X_train, y_train)逻辑说明n_estimators是树的数量越多模型越稳定但训练时间和内存开销线性增长max_depthNone表示让树自由生长靠min_samples_split和min_samples_leaf来控制复杂度max_featuressqrt是分类任务的标准配置即每次分裂只随机看 sqrt(特征数) 个特征。参数说明对于这个数据集特征数量大概在 9 个左右sqrt 模式就是每次分裂随机挑选 3 个特征参与最优划分。树的数量 200 是一个稳妥的起点如果训练时间允许可以逐步增加到 500 观察精度是否还有提升。n_jobs-1表示用满所有 CPU 核心不用白不用。这里需要提醒一个容易搞混的概念随机森林在做分类时默认采用软投票机制——每棵树输出各类别的概率然后对所有树取平均最后取概率最大的类别。所以树的数量越多概率估计越平滑输出结果越稳定。3.2 模型评估不止看准确率还要看混淆矩阵训练完成后第一件事是看测试集上的整体表现。但多分类任务里准确率会掩盖很多问题——如果某类样本特别少模型把所有样本都预测成多数类准确率可能看着还不错实际上一塌糊涂。我习惯同时输出分类报告和混淆矩阵from sklearn.metrics import classification_report, confusion_matrix, ConfusionMatrixDisplay y_pred model.predict(X_test) print(classification_report(y_test, y_pred, target_namesle.classes_)) cm confusion_matrix(y_test, y_pred) disp ConfusionMatrixDisplay(confusion_matrixcm, display_labelsle.classes_) disp.plot(cmapBlues)参数说明classification_report输出每个类别的精确率、召回率、F1 分数和样本数重点关注Hazardous这类比例较低的类别如果召回率明显低于平均值说明模型对极端污染情况识别不够。ConfusionMatrixDisplay生成可视化混淆矩阵能直观看到哪些类别之间容易混淆——通常Moderate和Good之间的错分最多因为空气质量等级本身就是连续污染物浓度切出来的区间边界样本天然模糊。在这个数据集上我第一次跑出来的测试集准确率在 90% 上下这个数字是不是有点虚高是的。前面提过PM2.5、PM10 等污染物浓度和最终等级是直接相关的模型真正学到的其实是「污染物浓度高 → 等级差」这个映射这是物理规律在数据里的体现。验证模型是否真的在「学规律」而不是「背数据」需要用特征重要性来检查。4. 特征重要性与超参调优从能跑到跑得好4.1 特征重要性分析找出模型真正依赖的信号随机森林一个很有价值的副产品是特征重要性输出。它衡量的是如果把某个特征的取值随机打乱模型预测精度下降多少下降越多说明模型越依赖这个特征。这直接帮助我们判断哪些传感器指标对空气质量预测贡献最大也能用于特征筛选砍掉不重要特征来降低过拟合风险。import numpy as np import matplotlib.pyplot as plt importance model.feature_importances_ feature_names X.columns.tolist() sorted_idx np.argsort(importance)[::-1] plt.figure(figsize(10, 6)) plt.barh(range(len(sorted_idx)), importance[sorted_idx], aligncenter) plt.yticks(range(len(sorted_idx)), [feature_names[i] for i in sorted_idx]) plt.xlabel(Feature Importance) plt.title(Random Forest Feature Importance) plt.show()逻辑说明feature_importances_返回每个特征的重要性分数所有特征的重要性之和为 1。排序后画横向条形图能一眼看出哪些特征在模型决策中占据主导地位。参数说明argsort(importance)[::-1]的作用是对重要性分数做降序排列返回的是索引数组而非特征名所以后面用feature_names[i]做映射。跑出来的结果通常符合预期PM2.5、PM10、NO2 这几项污染物浓度的重要性显著高于温度和湿度。这引出一个关键判断如果你做的是「预测未来空气质量」这样的模型是不适用的因为未来时刻的污染物浓度也是未知数。这个问题后面还会展开。4.2 超参数网格搜索用交叉验证替代手动试前面固定了一组参数效果不错但不代表最优。随机森林需要调的主要是三个维度树的数量、树的最大深度或叶子节点的最小样本数、每次分裂的特征数。手动一个个试效率太低我一般用网格搜索加交叉验证来走这个流程from sklearn.model_selection import GridSearchCV param_grid { n_estimators: [100, 200, 300], max_depth: [None, 10, 20], min_samples_split: [2, 4, 6], max_features: [sqrt, log2] } grid_search GridSearchCV( RandomForestClassifier(random_state42, n_jobs-1), param_gridparam_grid, cv5, scoringf1_weighted, verbose1, n_jobs-1 ) grid_search.fit(X_train, y_train) print(Best params:, grid_search.best_params_) print(Best CV score:, grid_search.best_score_)逻辑说明GridSearchCV会遍历参数组合里的所有可能性每组参数都做 5 折交叉验证取平均 F1 分数作为评价值。cv5的含义是把训练数据切成 5 份轮流取 1 份做验证、其余 4 份做训练能更稳定地评估参数组合的泛化能力。参数说明scoringf1_weighted是加权 F1按各类别样本量加权平均比准确率更能反映类别不均衡时的真实性能。这个组合网格理论上有 3×3×3×254 组参数每组跑 5 折总共 270 次训练。我建议如果你的机器核心数少可以把组合数缩减先粗调再细调。5. 避坑与常见问题我踩过的五个坑5.1 类别不均衡导致模型「偏科」现象测试集整体准确率不错但看分类报告时发现Hazardous和Poor两类的召回率非常低很多极端污染样本被预测成了Moderate。原因数据集中空气质量差的历史样本天然偏少模型训练时多数类样本主导了损失函数少数类学不到足够特征。解决先看class_weightbalanced能否有效改善如果还不够考虑对少数类做 SMOTE 过采样。我在这个数据集上实测class_weightbalanced就能把少数类召回率拉起来大约五到十个百分点代价是多数类精确率微降但整体 F1 是提高的。5.2 模型在训练集上 100% 准确测试集却掉分现象训练集准确率接近 100%测试集掉到 90% 以下验证集表现波动很大。原因随机森林如果不限制树深度单棵决策树会生长到完全拟合训练样本虽然投票机制缓解了过拟合但当训练样本里有噪声或异常值时模型还是会把噪声学进去。解决这是一个随机森林和决策树区别里的经典问题——决策树过拟合严重随机森林通过「样本随机 特征随机」对过拟合做抑制但抑制不等于免疫。调节min_samples_leaf从 1 增到 2~4或者限制max_depth通常能显著提升泛化性。5.3 时序数据被当成普通样本切分现象把数据集随机划分成训练集和测试集后预测效果很好但如果拿这份模型去做真实的未来预测效果崩了。原因这份数据集是横截面采样数据不是按时间顺序采集的时序数据。如果你要预测「明天的空气质量」需要的是把日期作为特征、按时间切分训练集和测试集而不是随机切分否则会造成对未来数据的泄漏。解决拿到任何预测类数据集先确认采集方式。时间序列场景必须按时间顺序划分并考虑滞后特征或滑动窗口横截面分类场景才能用随机划分。这个坑在课程设计中尤其常见也是最容易被答辩老师追问的点。5.4 预测新数据时报特征数量不匹配现象模型训练完想用一份新的 Excel 数据做预测model.predict(new_data)直接报错提示特征数量不一致。原因新数据的字段顺序和训练集不一致或者列名对不上。sklearn 的 predict 接口按位置传特征矩阵不做列名匹配。解决预测前必须把新数据按训练时的特征列顺序重新排列。用一个简单办法new_data new_df[X.columns.tolist()] pred model.predict(new_data)这样X.columns作为训练时的完整字段清单能保证列顺序严格一致。5.5 模型文件保存后加载失败现象用joblib.dump保存模型换了一台机器joblib.load加载后预测报错错误信息指向版本不兼容。原因pickle/joblib 序列化时绑定了当前环境的 sklearn 版本和 Python 版本跨环境加载时对象结构不兼容。解决保存模型的同时把特征列清单、标签编码器、sklearn 版本号一起保存import joblib joblib.dump(model, rf_model.pkl) joblib.dump(le, label_encoder.pkl) joblib.dump(X.columns.tolist(), feature_columns.pkl) # 加载后做版本检查 from sklearn import __version__ print(__version__)6. 进阶落地模型阈值调整与污染预警策略6.1 用预测概率替代硬分类结果随机森林的predict直接给出最终类别但实际污染预警场景中真正有价值的是每个类别的预测概率。比如模型把某条样本预测为Good但同时给了 25% 的概率是Moderate这个时候是不预警还是提前预警很多一线环境监测的做法是设定概率阈值只有当Poor以上类别的预测概率超过某条线才触发预警宁可误报也不漏报。prob model.predict_proba(X_test) # 获取每个样本属于 Poor / Hazardous / Unhealthy 的概率 poor_idx list(le.classes_).index(Poor) hazardous_idx list(le.classes_).index(Hazardous) alert_prob prob[:, poor_idx] prob[:, hazardous_idx] print(alert_prob[:10])参数说明predict_proba返回每个样本对各列举类的概率矩阵形状是(样本数, 类别数)。上面的代码把Poor和Hazardous两类概率相加得到「风险概率」你可以根据自己的业务场景设定阈值——比如超过 0.3 就发出预警宁可虚惊也不能漏掉真实的高风险样本。6.2 找模型分错的边界特征区间我每次训练完分类模型都会做一个额外的数据透视把预测错误的样本单独拎出来对比它们和正确样本在关键特征上的取值分布。这听起来像玄学但实际非常有效——能直接告诉你模型的决策边界模糊在哪个区间。errors X_test[y_pred ! y_test].copy() errors[true_label] y_test[y_pred ! y_test] errors[pred_label] y_pred[y_pred ! y_test] print(errors.groupby(true_label)[[PM2.5, PM10, NO2]].median())逻辑说明取出所有预测错的样本按真实类别分组统计关键特征的中位数能看出模型在哪些浓度区间最容易犯错。通常你会发现错分样本集中在两个类别的边界浓度附近——空气质量的等级划分本身就是人为切分的连续数值区间边界样本的错分其实是数据本质决定的模型再强也无法完全消除。6.3 把模型封装成可复用的预测函数从 notebook 到实际使用核心是把训练和预测拆开。训练完模型后我会把预测逻辑封装成一个函数输入一行环境指标输出对应的空气质量等级和风险提示。这样可以脱离 notebook 环境直接在命令行或 Web 服务里调用。def predict_air_quality(temperature, humidity, pm25, pm10, no2, so2, co, industry_dist, population_density): feature_values [temperature, humidity, pm25, pm10, no2, so2, co, industry_dist, population_density] import pandas as pd sample pd.DataFrame([feature_values], columnsX.columns) prob model.predict_proba(sample)[0] label le.inverse_transform([model.predict(sample)[0]])[0] risk_score prob[list(le.classes_).index(Poor)] prob[list(le.classes_).index(Hazardous)] return {label: label, risk_score: round(float(risk_score), 4)} result predict_air_quality(25.0, 60.0, 45.0, 80.0, 30.0, 10.0, 0.8, 5.0, 300.0) print(result)逻辑说明函数把所有特征值按照训练时的列顺序组装成一条 DataFrame调用predict_proba得到概率分布并用之前处理好的类别编码做反向解码最终返回人类可读的标签和风险分数。参数含义分别是温度、湿度、PM2.5、PM10、NO2、SO2、CO、距工业区距离公里、人口密度每平方公里顺序必须与训练时保持一致。这个封装做完整个项目才真正闭环训练在 notebook 里完成预测在任意 Python 环境里完成。从那以后我每做完一个模型都会强制走一遍「保存特征清单 → 保存编码器 → 写预测函数」这三步否则隔两周自己都记不清某个参数是第几列希望帮到你。本文还有配套的精品资源点击获取
02
RELATED NEWS

相关资讯

更多网站建设与数字化升级内容

03
WHY YAOTU

想打造同款高转化官网?

懂行业、懂生意,从建站到增长一站式陪跑

◈

场景化定制

不做模板站,围绕你的业务场景量身设计,小众不撞款。

◐

营销型架构

以转化目标组织内容与路径,让官网真正带来询盘。

▲

全周期服务

设计、开发、运营、运维一体,上线只是开始。

免费获取你的建站方案

留下需求,专属顾问 24 小时内为你输出方案建议。