摘要
本次工作的目标是构建一套可用于生态分类更新的 LightGBM/XGBoost 模型,而不是直接制作某一期生态分类数据。模型建设包含两个能力目标:第一,能够利用已有生态分类数据作为监督样本来源,学习生态类型与 Sentinel-2 遥感影像、地形、土壤等特征之间的关系;第二,模型在应用时能够接收最新年份的 30m 特征数据,从而具备输出新一期、更高分辨率生态分类结果的能力。
本文整理生态分类模型 LightGBM/XGBoost 路线的理论基础、数据组织、样本构建、特征工程、模型训练、模型推理和后处理方法。该路线的核心思想是:把已有 90m 生态分类图作为训练监督来源,而不是作为需要机械细化的最终产品;先在 90m 标签尺度上提取高置信度样本点,再为这些点读取 30m Sentinel-2 三季光谱指数、地形、土壤、ESA 等预测期可用特征,训练 LightGBM/XGBoost 表格模型。模型训练完成后,可在目标年份最新特征上按 R1-R9 分区推理,输出新的生态分类图作为模型应用成果。
关键词:生态分类模型;LightGBM;XGBoost;Sentinel-2;高置信度样本;30m 推理;JRC Global Surface Water;EMC-BUILT;分区模型;全国统一模型
过程概览
本次实操不是单纯训练一个分类器,而是围绕“已有 90m 生态分类如何更新为目标年份 30m 生态分类产品”建立完整流程。实操过程可以概括为四条主线:先把样本和特征做干净,再训练分区与全国模型,再用图件发现空间问题,最后通过 JRC/EMC 后处理把初始预测修正为可交付结果。
重点过程如下:
- 先用 R8 试点跑通流程。从 R8 高置信度样本开始,验证 Sentinel-2 三季特征、地形、土壤、ESA 等数据能否合并成训练表,并完成 LightGBM/XGBoost 训练和 10km tile 预测。
- 发现并排除特征泄漏。早期
all_numeric诊断模型虽然能跑出结果,但包含confidence_score、图斑面积、边界距离、邻域一致性等标签侧 QC 字段,正式模型改为只使用预测期可获得的spectral_env特征。 - 修正标签编码问题。训练过程中发现
3100/3200/3400/6200是误混入的二级编码,不应作为三级终端类训练。随后生成no_level2_codesfiltered 训练表,并重训 R1-R9 分区模型和全国统一模型。 - 用图件检查空间表现。对 R8 10km tile 生成四模型对比图、置信度图、差异掩膜图和单模型带图例图。图件显示,R8
regional XGBoost指标较好,但主水体仍被切分为4201/4202,说明仅靠测试集精度不能判断产品质量。 - 把 JRC 从普通特征改为后处理约束。试验表明,JRC 直接入模不能稳定解决大水体内部类别分裂,因此改为在预测后用 JRC 水体证据做拓扑一致性修正和 QA 标记。
- 加入 EMC-BUILT 约束城市绿地语义。
6206 城市草本绿地不能只由 NDVI 或光谱决定,需要结合建成环境比例、到建成区距离和 Greenness 有效性进行判断。 - 明确迁移时 Sentinel-2 必须先标准化。输入影像可以来自任意 CRS,但进入预测前必须校验并统一到中国 Albers 30m 网格;光谱和指数用
bilinear,SCL 用nearest。
本次实操最关键的改进有三点:第一,训练目标从旧 baseline 修正为no_level2_codes,避免二级编码污染三级分类;第二,模型选择不只看表格指标,而是结合 R8 10km 图件诊断空间问题;第三,最终产品不直接使用初始pred_level3,而是必须经过 JRC/EMC v4 后处理生成post_level3。
因此,本文档后续内容按照“方法、结果、问题、图件诊断、后处理、部署迁移、训练改进记录”的顺序展开。读者需要重点关注的不是某一次 test accuracy,而是从样本清洗到后处理 QA 的完整闭环。
模型训练
高置信度样本提取
样本提取阶段只看标签侧,不使用 Sentinel-2、DEM、HWSD 等特征。这样做的好处是避免把外部数据误当成标签来源,也避免因为某个特征质量不稳定而污染样本标签。
核心步骤包括:
- 从原始 90m 标签中过滤
nodata=65535、0和无法匹配编码表的值。 - 生成 I/II/III 级标签图。
- 在每个层级计算连通图斑、图斑面积、边界距离和腐蚀核心区。
- 计算 3×3、5×5 邻域同类比例。
- 结合空间网格和图斑 ID 做去聚集抽样。
- 输出样本点表、统计表和 split 字段。
这一步回答的问题是:“哪些 90m 标签像元足够可靠,可以作为训练监督来源?”
额外处理:
在原始数据中,存在混入的二级分类标签,必需祛除,不然后续会带来二级分类和三级分类同时存在的情况。
特征工程
训练表的每一行对应一个高置信度样本点。字段可以分为四类:
标识字段:sample_id、region_id、split、row_90m、col_90m 标签字段:level1_code、level2_code、level3_code、生态类型名称 模型特征:三季 Sentinel-2、地形、土壤、ESA 等 QA 字段:观测质量、缺失率、ESA 冲突标记等模型训练只使用预测期可获得的特征。confidence_score、边界距离、图斑面积、邻域一致性等标签侧 QC 字段不能作为正式预测特征,因为未来 30m 预测时没有这些标签侧信息。历史诊断试验表明,把这些字段放进模型会造成明显特征泄漏。
模型训练
当前训练目标是level3_code。正式有效训练表必须满足:
level3_code not in (3100, 3200, 3400, 6200)训练路线分为两类:
分区模型:R1-R9 每个生态区分别训练 LightGBM/XGBoost 全国统一模型:合并 R1-R9 filtered 样本训练一个全国模型分区模型的优势是更贴近区域生态差异,空间解释更直接;全国统一模型的优势是样本量更大,对某些小样本类别或相邻生态区共享规律可能更友好。当前策略不是预设谁一定更好,而是训练后按每区指标、类别级 F1 和代表 tile 空间 QA 决定候选默认模型。
评估指标包括:
accuracy macro F1 weighted F1 per-class precision/recall/F1 confusion matrix其中 macro F1 对小样本类别更敏感,weighted F1 更受主导类别影响。生态分类不能只看 overall accuracy,否则容易掩盖稀有湿地、河流、城市绿地等小类问题。
主要问题及改进
原始的数据
这是90m分类标签的原始数据。
这是春夏秋的Sentinel-2的数据(RGB合成)
卫星图像
水体分裂
下图有中间一张,本来联通的水体,在三级分类体系中分为两类:
| 4000 | 湿地生态系统 | 4200 | 湖泊 | 4201 | 湖泊 | 自然水面,静止 |
|---|---|---|---|---|---|---|
| 4000 | 湿地生态系统 | 4200 | 湖泊 | 4202 | 水库/坑塘 | 人工水面,静止 |
但,根据上面的RGB图形,明显可知,不管是自然水面还是人工水面,大范围的水体只可能是一类,当然对于新丰江水库这种体量来说,其分为湖泊还是水库都是行得通的,我们的目标就是处理掉分裂,在水体联通下的情况下,只分为一种水体。
我们加入JRC Global Surface Water 水体数据用来稳定水体产出,但把数据加入到训练特征后,并没有使数据更好。主要原因是原始数据中就存在大量的水体分裂问题,见下图左。
我们将其加入了后处理,即在水体联通时,只判断为一种水体,占比多的那种水体为最终结果。
下图右侧为最终结果。
JRC 水体约束总结:
JRC Global Surface Water 提供 occurrence、recurrence、maximum extent 等长期水体信息。由于在光谱特征中无法区分自然水体和人工水体,因此使用方式是不将数据加入到训练过程,而是预测后处理和 QA,不替代 2023 生态类型标签。
稳定水体可以初步定义为:
occurrence >= 90 AND recurrence >= 90在 R8 filteredregional XGBoost10km 示例中,JRC/EMC v4 后处理将初始4201=17772、4202=48027调整为后处理后的4201=2、4202=65802,unified_4201_4202_pixels=17770,基本消除了同一大水体内部的4201/4202分裂。
需要注意,后处理后 90m 标签采样 agreement 可能下降,因为原始 90m 标签本身在同一连续水体中混有4201/4202。这时不能只看 agreement,而要看连续水体斑块一致性、JRC 水体证据和人工核查。
区域内的jrc数据见下图:
EMC-BUILT 建成环境约束
6206 城市草本绿地的关键词不是“草本”,而是“城市”。因此判断它不能只看 NDVI,也要看是否位于人工建成环境内部或附近。
EMC-BUILT Total RES+NRES 用于派生:
emc_built_fraction_30m distance_to_emc_built emc_built_fraction_300mEMC-BUILT Greenness 作为建成环境绿度有效性信号。后处理会对远离建成环境、靠近稳定水体或历史淹水范围的可疑6206做 flag 或在概率支持时重分配。这样能减少水库岸线、消落带附近的城市绿地误判。
下图展示了原始数据、初始预测结果和经过jrc+emc处理后的结果,以及差异。
是全国模型还是分区模型
全国 30m 生态分类不适合一次性生成一张巨大的全国特征栈。当前工程策略是:
R1-R9 分区 -> 每区按 tile 处理 -> 三季 Sentinel-2 标准化 -> 环境特征对齐或采样 -> 表格模型推理 -> JRC/EMC 后处理 -> tile QA -> 分区拼接 -> 全国边界检查生态类型分类不是单纯土地覆盖分类。土地覆盖更多回答“地表看起来是什么”,例如水体、林地、草地、农田、建筑;生态分类还需要回答“这个地表在什么生态背景中形成”,例如同样是草本植被,在东北平原、内蒙古草原、青藏高原、南方丘陵和城市建成区中,生态含义并不相同。
如果不进行生态分区,而是把全国样本直接放入一个模型中,模型会遇到明显的“同谱异类”和“异谱同类”问题:
同谱异类:光谱相似,但生态类型不同。 异谱同类:生态类型相同或相近,但因气候、物候、地形不同,光谱表现差异很大。例如,高 NDVI 在东北可能对应森林或湿地植被,在华北可能对应农田,在南方可能对应常绿阔叶林或水田,在城市周边可能对应人工绿地。仅靠一个全国统一阈值或统一模型,很容易把区域生态背景差异误当成类别差异,或者把真实类别差异平均掉。
统一步骤训练全国模型和分区模型,发现,分区模型优于全国模型,与理论一致。
讨论:优势和边界
优势
第一,避免 90m 标签直接复制到 30m 带来的训练噪声。高置信度样本机制把标签尺度问题显式处理掉。
第二,工程成本可控。训练阶段只提取样本点特征,不需要保存全国完整 Sentinel-2 特征栈;预测阶段按 tile 流式处理。
第三,模型解释性较强。LightGBM/XGBoost 可以输出特征重要性、类别报告、混淆矩阵,方便定位问题类别。
第四,模型应用链条可追踪。每个 tile 都有初始预测、置信度、后处理 flags 和 QC JSON,便于复核和回滚。
局限
第一,三级生态类型中有些类别本来就难以仅靠 30m 光谱和静态环境特征区分,尤其是森林细分类、湿地细分类、河流/水渠、小样本城市绿地等。
第二,样本仍来自既有 90m 标签,模型上限受标签质量约束。高置信度抽样能减少噪声,但不能凭空创造更高质量真值。
第三,后处理规则需要持续积累代表 tile 的 QA 证据。JRC/EMC 规则不能机械扩大到所有问题类别,必须保持“有证据才修改,有不确定就 flag”的原则。
第四,分区模型和全国统一模型没有绝对优劣。部分区全国模型更好,部分区分区模型更稳,正式应用时需要按区选择并检查边界连续性。
结论
全国生态分类 LightGBM/XGBoost 路线的核心,不是简单地把遥感影像丢给一个树模型,也不是把已有 90m 生态分类图机械细化为 30m。它的核心任务是:利用已有生态分类数据构建可更新的生态分类模型,使模型能够结合目标年份最新遥感和环境数据,输出新一期、更高分辨率的生态分类结果。围绕这个任务,需要建立标签尺度、样本置信度、多季特征、生态分区、模型对照、空间后处理和 QA 追踪组成的完整模型工作流。
当前 filteredno_level2_codes重训已经完成,证明该路线具备全国扩展基础。下一阶段的重点不是再下载更多 Sentinel-2,也不是重新提取已有样本点,而是:
- 基于 filtered 模型继续做分区模型 vs 全国统一模型的类别级诊断。
- 为每个 R 区选择代表 tile,执行初始预测和 JRC/EMC 后处理 QA。
- 按区确定候选默认模型,而不是全国一刀切。
- 建立模型应用级 tile 网格、标准化输入、后处理和产品导出流程。
- 从最终
post_level3_30m.tif统一导出 GEP、GB/T42340 和 HJ 1166 三套分类产品。
一句话总结:这条路线不是“旧图细化工具”,也不是单次“生态分类数据制作流程”,而是一套“生态分类更新模型”。它把已有 90m 生态分类监督、目标年份 30m 遥感环境特征和全国模型应用之间的关系,拆解成可训练、可预测、可后处理、可质检的工程问题。LightGBM/XGBoost 是其中的模型核心,但真正决定模型质量的,是从样本到后处理的整套方法闭环。
训练和改进流水账
本节记录的是模型从试跑到当前可迁移流程之间遇到的问题、产生的中间结果、做过的图件和相应改进。它不是最终指标表的重复,而是说明“为什么后来要这样做”。
第一阶段:R8 试点,先验证表格模型路线能否跑通
最初没有直接做全国模型,而是先以 R8 为试点区。原因是生态分类数据、Sentinel-2、DEM、土壤和 ESA/JRC/EMC 等数据源很多,如果一开始全国展开,任何一个环节出错都会很难定位。
这一阶段的目标是打通:
90m 高置信度样本 -> Sentinel-2 样本级特征 -> 地形 / HWSD / ESA 特征合并 -> LightGBM / XGBoost 训练 -> R8 10km tile 预测 -> 图件和 QA 检查最初做过一个all_numeric诊断模型,把训练表里所有数值字段都放进模型。这个试验的作用是验证模型脚本、数据读取、split 和评估流程能不能正常工作。但后来发现all_numeric包含了confidence_score、图斑面积、边界距离、邻域一致性等标签侧 QC 字段,这些字段在未来 30m 预测时不可获得,会造成特征泄漏。因此该结果只保留为诊断,不作为有效模型。
改进措施:训练脚本train_tabular_baseline.py默认改为feature-mode=spectral,随后增加feature-mode=spectral_env。正式模型只使用预测期可获得的特征:Sentinel-2 三季光谱/指数、地形、ESA、HWSD 土壤等。
这个阶段形成的经验是:模型分数高不一定可信,必须先检查特征是否在预测期可获得。否则模型是在“偷看标签侧信息”。
第二阶段:从 summer 单季到三季
R8 试点先使用 summer 单季 Sentinel-2 特征训练模型。单季模型能够工作,但许多生态类型存在季节性差异,单季光谱不足以稳定区分森林、草地、湿地、农田和城市绿地等类别。
随后把 Sentinel-2 扩展为春、夏、秋三季,并合并地形和土壤特征,形成三季spectral_env训练表。改进方向包括:
1. 使用 spring / summer / autumn 三季 Sentinel-2。 2. 保留 B02-B12 主要波段和 NDVI/EVI/NDWI/MNDWI/NBR/NDMI/RENDVI 指数。 3. 对光谱波段增加 3x3 均值,提供局部纹理和邻域信息。 4. 合并 DEM、slope、aspect、aspect_sin、aspect_cos。 5. 合并 HWSD SMU 和 soil_* 土壤属性字段。 6. 保留 ESA WorldCover 作为外部辅助特征和 QA 证据。中间结果表明,spectral_env相比单季 spectral 有明显提升。R8 三季spectral_env旧 baseline 中,LightGBM test accuracy 约0.6590,XGBoost test accuracy 约0.6608。这证明表格模型路线是有效的,但也暴露了后续两个问题:标签编码里混入了二级编码,空间预测结果还存在水体分裂和城市绿地误判。
第三阶段:发现二级编码混入,废弃旧 baseline
在全国扩展和结果复核过程中,发现原始标签中有四个二级编码直接作为分类值出现:
3100 草甸 3200 草原 3400 草丛 6200 城市绿地早期做法曾把它们按“终端类”保留,旧 baseline 也是在这个基础上训练的。后来重新检查分类体系后确认,这四个值不是有效三级终端训练类,而是错误混入的二级编码。继续保留会带来两个问题:
1. 模型会学习到不应作为最终预测类别的二级码。 2. 标准分类映射和产品导出阶段会出现语义不一致。改进措施:不重新提取样本、不重新下载 Sentinel-2,而是复用已经生成的 R1-R9 三季spectral_env表,直接过滤level3_code in (3100, 3200, 3400, 6200),生成no_level2_codesfiltered 训练表,并重新训练 R1-R9 分区模型和全国统一模型。
过滤后的行数如下:
| 区域 | 过滤前 | 过滤后 | 剔除 |
|---|---|---|---|
| R1 | 38667 | 35615 | 3052 |
| R2 | 34450 | 30843 | 3607 |
| R3 | 36288 | 33815 | 2473 |
| R4 | 48553 | 41955 | 6598 |
| R5 | 28103 | 25332 | 2771 |
| R6 | 78058 | 69753 | 8305 |
| R7 | 45364 | 39298 | 6066 |
| R8 | 21157 | 19590 | 1567 |
| R9 | 37869 | 30022 | 7847 |
| 全国 | 368509 | 326223 | 42286 |
第四阶段:R1-R9 分区模型与全国统一模型重训
filtered 训练表生成后,重新训练了 R1-R9 分区 LightGBM/XGBoost 和全国统一 LightGBM/XGBoost。全国统一模型训练时必须显式传:
--region-id ""这是因为训练脚本默认--region-id R8,如果不传空字符串,全国训练会被错误过滤成 R8。
重训后的主要结果是:
| 区域 | 暂选模型 | test acc | weighted F1 | macro F1 |
|---|---|---|---|---|
| R1 | XGBoost | 0.7149 | 0.7079 | 0.4779 |
| R2 | LightGBM | 0.7302 | 0.7184 | 0.4978 |
| R3 | XGBoost | 0.7776 | 0.7608 | 0.5319 |
| R4 | XGBoost | 0.7990 | 0.7869 | 0.4843 |
| R5 | LightGBM | 0.6768 | 0.6759 | 0.4279 |
| R6 | XGBoost | 0.6923 | 0.6717 | 0.3950 |
| R7 | LightGBM | 0.7221 | 0.7047 | 0.4971 |
| R8 | XGBoost | 0.6787 | 0.6671 | 0.4431 |
| R9 | LightGBM | 0.8129 | 0.8027 | 0.5526 |
| 全国 | XGBoost | 0.7253 | 0.7166 | 0.5718 |
这里的“暂选模型”只是按 test accuracy 初步判断,并不是最终生产决策。正式生产仍要结合每区类别级 F1、空间图斑连续性、R 区边界一致性和代表 tile QA。
第五阶段:用图件发现空间问题,而不是只看测试集指标
训练表指标只能说明样本点上的表现,不能保证 30m 空间预测图合理。因此对 R8 10km 测试块做了四模型空间对比:
regional_lightgbm regional_xgboost national_lightgbm national_xgboost生成的主要图件包括:
r8_10km_prediction_comparison.png r8_10km_prediction_comparison_with_legend.png r8_10km_confidence_comparison.png r8_10km_model_difference_masks.png single_maps_with_legend/regional_lightgbm_map_with_legend.png single_maps_with_legend/regional_xgboost_map_with_legend.png single_maps_with_legend/national_lightgbm_map_with_legend.png single_maps_with_legend/national_xgboost_map_with_legend.pngfiltered 四模型初始预测 QA:
| 模型 | 类别数 | 90m 标签采样 agreement | mean confidence | confidence < 0.5 |
|---|---|---|---|---|
| regional LightGBM | 19 | 0.4347 | 0.8717 | 5.41% |
| regional XGBoost | 20 | 0.5085 | 0.7345 | 20.41% |
| national LightGBM | 27 | 0.4490 | 0.7424 | 22.30% |
| national XGBoost | 27 | 0.4976 | 0.6380 | 34.42% |
图件检查比单纯指标更重要。R8regional XGBoost的 sampled agreement 最高,但单图显示主水体仍被切成4201/4202两类。这说明:filtered 重训解决了二级编码问题,但像元级模型本身仍缺少水体拓扑一致性约束。
第六阶段:JRC 普通入模尝试与否定
中间曾尝试把 JRC 水体信息作为普通模型特征加入训练。样本级 test 指标有所提升,但 R8 10km 空间结果没有解决大水体内部4201/4202切分问题,且在局部扩大了城市绿地相关类别面积。
这个试验带来的结论是:
JRC 更适合做预测后空间约束和 QA, 不适合作为默认普通特征直接交给 LightGBM/XGBoost 解决所有水体问题。因此后续路线改为:模型先输出初始分类和概率,JRC 在后处理阶段用于稳定水体、岸线、消落带、历史水域、4201/4202拓扑统一和水陆冲突标记。
第七阶段:JRC/EMC v4 后处理,解决水体分裂和 6206 语义约束
R8 filteredregional XGBoost初始预测中,水体统计为:
4201 = 17772 4202 = 48027最大连续静水体斑块内部仍同时包含4201 湖泊和4202 水库/坑塘。这不是面积问题,水体总量与旧版接近;问题是同一个连续水体内部类别不一致。
改进措施:对 filteredregional XGBoost初始结果执行 JRC/EMC v4 后处理。JRC/EMC v4 使用的数据包括:
JRC occurrence JRC recurrence JRC max_extent distance_to_stable_water ESA built-up 类别,当前 built-up=50 EMC-BUILT built_fraction_30m distance_to_emc_built emc_built_fraction_300m emc_greenness_valid后处理图件包括:
figures/single_maps_with_legend/regional_xgboost_initial_map_with_legend.png figures/single_maps_with_legend/regional_xgboost_post_jrc_emc_v4_map_with_legend.png r8_10km_prediction_comparison.png r8_10km_prediction_comparison_with_legend.png后处理结果:
| 项 | 初始 | 后处理 |
|---|---|---|
| 4201 | 17772 | 2 |
| 4202 | 48027 | 65802 |
| 6206 | 1321 | 1291 |
关键 QC:
mixed_4201_4202_components = 1 unified_4201_4202_pixels = 17770 changed_pixels = 17802 shore_urban_reassigned_pixels = 32这一步基本消除了同一大水体内部4201/4202分裂。需要特别说明的是,后处理后 90m 标签采样 agreement 从0.5085降为0.4413,原因是原始 90m 标签自身在同一连续水体内部保留了4201/4202混合。因此水体拓扑修正不能只看 90m sampled agreement,而要看连续斑块一致性、JRC 水体证据和人工核查。
EMC-BUILT 的作用主要体现在6206 城市草本绿地。6206不是“有草就算城市绿地”,而是要有人工建成环境背景。后处理用 EMC-BUILT Total RES+NRES 派生建成区比例和距离,用 Greenness 判断建成环境绿度有效性。对远离建成环境、靠近水体或历史淹水范围、且缺少 Greenness 有效证据的6206,只在模型概率支持时重分配,否则写 flag 供 QA。
第八阶段:Sentinel-2 输入标准化,避免迁移时 CRS 和网格不一致
在部署迁移讨论中又补充了一个重要环节:预测时接收到的 Sentinel-2 GeoTIFF 不一定已经是当前生产网格。模型本身不认识 CRS,但模型输入特征必须来自一致网格。因此在predict_tabular_tile.py前必须增加 Sentinel-2 GeoTIFF 预处理环节。
预处理首先校验:
CRS resolution / pixel size transform width / height 三季 extent 是否一致 band count 和 band 顺序 nodata / dtype如果输入不符合生产要求,则转换为中国 Albers 30m 标准网格:
+proj=aea +lat_0=0 +lon_0=105 +lat_1=25 +lat_2=47 +x_0=4000000 +y_0=0 +datum=WGS84 +units=m +no_defs resolution = 30m重采样规则不能一律使用nearest。应按 band 类型区分:
| band 类型 | band | 重采样 |
|---|---|---|
| 光谱连续变量 | B02/B03/B04/B05/B06/B07/B08/B8A/B11/B12 | bilinear |
| 指数连续变量 | NDVI/EVI/NDWI/MNDWI/NBR/NDMI/RENDVI | bilinear |
| 分类/质量标记 | SCL | nearest |
nearest只适合 SCL 这类分类/质量层;光谱和指数是连续变量,用bilinear更符合训练特征分布。标准化后的springtif 作为 DEM、ESA、HWSD、JRC、EMC 的 target grid。