葵花8 AHI机器学习反演地面太阳辐射完整流程
发布时间:2026/10/2 4:03:41来源:尧图网络
简介一份面向遥感、气象与环境监测方向开发者及科研人员的完整Python实践项目基于葵花8号气象卫星AHI多光谱传感器数据借助机器学习算法反演地表太阳辐射适用于气候研究、环境监测与光伏能源评估等场景。压缩包共3个文件整体约2.58MB包含已训练模型文件、数据加载与建模脚本及示例卫星数据覆盖从影像读取、特征构建到模型推理的完整链路。已有251人浏览学习。借助压缩包内的模型与脚本可快速复现机器学习遥感反演方案了解监督学习在辐射估算中的特征选择、参数调优与模型验证思路并可基于示例数据检验模型效果进一步扩展至近实时太阳辐射监测系统的开发部署对气候变化应对与灾害预警研究具有实用参考价值。1. 卫星不直接测辐射葵花8 的 AHI 数据怎么靠机器学习算出地面太阳辐射地面太阳辐射数据是光伏选址、农业气象和建筑能耗模拟的刚需但地面辐照度观测站稀疏很多区域根本没有实测。葵花8 卫星的 AHI 传感器能看到整个圆盘10 分钟一景多光谱覆盖可见光到热红外但卫星测的是大气顶的反射辐射不是地面接受到的辐照度。物理反演模型要处理气溶胶、水汽、云等多种参数调起来很繁琐而且在不同地表和大气条件下经常失灵。机器学习把这个问题变成了回归任务用 AHI 的反射率、观测几何和时间信息去拟合地面辐射值效果往往比传统查表法更稳。这份资源包给出的正是完整反演流程适合做太阳能资源评估、遥感反演或相关课程设计的人直接拿来改。2. 反演前的数据底子AHI 波段特点、辐亮度定标与几何参数处理2.1 为什么选葵花8 的 AHI 而不是 MODIS做地面太阳辐射反演数据源选择直接影响模型上限。MODIS 有 36 个波段光谱信息丰富但它是极轨卫星一天过境两次无法捕捉一天内辐射的连续变化。葵花8 是静止轨道卫星固定在东经 140.7 度赤道上空对同一区域每 10 分钟输出一景全圆盘影像时间分辨率远高于极轨卫星。AHI 的波段设置也适合辐射反演可见光 0.47、0.51、0.64 微米反映云和地表反射近红外 0.86、1.6、2.3 微米对植被和水汽敏感热红外波段 10.4、11.2、12.4 微米可以辅助云检测。这套波段组合基本覆盖了辐射传输中关键的散射和吸收窗口。空间分辨率方面AHI 可见光波段最高 0.5 公里红外波段约 2 公里。反演地面辐射不需要太高的空间分辨率2 公里尺度已经能匹配大部分太阳能评估场景而且能避开 MODIS 那样的条带拼接问题。如果做站点尺度的验证把 AHI 数据重采样到站点经纬度附近窗口取平均即可。资源包里的脚本默认按 2 公里分辨率统一处理理由就在这里可见光波段降采样到 2 公里后噪声明显减少训练出的模型更稳定不会因单像元异常导致辐射预测跳变。2.2 辐亮度定标从 DN 值到反射率别跳过这步AHI 原始数据常见的有两个层级一种是 JMA 发布的 HRIT 格式另一种是经预处理的 L1 级 NetCDF。无论是哪种拿到手的第一步都是辐射定标即把原始数字量化值 DN 转换成物理量。可见光与近红外波段需要得到表观反射率红外波段需要得到亮温或辐射亮度。资源包脚本在读入 NetCDF 后会检查数据属性中的 scale 和 offset缺少这一步直接用原始 DN 值训练模型学到的只是传感器响应的线性变换换一个时段的数据立刻失效。import xarray as xr import numpy as np ds xr.open_dataset(AHI_L1_202407151030.nc) # 波段 03 是 0.64 微米可见光提取后做定标 band03 ds[band03].values.astype(np.float64) scale ds[band03].attrs.get(scale_factor, 1.0) offset ds[band03].attrs.get(add_offset, 0.0) refl band03 * scale offset # 表观反射率 refl np.clip(refl, 0.0, 1.2) # 极端值截断防止太阳耀斑带来的异常高值这段代码先把波段数据转为 float64 防止溢出再通过属性中记录的 scale_factor 和 add_offset 完成定标。最后用 clip 限制反射率范围原因是云边和耀斑区可能出现大于 1 的反射率直接保留会影响模型对晴空和云像元的区分。如果你使用的 AHI 数据已经是反射率产品可以跳过这一步但建议仍然打印数值范围确认很多公开数据集的定标系数在不同版本间改过肉眼检查是对黑匣子的基本尊重。太阳天顶角余弦值是辐射反演中最强的单变量特征之一需要单独计算。AHI 产品的几何文件通常提供每个像元的太阳天顶角若只有时间戳和经纬度可以用 pysolar 或 astropy 按过境时间计算然后重采样到波段网格from pysolar.solar import get_altitude from datetime import datetime, timezone lat, lon 30.5, 114.2 dt datetime(2024, 7, 15, 2, 30, tzinfotimezone.utc) altitude get_altitude(lat, lon, dt) # 太阳高度角度 cos_sza np.cos(np.radians(90.0 - altitude)) # 转为天顶角余弦这里用的是站点经纬度而不是像元中心经纬度因为全圆盘影像中远离星下点的区域像元几何形变大站点位置处的几何参数才是实际观测时刻的太阳位置。如果数据产品自带几何波段优先用产品值自算几何仅作为补充或校验手段。2.3 云像元过滤不滤云模型会拼命学云的特征地面太阳辐射反演有个天然矛盾云是影响辐射最大的因子但可见光通道里云和地表在反射率上有重叠模型容易把厚云判成高反射率地表。资源包里的做法是先做云掩膜再分晴空与云天分别建模。最简单可靠的云掩膜用红外亮温差实现云顶亮温低地表在 11 微米附近的亮温通常高于 270K取 10.4 微米与 12.4 微米亮温差可以识别卷云。bt11 ds[band14].values * scale offset # 10.4 微米亮温 bt12 ds[band15].values * scale offset # 12.4 微米亮温 cloud_mask (bt11 270.0) | ((bt11 - bt12) 2.0)第一项用绝对亮温 270K 区分低云和地表第二项是分裂窗差值识别卷云。单靠阈值会误伤高海拔冷地表比如青藏高原冬季地表亮温低于 270K会被当成云。保险做法是叠加可见光反射率判断反射率大于 0.4 且亮温低于 280K 才是云。你可以在资源包的预处理脚本里看到这套组合判断逻辑实际使用时建议根据你研究区域的气候特性微调阈值。3. 特征工程与训练集构建不是把所有波段丢给模型就完事3.1 波段相关性分析选特征先看冗余AHI 16 个波段中不少是相关的。0.47 和 0.51 微米都受瑞利散射影响晴空下二者反射率高度相关近红外 0.86 与 1.6 微米在植被覆盖区也强相关。把全部波段堆给模型不是不行随机森林能容忍一定冗余但会导致训练时间变长、模型解释性变差尤其在样本量不大的情况下还容易过拟合。资源包脚本内置了相关性筛选逻辑先计算各波段与辐射真值的 Pearson 相关系数再计算波段之间的相关系数保留与真值相关高、且互相相关低于 0.85 的波段。import pandas as pd # df 每一行是一个样本特征列 辐射真值列 corr_target df.corr()[ghi].abs().sort_values(ascendingFalse) drop_list [] for i in range(len(corr_target.index)): for j in range(i 1, len(corr_target.index)): f1, f2 corr_target.index[i], corr_target.index[j] if f1 ghi or f2 ghi: continue if abs(df[[f1, f2]].corr().iloc[0, 1]) 0.85: # 保留与目标相关性更高的那个去掉另一个 drop_list.append(f2 if corr_target[f1] corr_target[f2] else f1) features [c for c in df.columns if c not in set(drop_list) and c ! ghi]这段循环按 0.85 阈值做冗余筛除保留与地面辐射相关性更高的波段。0.85 的经验值来自常见遥感特征选择实践你如果用 XGBoost 这类对冗余不敏感的模型可以放宽到 0.92但如果你用线性模型或 BP 神经网络建议收紧到 0.8。资源包默认给出的特征子集是 0.47、0.64、0.86、1.6、2.3 微米反射率加上太阳天顶角余弦和相对方位角共 7 个特征。实测中这组特征能覆盖约 90% 的解释信息增加更多波段对精度提升有限。3.2 辐射-几何-时间三元特征为什么几何参数比部分波段还重要地面太阳辐射的物理机制是辐射量等于大气层顶辐射乘以大气透过率。大气层顶辐射由太阳常数和太阳天顶角决定因此太阳天顶角余弦本身就是辐射值的下界估计。把 cos(SZA) 作为特征等于给了模型一个物理锚点模型只需要学透射率的修正项。观测几何中还有一个容易被忽略的参数是相对方位角即太阳方位角与卫星观测方位角的差值它影响地表二向反射在可见光波段中会带来显著的方向性变化。时间特征是必要的补充。葵花8 覆盖范围内季节变化明显太阳高度角逐日变化只给模型瞬时几何参数而不给日期模型无法区分同一几何角出现在冬季还是夏季。资源包中的常用处理是把日期转为年积日和当地太阳时两个连续变量年积日用正弦余弦编码避免 12 月 31 日与 1 月 1 日的跳变。df[doy_sin] np.sin(2 * np.pi * df[doy] / 365.25) df[doy_cos] np.cos(2 * np.pi * df[doy] / 365.25) df[hour_local] df[hour_utc] 8.0 # 东八区示例按目标区调整正弦余弦编码保证了 1 月 1 日和 12 月 31 日在特征空间中是相邻的不会出现数值上的断裂。当地太阳时的计算要考虑经度修正单用 UTC8 在西部省份会有明显偏差建议用经度除以 15 做修正。这套编码在资源包的多处脚本中都有体现也是模型在跨季度预测时不掉链子的关键。3.3 训练集构建站点匹配、时间对齐与样本平衡训练样本来自地面站点。常见做法是取卫星过境时刻前后 10 分钟内的地面辐射平均值作为真值与 AHI 影像像元对应。这里有三个细节直接影响样本质量第一地面辐射计观测的是水平面总辐射 GHI而卫星像元对应的物理量是大气顶反射率两者之间是透过率关系模型学习的是这个非线性映射第二站点经纬度所在像元和周围 3x3 像元窗口的均值更稳定单像元容易受配准误差影响第三站点数据需要质量控制剔除辐射值异常、太阳高度角过低和仪器维护时段的数据。# 假设站点观测为逐分钟数据提取卫星过境时刻前后10分钟均值 obs_time pd.Timestamp(2024-07-15 02:30:00, tzUTC) window obs_time - pd.Timedelta(minutes10), obs_time pd.Timedelta(minutes10) ghi_mean station_df.loc[window[0]:window[1], ghi].mean() sample {ghi: ghi_mean, cos_sza: cos_sza, band03: refl_3x3}这里取了 20 分钟的观测窗口取平均能有效平滑辐射计的瞬时波动。资源包训练集默认只保留太阳高度角大于 5 度的样本原因是低角度下大气路径长、辐射值小观测噪声相对大且卫星观测几何不佳。样本平衡上晴天和云天样本比例如果不控制模型会偏向样本多的那一类。常见方式是分别统计晴空和云天样本量按较少类别的数量对较多类别做不放回采样或给少数类更高的样本权重。4. 模型训练与调参随机森林、XGBoost 和 LightGBM 的取舍4.1 模型选型逻辑先跑基线再看复杂度辐射反演的机器学习模型不需要一上来就上深度学习。AHI 波段数和特征总数在几十量级样本量如果是数万到数十万树模型已经能拟合大部分非线性关系而且训练快、调参直观、可解释性也好。资源包里的基线模型是随机森林n_estimators 设为 300max_depth 限制在 12min_samples_leaf 设为 5。这么设的原因在于辐射反演不是要完美拟合训练集而是要在地理外推时保持稳定树深度过大容易记住特定站点的大气特征。如果随机森林精度不够再换 XGBoost 和 LightGBM。两者都支持正则化对特征尺度不敏感训练速度比随机森林快一个量级。XGBoost 在中小数据集上通常表现更稳LightGBM 的直方图算法在大样本上占优势。资源包的对比实验中样本量小于 10 万时 XGBoost 的 R² 略高于 LightGBM超过 10 万后两者基本持平但 LightGBM 训练时间只有前者三分之一。如果你只是为了课程设计或验证方法随机森林足够了如果要做业务级精度可以重点调 XGBoost 的 max_depth 和学习率。4.2 数据划分随机划分是最大的错误时间序列数据最忌讳随机打乱后划分训练集和测试集。卫星影像和站点观测都有强时间自相关相邻时刻的样本高度相似随机划分会让模型在测试集上偷看到邻近时刻的信息验证指标虚高。正确做法是按时间顺序划分例如用 2023 年 1 月到 10 月的数据训练11 月到 12 月验证再用 2024 年数据测试。资源包里三种划分方式都有默认推荐的是时间和空间双重划分。train df[df[time] 2024-01-01] val df[(df[time] 2024-01-01) (df[time] 2024-04-01)] test df[df[time] 2024-04-01]空间上的划分更严格选择某些站点只用于训练、另一些站点只用于测试检验模型的地理泛化能力。很多卫星反演模型在训练站点上精度很高一换站点性能立刻下降问题就出在地表类型差异上。如果资源包允许按站点拆分我会优先这么做因为它更贴近实际应用场景——你最终要把模型用到没有地面观测站的地方。4.3 关键超参数与调参方向核心超参数就那么几个树模型的 max_depth 控制单棵树复杂度learning_rate 控制学习速度subsample 和 colsample_bytree 控制随机性。经验规律是先固定 learning_rate 为 0.05用网格搜索确定 max_depth 在 6 到 12 之间的最优值然后增大 n_estimators观察验证集损失是否继续下降如果过拟合明显加大 min_child_weight 和 subsample。import xgboost as xgb params { objective: reg:squarederror, max_depth: 8, learning_rate: 0.05, subsample: 0.8, colsample_bytree: 0.7, min_child_weight: 3, eval_metric: rmse, } dtrain xgb.DMatrix(X_train, labely_train) dval xgb.DMatrix(X_val, labely_val) bst xgb.train( params, dtrain, num_boost_round2000, evals[(dval, val)], early_stopping_rounds50, verbose_eval100, )colsample_bytree 设为 0.7 意味着每棵树只用 70% 的特征这能降低特征间的共线性影响。early_stopping_rounds 设为 50验证集 RMSE 连续 50 轮不下降就停止避免过拟合。注意这里的 eval_metric 用 RMSE 而不是 R²因为 RMSE 直接反映辐射值误差的大小单位是瓦每平方米更容易和业务需求挂钩。调参的一个底线原则是每改一次参数都要重新按时间划分验证绝不能用测试集反复试否则测试集就变成了训练集的一部分。4.4 模型对比与评估口径评估时不能只报告 R²。R² 对异常值不敏感而辐射反演中最怕的是在阴天边缘时刻预测偏差大。资源包里统一用三个指标R²、RMSE 和 MAPE。RMSE 反映大误差MAPE 反映相对误差但 MAPE 在辐射值接近零时会爆炸所以只在太阳高度角大于 10 度的样本上计算。晴天和云天样本分别统计也很重要因为晴天的 RMSE 通常只有几十瓦每平方米云天会到一百以上混在一起统计会把晴天的优势掩盖掉。模型对比表按数据段划分晴空、云天、全部。如果你的资源包里只有随机森林脚本而没做对比建议至少跑一个简单线性回归作基线。辐射反演问题中线性回归用同样的特征通常能拿到 0.85 左右的 R²如果树模型连 0.88 都达不到说明特征或数据处理有问题不是模型的问题。这个排查思路能在训练早期快速发现问题。5. 避坑与常见问题反演结果偏低或发飘的五类根源5.1 现象晴空反演结果整体偏低 20 到 40 瓦每平方米原因分析地面辐射真值用的是水平面总辐射 GHI而模型输入的表观反射率受大气分子散射影响晴空下瑞利散射会抬高可见光波段的反射率。模型学到的是反射率与 GHI 的关系如果训练集里缺少低气溶胶、高透明度的高辐射样本模型对晴空高值区的外推能力不足预测结果就会整体偏低。解决方案先检查训练集辐射真值的分布看最大值是否超过 1000 瓦每平方米。如果最大只有 900 左右说明缺少夏季正午的强辐射样本。常见做法是按太阳高度角分层采样确保 cos(SZA) 大于 0.8 的样本占比不低于 15%。另一个补救措施是给特征中加入气溶胶光学厚度 AOD 产品数据如果没有外部 AOD可以用 0.47 和 0.64 微米波段的比值做近似代替瑞利散射在短波更强比值偏离理论值的程度能间接反映气溶胶负荷。5.2 现象模型在冬季表现尚可夏季误差突然增大原因分析夏季太阳高度角高地表辐射强但也是对流云高发季节。云的种类多样积云边缘的反射率梯度大AHI 的 2 公里分辨率无法完全分辨云的边界。一个 2 公里像元内含半云半晴平均反射率对应着一个不存在的辐射状态模型给出的预测值也落在非晴非云的中间区域误差自然大。解决方案有两种路径。一是过滤掉混合像元用 3x3 窗口内反射率的变异系数做筛选变异系数大于 0.3 的样本直接丢弃这类样本本身代表空间不均匀站点观测的 20 分钟均值也难以代表面尺度辐射。二是单独训练云天模型和晴空模型把问题拆开。资源包做法是同时保留两条路径先分类后回归。5.3 现象模型在 A 区域验证很好换到 B 区域性能骤降原因分析训练站点集中在单一地表类型上。例如站点都在城市周边训练样本的地表反射率特征主要来自建筑和裸土换到植被茂密的区域近红外波段的反射率特征完全不同模型学到的映射关系失效。这是空间外推失败的典型案例。解决方案确认训练集站点覆盖的经纬度范围是否与实际应用区域一致不一致时至少要保证特征空间覆盖度足够。一个实用做法是统计训练站点 NDVI 的分布计算方式是 (0.86 微米反射率 - 0.64 微米反射率) 除以二者之和然后用核密度匹配保证应用区域的 NDVI 值落在训练集的覆盖区间内。超出覆盖范围的像元预测结果应标记为低置信度。5.4 现象白天时段预测稳定日出日落时段误差明显原因分析太阳高度角低时大气路径增长气溶胶和水汽的影响被放大而 AHI 在低角度下的观测几何导致反射率的信噪比下降。另外训练样本中低角度样本占比天然少模型在该区域拟合不充分。误差集中在日出后和日落前两小时。解决方案对低太阳高度角样本单独训练一个校正模型或直接在这些时段降低模型输出的权重。资源包里更实用的做法是预测结束后用太阳高度角余弦加权的局部线性回归对残差做一次薄板样条校正输出的最终 模型预测值 校正值。这个技巧能显著改善日出日落时段的连续性。5.5 现象预测值出现明显条带或块状噪声原因分析AHI 影像在拼接和重采样过程中可能出现行与行之间的亮度差异尤其在全圆盘边缘区域。如果训练时没有对输入影像做空间平滑模型会把这种条带噪声当成真实反射率特征。另一种可能是辐亮度定标参数在影像边缘部分失效导致反射率值偏移。解决方案在预处理中增加一步 3x3 中值滤波只对反射率特征做不动原始影像。中值滤波能有效去除椒盐噪声而不模糊云边界。同时建议在建模前把所有特征矩阵标准化但不要用全局均值方差而是按月份分别标准化。辐射值的季节变化显著全局标准化会压缩夏季特征的变化范围导致季节性的预测精度下降。6. 验证指标与进阶用法从单时刻反演到批量处理管线6.1 验证指标怎么算才能真实反映模型能力验证时按天聚合再计算指标比按样本直接计算更符合业务需求。站点观测和卫星观测在样本级别上的随机误差会在日均值中抵消一部分按天计算 RMSE 更能反映实际日累积辐射预测的精度。具体做法是先对每个站点每天做平均再在日平均值上计算 R² 和 RMSE。daily_pred test_df.groupby([station, date])[pred].mean() daily_true test_df.groupby([station, date])[true].mean() rmse_daily np.sqrt(((daily_pred - daily_true) ** 2).mean())如果你关注的是光伏发电量还要单独计算日累积辐射量误差。瞬时辐射的 RMSE 达到 80 瓦每平方米并不算大问题但累计到一天可能导致日辐射总量偏差百分之十五以上。这个指标最容易让业务方理解模型的价值。资源包脚本输出的评估报告里包含瞬时和日累积两种统计口径建议你在实际项目中保留同样的双口径分析。6.2 批量处理管线单景影像怎么拓展到全年把单景预处理脚本扩展成批量管线有三个关键改动一是按文件时间自动排序并记录处理状态防止中断后重复计算二是为每个站点建立独立的输入文件避免特征拼接时索引错乱三是把模型预测和验证分成两个独立脚本训练只用历史数据预测只读取最新影像。推荐用配置文件管理路径和参数而不是硬编码在脚本里。python preprocess.py --input ./AHI_netcdf/ --output ./features/ --config config.yaml python train_model.py --features ./features/train/ --model ./output/model.pkl python predict_batch.py --features ./features/infer/ --model ./output/model.pkl --out ./output/prediction.nc三个命令行脚本各干一件事配上配置文件后在服务器上可以丢进 crontab 定时执行。实际部署时要注意内存管理葵花8 全圆盘单景数据大小在几百兆到 1G 之间一年数据量可观建议按天分批处理处理完压缩特征表并删除元数据。6.3 进阶方向分季节建模与极端辐射值修正提升精度的两个实用技巧分季节建模和极端值修正。把训练集按气象季节分成四个子集分别训练四个模型预测时根据日期自动选用对应模型这样能避开季节不stationary问题。极端值修正针对的是高辐射晴空场景随机森林预测的高辐射值容易偏低因为树模型无法超出训练集最大值的外推限制。常见做法是二次建模对残差大于阈值的高辐射样本单独训练一个线性回归叠加到主模型输出上。从资源包整理出的这整套流程我在自己的光伏资源评估项目中跑了不下十遍。从那以后我每次换区域或者换数据集都强制走一遍同样的路线先画特征相关性矩阵再按时间划分验证最后按天聚合评估三条缺一不可避免了很多后续返工。整个流程的主体框架、参数设置和处理思路都在资源包里下载后对照本文逐节复现跑通一条站点到辐射预测的完整链路不会太费周折希望帮到你。本文还有配套的精品资源点击获取
网站建设高端定制企业官网