ARTICLE DETAIL

资讯详情

深耕郑州网站建设与运营推广的一线实战洞察。

TOA深度学习反演PM2.5:Python遥感毕设源码全解析

TOA深度学习反演PM2.5:Python遥感毕设源码全解析 简介这是一份基于Python的遥感毕业设计项目通过TOA大气顶部反射率数据与深度学习模型反演PM2.5浓度配套完整源码与文档说明内容覆盖遥感数据准备、PM2.5值提取、索引处理、深度学习建模及交互式分析等完整环节。项目实现链条清晰适合遥感、环境科学、人工智能、自动化、计算机等相关专业学生用于毕业设计、课程设计或项目初期演示基础较好的学习者还可在此基础上扩展不同区域或不同气溶胶参数的反演功能。代码均经过测试运行成功答辩评审平均分达到94.5分可读性高实际参考价值较强。压缩包内共6个文件含4个Python脚本、1个Jupyter Notebook和1个文本说明脚本分别承担数据预处理、PM2.5提取、索引与数值处理、深度网络训练等任务Notebook展示完整反演流程并便于直接运行观察结果整体仅12KB目录结构简洁。上线后已有244人学习下载能帮助读者较快理解TOA遥感反演与深度学习结合的实现路径并迁移到自身课题中。1. TOA反演PM2.5这份毕设源码先想清楚它解决什么问题遥感方向的毕业设计真正卡人的地方往往不在算法而在“从原始影像到模型训练”这条完整数据链。这套基于Python的遥感毕业设计源码走的是TOA深度学习反演PM2.5的路线直接用大气层顶反射率的多波段数据作为输入绕开大气校正这个黑匣子用深度学习模型回归出近地面PM2.5浓度适合遥感、GIS、环境科学、计算机相关方向的毕设、课设以及算法预研。资源描述里明确写了代码测试通过、答辩评分94.5我把它当成一个已经跑通的成品基线来看。需要先说清楚它不是“下载下来直接出结果”的傻瓜包。遥感影像、站点监测数据这类原始资料得你自己准备源码提供的是“数据准备→特征提取→站点标签对齐→深度学习训练→反演出图”的完整工作流而这恰恰是反演类毕设里最容易写崩的环节。适不适合你主要看两件事一是毕设题目是否围绕“卫星反演空气质量”展开二是你能不能接受用Python脚本加Jupyter Notebook来跑实验。这两条都满足这份源码就值得下载。2. 源码结构拆解五个模块先把数据流盘清楚拿到一个毕设压缩包先别急着双击运行第一步永远是“盘文件”。把每个文件在数据流里的位置搞清楚后面跑起来会省掉大量排错时间。这套源码的文件结构比较清晰五个模块各管一段我按“数据准备→标签提取→特征提取→模型训练”的顺序给你拆开。2.1 压缩包里的文件谁管数据、谁管模型文件类型在数据流里的角色Data_Preparation目录数据准备存放裁剪、波段合成相关脚本Extraction_PM_V3.pyPython脚本从监测站数据中提取PM2.5浓度生成标签Data_Extraction_index.pyPython脚本提取遥感指数特征如NDVI等Data_Extaction_Value_V4.pyPython脚本按坐标提取TOA多波段像元值Deep_learning目录存放深度学习训练脚本Deep.pyTOA反演PM2.5.ipynbJupyter Notebook主流程串联训练、反演、绘图注意一个细节Data_Extaction_Value_V4.py这个文件名里“Extaction”是原文件自带的拼写不是笔误。下载后不要手贱去“修正”它因为脚本之间可能按文件名互相引用改名容易触发一连串报错。我一般会先把压缩包原样解压确认能跑通之后再考虑重构。这条数据流大致是TOA遥感影像先进Data_Preparation做裁剪合成同时用Extraction_PM_V3.py从站点数据里抽出PM2.5浓度作为标签再用Data_Extraction_index.py和Data_Extaction_Value_V4.py从影像里提取特征像元值最后把标签和特征拼成一张训练表交给Deep_learning里的模型训练Notebook负责输出反演结果。2.2 Data_Preparation裁剪和波段合成是第一道坎L1级别的TOA产品通常覆盖范围很大直接拿来训练既浪费内存也没意义。常规做法是先按研究区矢量边界做裁剪再从需要的波段合成多波段文件最后统一转成float32降低后续读取开销。Data_Preparation目录里的脚本主要就是在干这几件事。import os from glob import glob data_root rD:\rs_data\L1_TOA site_shape rD:\rs_data\study_area.shp tif_list sorted(glob(os.path.join(data_root, **, *.tif), recursiveTrue)) print(f共找到 {len(tif_list)} 景影像) for tif in tif_list[:5]: fname os.path.basename(tif) # 常见命名规则如 LC08_L1TP_xxx_20210101最后一段是成像日期 date_str fname.split(_)[-1].replace(.tif, ) print(date_str, tif)这段代码解决的是“先把数据底账盘出来”的问题。递归glob能找全子目录下的所有tif文件避免手工一个一个写路径从文件名里解析成像日期是为了后面和站点PM2.5监测数据做时间匹配做准备。这里的核心参数是data_root和site_shape我一般建议都用绝对路径且路径里不要带中文和空格Windows下可以用反斜杠但跨平台更稳的写法是像上面这样用正斜杠加os.path.join。跑通这一步之后Data_Preparation里通常还包含一个按矢量边界裁剪tif的函数内部会调用rasterio的mask模块。这块最常见的坑是矢量文件和影像的坐标系不一致裁剪出来全黑后面第4章会单独讲。2.3 三个提取脚本站点浓度和像元值怎么对齐Extraction_PM_V3.py负责把监测站点的PM2.5浓度整理成一张结构化表格字段至少包含站点经纬度、日期、浓度值。Data_Extraction_index.py和Data_Extaction_Value_V4.py则负责从TOA影像里提取特征前者算指数后者按坐标取多波段像元值。这三个脚本配合的最终产物是一张训练样本表datelonlatb1b2b3...b9ndvipm25这里的核心操作是“按站点坐标取像元值”。遥感影像的坐标和站点经纬度通常不是同一套投影系统站点一般是EPSG:4326经纬度而影像可能是UTM投影直接套坐标取行列号必然错位。import rasterio import pandas as pd site_df pd.read_csv(pm25_sites.csv, encodingutf-8-sig) toa_tif TOA_20210101.tif with rasterio.open(toa_tif) as src: for idx, row in site_df.iterrows(): lon, lat row[lon], row[lat] # rowcol默认按影像自身的坐标系解析站点经纬度需先投影转换 col, row_idx rasterio.transform.rowcol( src.transform, lon, lat ) if 0 row_idx src.height and 0 col src.width: val src.read(1)[row_idx, col] site_df.loc[idx, toa_b1] val这段代码的逻辑是遍历站点表的每一行把经纬度转换成影像坐标对应的行列号再从第一波段里取出该位置的像元值。这里有两个关键点一是调用rowcol前要确保站点经纬度已经被转换到和影像一致的投影坐标系否则取到的行列号是错的二是读取之前先做边界判断不然站点落在影像范围外时取下标会直接抛IndexError。实际毕设里建议在循环外加一个坐标转换步骤比如用pyproj把整个站点表的经纬度批量转成UTM坐标再逐点取值效率会高很多。2.4 运行顺序与文件路径先跑哪个、后跑哪个这套源码的运行顺序基本是固定的跳步跑大概率报错。按我的习惯拿到压缩包后先建一个干净的纯英文路径目录再按下面顺序操作把站点PM2.5数据整理成CSV确保列名是lon、lat、date、pm25。运行Data_Preparation里的脚本生成裁剪好的研究区TOA多波段tif。运行Extraction_PM_V3.py生成站点浓度表。运行Data_Extraction_index.py和Data_Extaction_Value_V4.py生成特征表。把特征表和站点浓度表按日期、站点ID合并成训练样本CSV。运行Deep_learning下的Deep.py训练模型。在TOA反演PM2.5.ipynb里完成反演和出图。路径问题我在这一步就会提前做预防把所有输入输出路径统一改成绝对路径并且把脚本里的相对路径写法全部换掉。压缩包自带的脚本通常默认相对路径当前工作目录变了就会报No such file这条线索在毕设答辩时也经常被老师拿来问。3. 深度学习反演模型Deep.py与Notebook怎么配合数据流理清楚之后核心环节就是深度学习模型本身。这一章讲透三件事为什么用TOA反射率做输入、Deep.py里的网络结构怎么写、Notebook怎么把训练和反演串成一条完整流程。反演类毕设的答辩重点大部分集中在这一章值得多花时间。3.1 为什么用TOA反射率把大气校正问题交给模型传统的光学遥感反演PM2.5标准路线是先做大气校正得到地表反射率再结合气象数据建立统计回归模型。大气校正是个典型的黑匣子涉及气溶胶光学厚度、水汽、臭氧等一堆参数任何一环输入不对反射率就有系统偏差。这套源码的思路是直接用TOA反射率作为模型输入把“大气路径辐射如何影响观测值”这个问题一并交给深度学习去拟合。这个选择的合理性在于神经网络本质上是个万能函数逼近器只要训练样本里包含足够多的天顶角、观测几何和大气状态组合模型能自己学到大气散射的隐含关系。实际做的时候输入特征一般不止裸的TOA反射率常见做法是把太阳天顶角余弦、观测天顶角、相对方位角这些几何参数也拼进来甚至加上边界层高度、相对湿度等辅助变量一起送入网络。3.2 Deep.py里的网络结构回归任务的常见写法Deep.py作为深度学习训练脚本一般包含数据加载、标准化、模型定义、训练循环和模型保存。模型结构通常是全连接回归网络在站点样本量只有几百到几千的场景下MLP比CNN和LSTM更稳参数量小不容易过拟合训练也快。import torch import torch.nn as nn class TOAPM25Regressor(nn.Module): def __init__(self, in_features9, hidden128): super().__init__() self.net nn.Sequential( nn.Linear(in_features, hidden), nn.ReLU(), nn.Dropout(0.2), nn.Linear(hidden, hidden // 2), nn.ReLU(), nn.Linear(hidden // 2, 1) # 回归任务输出层不加激活函数 ) def forward(self, x): return self.net(x).squeeze(-1) model TOAPM25Regressor(in_features9) criterion nn.MSELoss() optimizer torch.optim.Adam(model.parameters(), lr1e-4)这里要注意几个细节。回归任务的输出层不加激活函数因为PM2.5浓度是连续值模型需要输出“无限范围”的数值加sigmoid或ReLU反而限制了表达范围。损失函数用MSELoss对应机器学习里的均方误差既能把大误差放大又方便后续计算RMSE。优化器选Adam学习率设1e-4是比较稳的起点遥感样本量不大时可以先用这个值跑几十个epoch观察loss曲线再调。Dropout设0.2是给全连接层加一点正则化防止站点样本少时模型把训练集背下来。in_features这个参数要和训练表的特征列数严格对齐少一个多一个都会在第一次forward时报shape错。3.3 TOA反演PM2.5.ipynb训练、评估、出图一气呵成Notebook在这个项目里起的是串联作用读取Deep.py训练好的模型在整景影像上逐像元反演PM2.5并把结果可视化。训练阶段通常也在Notebook里跑一轮方便边跑边看指标。import matplotlib.pyplot as plt import numpy as np y_true valid_y.numpy() y_pred model(valid_x).detach().numpy() r2 1 - np.sum((y_true - y_pred) ** 2) / np.sum((y_true - y_true.mean()) ** 2) rmse np.sqrt(np.mean((y_true - y_pred) ** 2)) plt.figure(figsize(6, 6)) plt.scatter(y_true, y_pred, s8, alpha0.6) plt.plot([y_true.min(), y_true.max()], [y_true.min(), y_true.max()], r--) plt.xlabel(站点实测 PM2.5 (ug/m3)) plt.ylabel(模型预测 PM2.5 (ug/m3)) plt.title(fR2{r2:.3f} RMSE{rmse:.3f}) plt.tight_layout() plt.savefig(pred_vs_obs.png, dpi300)散点图是反演类毕设的必备输出答辩老师几乎必看。红色虚线是1:1参考线点越贴近这条线说明预测越准。R²的计算公式里用到了预测值和真实值的方差比数值越接近1越好RMSE的量纲和PM2.5浓度一致比如RMSE15意味着平均误差在15微克每立方米左右。这里有个细节valid_x要和valid_y按行严格对齐一旦前面合并训练表时排序出了问题散点图会出现“预测值和实测值对不上”的混乱分布特征提取那段脚本就得回头查。4. 常见问题与避坑从文件路径到验证集划分这部分是复现过程中最值钱的内容。我在拆这类反演毕设时踩过的坑基本都集中在路径、坐标系、数据预处理和验证集划分这四类问题上。每一条都是从真实run出来的报错里总结的现象、原因、解决按顺序写清楚。4.1 No such file or directory先检查路径分隔符和文件名现象运行Data_Extaction_Value_V4.py时直接报FileNotFoundError提示找不到某个tif或CSV。原因脚本里写的是相对路径你当前工作目录不在它预期的地方或者文件名被系统自动“纠正”过比如把Extaction改成了Extraction。解决把脚本里所有路径改成基于os.path.join的绝对路径文件名的拼写保留压缩包原样不要手动修改。4.2 提取出的PM2.5全是NaN坐标系没统一现象站点表和特征表合并后PM2.5列大量为空值或者像元值一列全是nan。原因站点经纬度是EPSG:4326而影像可能是UTM或其他投影坐标系rowcol按影像坐标系解析站点坐标得到的位置完全错误。解决先用pyproj把站点坐标批量投影到影像坐标系再执行取值验证方法是取几个站点坐标打印转换前后的数值确认量级是否合理。4.3 loss不降反升特征和标签量级差太大现象训练几十个epoch后MSE一直维持在很高水平甚至出现发散。原因TOA反射率取值范围在0到1之间而PM2.5浓度在几十到几百两个尺度差了两个数量级梯度更新不稳定。解决特征列用StandardScaler做标准化标签列先做异常值截断比如把大于500的站点记录视为仪器异常直接剔除或clip再进入训练。4.4 一跑就内存爆炸整景影像别直接全读现象8GB内存的机器上rasterio.open之后执行read()直接卡死或被系统杀进程。原因Landsat级别的TOA影像动辄几万乘几万像素全波段读入内存需要占用数十GB。解决用rasterio的window参数分块读取或者在提取像元值阶段只计算站点对应位置的像素不要一次性load整个栅格。数据类型也尽量转成float32能省一半内存。4.5 R²看着很高答辩却说“不严谨”训练验证没按时间切现象随机划分训练集和验证集后R²能到0.95但把预测结果画在空间分布图上看出现明显的影像轨道痕迹。原因同一景影像内相邻像元的TOA反射率高度相关随机划分把同一景的样本同时拆到了训练集和验证集造成信息泄漏。解决按date字段做GroupKFold分组交叉验证保证同一成像时间的样本不会同时出现在训练集和验证集里。5. 把反演结果落回空间时间分组交叉验证与栅格输出毕设想往上走一个档次光有训练散点图是不够的还差两件事一是用时间分组的交叉验证代替单次随机划分让评价指标经得起追问二是把模型预测结果写成tif栅格文件放到ArcGIS里和底图叠加展示。from sklearn.model_selection import GroupKFold groups sample_df[date] # 按成像日期分组避免信息泄漏 gkf GroupKFold(n_splits5) for fold, (tr_idx, va_idx) in enumerate(gkf.split(sample_df, groupsgroups)): train_fold sample_df.iloc[tr_idx] valid_fold sample_df.iloc[va_idx] # 这里复用Deep.py里的模型训练流程逐折训练并记录指标GroupKFold是这里的关键它保证同一时间点的样本整体进入训练集或验证集不会撕裂。每一折训练完都记录R²和RMSE最后取五折平均值作为模型的最终评价指标这个做法在答辩时比“单次随机划分的R²”有说服力得多。with rasterio.open(template_tif) as src: profile src.profile.copy() profile.update(dtyperasterio.float32, count1, compresslzw) with rasterio.open(pm25_pred.tif, w, **profile) as dst: dst.write(pred_grid, 1)pred_grid是模型在整景影像上逐像元预测的结果形状要reshape成(height, width)才能写进tif。用template_tif做模板的好处是投影、分辨率、坐标系这些元数据都自动继承不用手写。我记得自己做第一个反演项目时最难受的一次就是随机划分后R²到了0.9答辩老师问“同一景影像的训练样本和验证样本是不是被切到两边了”当场没接住。从那以后我每次做卫星反演项目都强制走一遍“先按时间分组再交叉验证最后把结果写回栅格”的流程这一步做扎实了整个项目的可信度会上一个台阶。希望帮到你。本文还有配套的精品资源点击获取
返回列表