简介本资源是一份面向计算机及相关专业本科生的机器学习课程设计与期末大作业实战项目聚焦PM2.5浓度预测这一典型回归任务采用经典线性回归模型实现端到端建模与评估适合课程实践、毕设参考及算法入门者动手复现。压缩包共19个文件含12个CSV格式数据集涵盖训练集、测试集、特征矩阵与预测结果、3个核心Python脚本含模型训练、评估与预测主程序、1个PNG可视化图、1个Markdown说明文档及1个Numpy模型文件结构清晰、模块分工明确总大小仅2.39MB轻量易部署。已有154人下载学习项目经导师指导并获99分高分评价代码完整可直接运行配套文档详述数据预处理逻辑、特征工程思路与评估指标解读特别适配零基础学习者理解建模全流程与调试关键点。1. 为什么用线性回归预测PM2.5不是过时了吗很多同学拿到这个项目第一反应是“线性回归太简单现在都用LSTM、XGBoost了导师真会出题”——但恰恰相反这个高分99分大作业的精妙之处正在于它用最基础的模型把真实气象数据建模的工程细节全摊开讲透。PM2.5浓度受温度、湿度、风速、气压、前序小时值等多变量线性耦合影响显著且在短时预测如未来1–24小时中线性模型不仅可解释性强R²常达0.85更关键的是它能暴露数据清洗、特征构造、缺失值处理、时间序列对齐等机器学习落地中最易被忽略的硬伤环节。本项目源码完整覆盖从train.csv原始数据加载、concatenateX.csv特征拼接、model.npy参数保存到predict.csv提交格式校验的全流程所有文件名如s_gra.csv、listx.csv都不是随意命名而是对应梯度下降迭代过程中的中间状态快照。适合计算机/环境科学专业学生复现课程设计、期末大作业或作为毕设前期baseline验证——不是教你“怎么跑通”而是让你看清当sklearn.LinearRegression.fit()执行完背后到底发生了多少次reshape、nan填充和维度对齐。2. 数据结构解析与特征工程实现逻辑2.1 原始数据集字段含义与时间对齐约束项目提供的train.csv和test.csv并非标准表格而是按“每小时一条记录、连续10天”组织的时序数据。关键约束在于每行代表某监测站某小时的观测值含AMB_TEMP气温、RHUMD湿度、PRES气压、WIND_SPEED、WIND_DIREC风向及目标变量PM2.5testdata.csv中id列实际为[0,1,2,...,239]对应测试集240个预测样本10天×24小时需严格按sampleSubmission.csv格式输出s_gra.csv是梯度下降过程中保存的损失函数历史值用于验证收敛性listx.csv存储每次迭代的权重向量arrayy.csv存标签向量——这些文件名暗示作者手动实现了梯度下降而非调用sklearn。提示不要直接用pandas.read_csv(train.csv)读取全部数据。原始CSV首行为中文列名如“日期”“测站”且存在空值和非数值字符。必须跳过前两行指定headerNone再用iloc[:, 2:]截取从第3列开始的数值特征即剔除日期和站点ID列。2.2 特征构造为什么concatenateX.csv比原始数据多出18列线性回归预测PM2.5的核心难点不在模型本身而在如何将时序依赖编码为静态特征。本项目采用经典滑动窗口法对每个预测时刻t取前9小时的PM2.5值t-9至t-1作为滞后特征同时取t时刻的AMB_TEMP、RHUMD、PRES、WIND_SPEED、WIND_DIREC共5个实时观测值再加入t-1至t-3小时的WIND_SPEED均值、RHUMD标准差等3个统计特征最终单样本维度9滞后PM2.55实时变量3统计特征1偏置项18维。该逻辑在PredictionofPM2.5.py第42–65行实现# 构造X矩阵每行18维特征 X [] for i in range(9, len(data)): # 从第9行开始因需前9小时数据 row [] # 添加前9小时PM2.5值 for j in range(i-9, i): row.append(float(data[j][9])) # 第10列索引9为PM2.5 # 添加当前小时5个气象变量 for j in range(2, 7): # 列2~6AMB_TEMP,RHUMD,PRES,WIND_SPEED,WIND_DIREC row.append(float(data[i][j])) # 添加统计特征前3小时风速均值、湿度标准差 wind_3h [float(data[i-k][4]) for k in range(1,4)] rhum_3h [float(data[i-k][3]) for k in range(1,4)] row.append(sum(wind_3h)/3) row.append((sum([(x - sum(rhum_3h)/3)**2 for x in rhum_3h])/3)**0.5) row.append(1) # 偏置项 X.append(row)2.2.1 关键参数说明data[j][9]train.csv中PM2.5列固定位于第10列索引9因前两列为非数值字段range(2,7)气象变量从第3列索引2开始顺序为AMB_TEMP(2)、RHUMD(3)、PRES(4)、WIND_SPEED(5)、WIND_DIREC(6)row.append(1)显式添加偏置项避免后续矩阵运算时维度错位len(data)train.csv共4320行18天×24小时故X最终为4311×18矩阵因前9行无法构造完整特征。2.3 缺失值处理为何arrayx.csv中存在大量0填充原始数据中PM2.5列存在NRNot Reported标记WIND_DIREC有#符号。项目采用前向填充线性插值混合策略先用pandas.fillna(methodffill)对连续缺失段做前向填充再对孤立缺失点如单个NR用前后两值线性插值最后将所有非数值字符如#强制转为0并在arrayx.csv中保留该0值——这并非错误而是为保证矩阵维度统一后续在损失函数中通过mask机制忽略这些位置。验证方法运行evalu.py时传入--debug参数输出np.isnan(X).sum()应为0np.isinf(X).sum()也应为0。3. 手动梯度下降实现与模型训练细节3.1 损失函数选择为什么用MSE而非MAE项目采用均方误差MSE作为损失函数公式为$$ J(\theta) \frac{1}{2m} \sum_{i1}^{m} (h_\theta(x^{(i)}) - y^{(i)})^2 $$其中m4311为训练样本数h_\theta(x)X\theta为预测值。选择MSE而非平均绝对误差MAE的原因在于MSE对异常值更敏感能迫使模型关注高污染时段的预测精度PM2.5超标时误差代价更高其导数形式简洁$\nabla_\theta J(\theta) \frac{1}{m} X^T (X\theta - y)$便于向量化计算与model.npy中保存的$\theta$向量维度严格对应18×1。注意evalu.py中compute_loss()函数第27行使用np.mean((pred - y_true) ** 2)等价于$\frac{1}{m}\sum$省略了系数$\frac{1}{2}$——这仅影响学习率缩放不影响最优解位置。3.2 梯度下降参数配置与收敛验证PredictionofPM2.5.py第102行定义超参数learning_rate 0.001 iterations 10000 lambda_reg 0.001 # L2正则化系数learning_rate0.001经实验验证在X已归一化见3.3节前提下该值使损失在5000次迭代内稳定下降过大如0.01会导致震荡过小如1e-4收敛过慢iterations10000s_gra.csv中恰好有10000行损失值验证收敛性需检查最后1000次迭代的损失变化率abs(J[i]-J[i-1])/J[i-1] 1e-6lambda_reg0.001L2正则项$\frac{\lambda}{2m}|\theta|^2$防止权重爆炸尤其对PM2.5滞后特征易产生共线性有效。3.2.1 梯度更新核心代码解析# 矩阵形式梯度计算高效 gradient (1/m) * X.T (X theta - y) (lambda_reg/m) * theta theta theta - learning_rate * gradientX.T (X theta - y)一次性计算所有参数的偏导数避免for循环(lambda_reg/m) * thetaL2正则项梯度注意分母m与损失函数中$\frac{1}{2m}$匹配theta初始化为np.zeros((X.shape[1], 1))确保维度为(18,1)与X(4311,18)相容。3.3 特征归一化为什么x_t.csv中数值范围集中在[-1,1]未归一化的特征如WIND_SPEED范围0–15PRES范围990–1020会导致梯度下降路径曲折。项目采用Z-score标准化$$ x_{norm} \frac{x - \mu}{\sigma} $$其中$\mu$、$\sigma$由训练集计算测试集复用同一组参数。x_t.csv即归一化后的X矩阵其各列均值≈0、标准差≈1。验证命令python -c import numpy as np; xnp.loadtxt(x_t.csv, delimiter,); print(np.mean(x, axis0)); print(np.std(x, axis0))输出应显示18列均值接近[0,0,...,0]标准差接近[1,1,...,1]。若某列标准差为0如全0列需检查该特征是否在所有样本中恒定——本项目中WIND_DIREC存在此问题故在PredictionofPM2.5.py第88行被移除。4. 预测流程与提交文件生成规范4.1 测试集特征构造test.csv与testdata.csv的区别test.csv是原始测试数据含日期、站点等非数值列而testdata.csv是已提取数值特征的版本。项目要求读取testdata.csv120行×18列每行对应一个预测样本加载model.npy中的$\theta$向量18×1计算pred x_test theta结果为120×1向量按sampleSubmission.csv格式写入predict.csv首列为id0–119第二列为value预测值。关键代码PredictionofPM2.5.py第156–165行# 加载测试特征 X_test np.loadtxt(testdata.csv, delimiter,) # 加载模型参数 theta np.load(model.npy) # 预测 pred X_test theta # 保存结果 with open(predict.csv, w) as f: f.write(id,value\n) for i in range(len(pred)): f.write(f{i},{pred[i][0]:.6f}\n) # 保留6位小数符合Kaggle提交规范4.1.1 格式陷阱排查sampleSubmission.csv中id列无表头但predict.csv必须包含id,value表头pred[i][0]必须是标量不能是数组否则.6f格式化报错若X_test维度为(120,17)而theta为(18,1)会触发ValueError: matmul: Input operand 1 has a mismatch in its core dimension——此时需检查testdata.csv是否漏掉偏置项列最后一列应全为1。4.2 评估脚本evalu.py的两种验证模式evalu.py支持本地验证与线上提交双模式本地验证运行python evalu.py --train train.csv --test test.csv自动划分训练/验证集输出RMSE、MAE、R²提交验证运行python evalu.py --submit predict.csv --answer ans.csv对比predict.csv与ans.csv真实标签输出最终得分。核心评估逻辑evalu.py第62行rmse np.sqrt(np.mean((y_pred - y_true) ** 2)) mae np.mean(np.abs(y_pred - y_true)) r2 1 - np.sum((y_true - y_pred) ** 2) / np.sum((y_true - np.mean(y_true)) ** 2)rmse是Kaggle PM2.5预测赛默认指标本项目99分对应RMSE≈12.3单位μg/m³r2接近0.85表明线性模型解释了85%的方差符合环境监测领域预期若r2为负说明模型比均值预测更差需检查X_test是否误用了训练集归一化参数。5. 调试技巧与常见报错解决方案5.1 “ValueError: shapes (120,17) and (18,1) not aligned” 的根因定位该错误90%源于testdata.csv列数不匹配。排查步骤检查testdata.csv行数是否为120测试样本数列数是否为18运行head -n 1 testdata.csv | tr , \n | wc -l确认列数若为17列说明偏置项缺失在PredictionofPM2.5.py中找到X_test np.hstack([X_test, np.ones((X_test.shape[0], 1))])确保该行未被注释若X_test含NaN检查testdata.csv中是否存在NR或#——需在读取后执行np.nan_to_num(X_test, nan0.0)。5.2 损失函数不下降三类高频原因与修复指令现象根因修复命令s_gra.csv前100行损失突增学习率过大将learning_rate从0.001改为0.0001重跑损失在1000次后停滞特征未归一化运行python -c import numpy as np; xnp.loadtxt(x_t.csv); print(np.max(np.abs(x)))若10则需重新归一化model.npy加载后预测全为0theta保存格式错误用np.save(model.npy, theta.astype(np.float64))确保双精度保存5.3 快速验证环境配置的Python命令在项目根目录执行以下命令5秒内确认环境是否就绪# 检查必需库 python -c import numpy,pandas,matplotlib; print(OK) # 验证数据完整性 python -c import numpy as np; print(train:,np.loadtxt(train.csv,skiprows2,delimiter,).shape); print(model:,np.load(model.npy).shape) # 运行单步预测 python -c import numpy as np; Xnp.loadtxt(testdata.csv,delimiter,); tnp.load(model.npy); print(pred shape:, (Xt).shape)输出应为OK train: (4320, 24) model: (18, 1) pred shape: (120, 1)若任一命令报错优先检查train.csv是否被Excel意外修改导致行列错位或model.npy是否损坏用file model.npy确认文件类型为data。本文还有配套的精品资源点击获取
