做遥感这行的人,时间大多不是花在分析上,而是花在等下载。我最早做县域尺度地表覆盖制图时,一个中等县五年的 Landsat 影像,从检索、排队、下载、解压到拼成一张能用的年度合成图,前后折腾了将近两周,硬盘塞满了 400 多个 G,最后真正用于建模的像素可能不到总量的十分之一。更别提中间还夹着云掩膜没做干净、坐标系不统一、跨年份辐射定标不一致这些细碎问题。后来我开始把整条链路往云上搬,AI Earth 地球科学云平台就是在这个背景下进入我工作流的——它属于达摩院发的那套地球科学云平台,把 PB 级的遥感数据、在线 Notebook 算力和一批预训练的 AI 解译模型放在同一个浏览器窗口里。简单说,它能让一个只有笔记本、没有服务器的人,用几十行代码跑完过去要一周才能跑完的区域级分析。这篇文章我想聊的不是官方文档里那些功能介绍,而是一个真正拿它干过活的人会关心的事:数据怎么挑、算力怎么省、AI 模型到底能信几分、以及哪几个坑我替你踩过一遍。
1. AI Earth 在地球科学工作流里的真实位置
1.1 传统遥感处理的三个卡点
先说说为什么"上云"这件事对地学分析不是锦上添花,而是效率上的一次结构性改变。传统工作流里最要命的第一个卡点是数据搬运成本。一景 Landsat 8 的 Level 2 产品解压后接近 1 个 G,一个省十年的量级轻松上到几十 TB。这些数据你得先下到本地,再读进内存,算完再写回磁盘,整个过程中 CPU 大部分时间在等 IO,而不是在算。第二個卡点是环境依赖,GDAL 的版本、PROJ 的坐标系库、rasterio 编译时的底层依赖,随便一个版本不匹配就能让人调半天,换一台机器又要重来一遍。第三个卡点是算力天花板,本地做全国尺度的时序合成,内存一爆就是 MemoryError,然后你只能退而求其次,把研究区切小,切小之后又面临边界拼接和统计口径不一致的新问题。
这三个卡点叠加起来的结果是:大量时间被消耗在"让流程跑起来"而不是"让结论站得住"。我见过不少做地表变化研究的同学,论文里方法写得漂漂亮亮,但数据预处理那一段永远是黑箱,因为自己也没完全搞清楚当年是怎么把那些影像拼在一起的。
1.2 "数据不动,代码动"到底改变了什么
云平台的核心逻辑其实一句话能说清:把算力搬到数据旁边,而不是把数据搬到算力旁边。你在 Notebook 里写的那几行代码,会在平台侧的数据中心执行,影像不需要落地到你的硬盘。这件事带来的直接好处有三个层面。
第一层是时间。以前检索完要等下载,现在检索完直接filterBounds+filterDate就是在做虚拟筛选,只有真正参与计算的像素才会被读取。我做长三角一个市的年度合成,从写代码到出图大概二十分钟,其中十九分钟在等合成和导出。
第二层是一致性。平台上的公开数据集是统一做过预处理和元数据规整的,投影、波段命名、缩放系数基本统一,跨年份、跨传感器的对比不再是玄学。
第三层是可复现。你的代码、参数、时间范围、研究区矢量全部记录在一份 Notebook 里,别人打开就能重跑,这比"我本地有份处理好的 TIFF,你要不要"要靠谱得多。我现在的习惯是每个项目一个 Notebook,从检索到出图全部串起来,半年后回头改一个参数重新跑,五分钟的事。
1.3 它不适合谁,这点也要说清楚
不是所有场景都值得上云。如果你的研究区只有一个县,数据量两三个 G,本地笔记本跑得动;或者你的核心工作是精细的辐射校正算法开发,需要对原始 DN 值做大量实验;又或者你的数据是涉密的、不能出内网的,那云平台帮不上忙。另外,如果你只是想"看看某地现在什么样",其实直接用地図服务的时序影像底图更快,没必要动代码。
云平台真正的甜点区是这三类:区域尺度以上的时序分析(省级、流域级、跨国区域)、需要批量试参数的模型实验(同一套流程跑十几种阈值组合)、教学与协作场景(一批人用同一套数据和环境)。判断标准很简单:如果你估计自己的任务在本地要跑超过两小时,或者要处理超过 100 景影像,那就值得搬到云上。
2. 数据货架怎么挑:常用数据集与组合策略
2.1 光学影像三件套:Landsat、Sentinel-2、MODIS 各自的位置
平台上的光学数据看着多,实际常用的就三类,各自的分工非常明确。Landsat 系列(Landsat 8/9 的 Collection 2 Level 2)是长期时序分析的主力,30 米空间分辨率,单星重访 16 天,Landsat 8 和 9 组网后能压到 8 天左右,从 2013 年至今的连续记录基本够用。它的优势是时间跨度长、辐射一致性做得比较好,缺点是回访周期长,在多云地区一年能用的晴空影像可能只有个位数。
Sentinel-2是 10 米分辨率、5 天重访,在空间细节和时间密度上都压过 Landsat,做城市内部结构、小水体、地块边界的活儿它是首选。但要注意它的波段分辨率不一致,10 米的是 B2/B3/B4/B8,20 米的是红边和 SWIR 那一批(B5-B7、B8A、B11、B12),做指数计算时如果直接混用,分辨率会被自动对齐到最粗的那一档,细节收益就没了。我的做法是先用 10 米波段做主分析,需要 SWIR 的指数(比如 MNDWI)时单独处理,心里清楚这一步的代价。
MODIS是 250 米到 1 公里级的日频数据,它的定位不是"看得清",而是"看得勤"。做物候分析、大区域快速变化预警、给高分辨率结果提供时间维度的上下文,MODIS 的价值无可替代。常见产品是 MOD09 系列地表反射率和 MOD13 系列的植被指数,后者已经算好了 NDVI 和 EVI,直接拿来用可以省掉一步。
选择逻辑可以总结成一句话:要看长期趋势选 Landsat,要看空间细节选 Sentinel-2,要看时间密度选 MODIS。三者不是替代关系,很多时候是互补的,比如用 MODIS 定位变化发生的月份,再用 Sentinel-2 定位变化发生的具体地块。
| 数据集 | 空间分辨率 | 重访周期 | 常见用途 | 主要短板 |
|---|---|---|---|---|
| Landsat 8/9 C02 L2 | 30 米(全色 15 米) | 8 天(双星) | 长时序趋势、省级制图 | 单年晴空影像少 |
| Sentinel-2 MSI | 10/20/60 米 | 5 天 | 城市细节、小水体 | 波段分辨率不一,2015 年前无数据 |
| MODIS | 250/500/1000 米 | 1-2 天 | 物候、大区域预警 | 混合像元严重 |
2.2 立体与辅助数据:DEM、夜光、降水
光有光学影像做不了完整的分析。DEM 数据(比如 SRTM 或 ASTER GDEM)至少有三个用途:一是做坡度、坡向,参与地形校正和分类特征构建;二是做高程分区统计,比如把研究区按海拔分带后分别做分类,能显著提升山地场景的精度;三是做地形阴影掩膜,把因为地形遮蔽导致的异常暗像元剔掉,否则这些像元在分类器眼里会被误判成水体。
夜光遥感(比如 NPP-VIIRS 的月度合成)是城市研究的利器,建成区的提取用夜光比用光学影像有时更直接,因为它对灯光强度的响应和人类活动强度高度相关。但要注意夜光数据的饱和问题,特大城市核心区容易过饱和,用它做城市面积统计会有系统性低估,通常需要和光学影像做交叉验证。
降水与温度栅格这类气象数据在植被分析里是必需的对照变量。做 NDVI 年际波动分析时,如果不把降水年际变化这个变量控制住,你很容易把"今年雨水多所以植被长得好"误读成"生态恢复有效"。这一步是很多论文里被忽略的,但审稿人经常问。
2.3 检索四件套:时间、空间、云量、波段
在平台上做数据检索,永远是这四个条件在组合。时间范围决定了你拿到多少景,空间范围决定了单景被裁掉多少,云量阈值决定了有效影像的筛选强度,波段选择决定了后面计算的数据量。这四个条件里,最容易被滥用的是云量阈值。
我见过不少人直接把云量过滤设成 10% 以下,结果一年只剩两三景,做中值合成的时候样本严重不足,最后出来的图有明显的条带感。正确做法是先看研究区的气候背景:如果是干旱区,设 20% 都可能偏严;如果是长江中下游,全年能有 30% 以下云量的影像本来就不多,设 40% 再配合逐像元云掩膜,比设 10% 直接丢掉大半影像要好得多。
空间范围也有讲究。很多人习惯先圈一个很大的矩形,再在里面慢慢筛,这样每次计算扫描的瓦片数会成倍增加。我的习惯是把研究区矢量简化(simplify)一下再上传,去掉那些为了精度加进去的碎顶点,一个县域的边界从三万多个点简化到两三千个点,几何运算耗时能降一个量级,而实际面积误差可以忽略。
提示:上传矢量时优先用 WGS84 经纬度(EPSG:4326)或平台明确支持的投影,坐标系不对会导致 filterBounds 返回空集合,这个错误不会报异常,只会让你拿到零景影像,非常容易误判为"这个区域没有数据"。
3. 在线 Notebook 实战:环境、内存与导出
3.1 初始化与依赖管理
平台的在线 Notebook 本质是一个托管环境,你需要先做认证和初始化,然后才能调用数据接口。接口风格和主流的地球科学云平台很像,如果你有 GEE 的使用经验,上手基本没有障碍。下面这段是我常用的起手式,注意这是示意写法,具体的类名和方法请以平台当前文档为准,因为这套 SDK 更新比较频繁。
import aie aie.Authenticate() # 绑定平台账号 aie.Initialize() # 初始化地图与计算上下文 roi = aie.FeatureCollection('projects/xxx/assets/my_county') collection = (aie.ImageCollection('LANDSAT/LC09/C02/T1_L2') .filterDate('2023-06-01', '2023-09-30') .filterBounds(roi) .filter(aie.Filter.lte('eo:cloud_cover', 40)))关于依赖,平台预装了 numpy、pandas、rasterio、geopandas 这些常用库,绝大多数分析不用自己装。真正需要自己装的情况通常是你要用某个特定的深度学习框架或某个冷门的投影库,这时候要注意在线环境的持久化问题,很多平台的 Notebook 一旦重启,手动 pip 安装的包就没了。我的做法是把安装命令写在 Notebook 第一格,重启后顺手跑一遍,比去研究持久化配置要省心。
还有一个细节:认证凭证是有有效期的。跑长任务的时候如果中间凭证过期,导出任务可能会失败。所以长时间运行的导出操作,最好在任务启动后确认一下任务状态,别设完就跑去做别的事。
3.2 分块与降采样:别让内存先崩
云平台虽然算力比本地强,但也不是无限的,尤其是在线 Notebook 用的往往是共享资源。我踩过最惨的一次坑是直接对全省范围做年度中值合成,代码没报错,跑了四十多分钟之后任务被中断,原因是内存超限。后来改成网格分块处理,把研究区切成 20 公里见方的格子,循环处理每一格再拼接统计结果,同样的任务十几分钟就跑完了,而且中途某一格失败可以单独重跑。
分块的逻辑不复杂,核心是在空间维度上切,而不是在时间维度上切。时间维度切开会导致每年的合成图来自不同的影像集合,跨年对比时引入额外噪声。空间维度切开的代价只有边界拼接,处理起来简单得多。
grid = roi.geometry().coveringGrid('EPSG:4326', 20000) # 示意 results = [] for i in range(grid.size().getInfo()): cell = grid.get(i) comp = (collection.filterBounds(cell) .map(mask_qa) .median() .clip(cell)) stat = comp.reduceRegion( reducer=aie.Reducer.mean(), geometry=cell, scale=30, maxPixels=1e13, bestEffort=True ) results.append(stat.getInfo())maxPixels和bestEffort这两个参数值得单独说。默认的maxPixels值很小,做区域统计时经常被拒绝,报一个"too many pixels"的错。把它调到 1e13 配合bestEffort=True,平台会自动调整采样步长来完成统计,代价是精度会略降。用于趋势分析完全够用,但如果是要做最终的面积统计,我还是会老实用分块 + 精确尺度算,不依赖重采样。
降采样是另一个省资源的技巧。做参数试错阶段,完全没必要用 30 米全分辨率跑,把scale设成 300 米,速度能快十倍以上,等你确定阈值和流程了再用原分辨率跑最终结果。这个习惯让我在调试阶段节省了大量算力额度。
3.3 导出格式与参数
导出是整条链路里最容易被低估的一步。平台上的栅格导出一般可以选 GeoTIFF,矢量导出可以选 Shapefile 或 GeoJSON,统计结果直接导 CSV。几个参数必须显式指定,别依赖默认值。
scale决定输出分辨率,写 30 就是 30 米;crs决定输出投影,如果你的研究区跨带或者要做面积统计,这里必须换成等积投影,比如 Albers 等积投影,具体参数要根据研究区中心纬度定;region决定导出范围,写roi.geometry()就是按矢量边界裁,写roi.geometry().bounds()就是按外接矩形裁,后者速度更快但文件更大。
task = aie.Image.export( image=classification, description='landcover_2023', scale=30, crs='EPSG:xxxx', # 换成适合研究区的等积投影 region=roi.geometry(), maxPixels=1e13, fileFormat='GeoTIFF' )description是任务名,不能有中文和空格,我一般用项目名_年份_版本的格式,比如lc2023_v2,方便后续在任务列表里检索。另外要注意,同时运行的导出任务数通常有上限,批量导出的时候用一个简单队列控制并发数,别一次性提交三十个任务,容易被限流。
还有一个导出失败的高频原因是输出尺寸超限。单次导出的像素总量是有上限的,如果研究区很大、分辨率又要求很细,导出的 TIFF 会超出限制。解决办法有两个:要么降低分辨率,要么按分块分别导出再在本地拼接。我一般用第二个,因为分块导出的结果可以直接用于后续的分块统计,一举两得。
4. 预训练 AI 解译模型能做什么、做不到什么
4.1 几类任务的实际表现
平台提供了一批预训练的 AI 解译能力,常见的有地物分类、变化检测、目标检测(比如提取光伏板、风机、大棚这类特定目标)、语义分割等。这些模型是"开箱可用"的,你不用自己训练就能跑出结果,这一点对没有深度学习背景的地学研究者非常友好。
但真实表现和宣传图之间是有落差的,我按自己的使用经验给个大致判断。大尺度地物分类(水体、植被、建设用地、裸地这类宏观类别)表现通常不错,因为它对纹理和光谱差异的依赖不强,模型见过的样本也多。特定目标检测在目标形态规整、背景单一的场景下效果很好,比如在平坦农田里提取光伏板阵列,召回率能到很高;但一旦目标被遮挡、或者背景本身很杂乱,漏检就明显增加。变化检测是最需要小心的一类,因为它对前后两期影像的配准精度、时相一致性、辐射一致性都极其敏感,输入差一点,输出可能就是一堆噪点。
我的一般原则是:把 AI 模型当成一个高质量的预标注工具,而不是最终产品。用它跑出初稿,再人工修正关键区域,效率比纯人工高出一个量级,精度又比纯模型靠谱。
4.2 微调与样本量的关系
如果你需要更高的精度,就得自己标样本做微调。这里有个常见误解:很多人以为样本越多越好,于是花两周硬标了五千个点,结果精度提升有限。实际上在小样本场景里,样本的空间分布质量比数量重要得多。
我的经验是,标 200 到 400 个高质量样本点,如果分布覆盖了研究区的所有地物类型和地形梯度,效果往往好过 2000 个扎堆在平原区的样本点。原因很简单,模型学到的是特征的边界,如果你没给它看过山地阴影下的水体、城镇边缘的混合像元、休耕期的农田,它就没有办法在这些区域做出正确判断。
样本标注还有两个细节容易被忽略。一是纯像元原则,标注点要落在类别内部的均质区域,不要落在类别边界上。30 米分辨率下,一个像素对应地表 900 平方米,在城乡交错带几乎不存在纯像元,这些地方标注本身就是"错"的,标进去只会给模型添乱。二是类别平衡,如果建设用地只占研究区的 5%,而植被占 70%,直接训练会导致模型倾向于把所有模棱两可的像元都判成植被。解决方法是欠采样大类或者给类别加权,我通常用加权,因为欠采样会丢掉大量信息。
4.3 精度评价的正确姿势
模型跑完,出来一张花花绿绿的分类图,这时候最容易犯的错误是直接看图觉得"挺像的"就交付了。分类精度必须量化,而且要看的东西不止一个数字。
最基础的是混淆矩阵,从中能算出总体精度(OA)、Kappa 系数,以及每一类的制图精度(Producer's Accuracy)和用户精度(User's Accuracy)。这里有个概念必须分清:制图精度说的是"真实属于 A 类的像元里,有多少被正确识别为 A",用户精度说的是"被识别为 A 的像元里,有多少是真的 A"。前者的误差是漏分,后者的误差是错分。对做面积统计的人来说,用户精度更关键,因为你统计出来的 A 类面积里掺杂的错分部分会直接造成偏差。
更进一步的一步是面积无偏估计。即使分类图精度是 90%,直接数像素算出来的面积依然可能有系统性偏差,尤其是小类别。做法是用分层随机抽样,每一类按分类图中的比例分配样本量,对样本做人工判读,然后用矩阵反推真实面积比例。这套方法在小类别的面积估计上能把误差从百分之十几压到百分之五以内,代价是要人工判读几百个点。如果你做的是要对外发布的变化数据,这步不能省。
验证样本的来源也有讲究。如果研究区有历史的高分辨率影像(比如亚米级的商业影像存档),用它做参考最理想;没有的话,用同期更高分辨率的免费影像辅助判读。要避免的是用同一套影像既训练又验证,那样得到的精度是虚高的。
5. 一条完整的实战链路:城市扩张监测
5.1 问题定义与指标
光讲原理没意思,我把一个完整的项目拆开走一遍。任务是这样:某地级市 2013 到 2023 年的建成区扩张监测,输出每年的建成区范围、面积统计、扩张方向,以及新增建成区占用的原土地类型构成。
指标要提前定死,不然做到一半会不断改需求。我的指标体系是:分类总体精度不低于 85%,Kappa 不低于 0.8,面积相对误差控制在 10% 以内,逐年结果的空间配准误差不超过一个像元。这几个数字不是拍脑袋来的,是参考同类研究的通行标准,也是审稿人会盯的地方。
还有一个容易被忽略的前置决策:建成区的定义。是只算连续的人工不透水面,还是包含城市内部的大片绿地和水体?这个定义直接决定分类体系的类别划分,也决定了后续的面积数字怎么解释。我采用的是"连续不透水面为主、剔除面积大于一定阈值的水体、保留城市内部绿地"的口径,并在交付文档里写清楚,避免用的人按自己的理解再解释一遍。
5.2 云掩膜与年度合成
数据源用 Landsat 8 和 9 的 Collection 2 Level 2,时间窗口选每年 6 月到 9 月的生长季。为什么选生长季?因为这时候植被茂盛,植被和不透水面的光谱差异最大,分类最容易分开;如果混入冬季影像,落叶林和建成区的光谱会接近,误差上升。
第一步是云掩膜,用 QA_PIXEL 波段做位运算。
CLOUD_BITS = (1 << 1) | (1 << 2) | (1 << 3) | (1 << 4) | (1 << 5) def mask_qa(img): qa = img.select('QA_PIXEL') mask = qa.bitwiseAnd(CLOUD_BITS).eq(0) return img.updateMask(mask) def scale_sr(img): optical = img.select('SR_B.*').multiply(0.0000275).add(-0.2) return img.addBands(optical, None, True)位运算这段值得解释。QA_PIXEL 是一个 16 位整数,每一位代表一种状态,位 1 是膨胀云,位 2 是卷云,位 3 是云,位 4 是云阴影,位 5 是雪。把这几位对应的数值按位或起来,再检查结果是不是零,是零就说明这些状态一个都没触发,这个像素是干净的。用位运算而不是简单比较数值,是因为一个像素可能同时是好几种状态的组合,数值会变得很大,直接比大小会漏掉情况。
scale_sr里的两个系数是 Collection 2 Level 2 产品特有的。它的地表反射率存的是整数,需要乘 0.0000275 再减 0.2 才能还原成真实反射率。这一步看着不起眼,但不做的话所有指数的绝对值和阈值全部偏移,我见过有人因为这个把 NDVI 的阈值定错了 0.15,水体边界整整扩出去一圈。
掩膜完成后做中值合成。这里有个顺序问题,必须先掩膜再合成,不能先合成再掩膜。原因很直观:中值是对所有影像逐个像素取中位数,如果云像素还在里面,它就会参与中位数的计算,在有多云影像的时候中值会被污染。先掩膜之后,被遮掉的像素不参与合成,中值才是干净的。
5.3 分类后处理与面积统计
合成的年度影像上算几个指数作为特征:NDVI 区分植被,NDBI(归一化建筑指数,用 SWIR1 和 NIR)突出不透水面,MNDWI(改进的归一化水体指数,用绿波段和 SWIR1)提取水体。
MNDWI 相比传统的 NDWI 的优势在于它用了 SWIR1 而不是 NIR,在建成区背景下水体的对比度更强。传统 NDWI 在城市区域会因为建筑的高反射率出现大量误判,MNDWI 把这个问题解决得比较彻底,代价是它对 SWIR 波段的分辨率有依赖,Sentinel-2 上 SWIR 是 20 米,会拉低整体分辨率。
分类可以用平台的监督分类能力,也可以用随机森林。我这次用的是随机森林,特征包括三个指数加上原始的多光谱波段,样本 320 个,训练集和验证集按 7:3 分。分类完之后做两步后处理:一是众数滤波,用一个 3×3 窗口把孤立的单像素噪声平滑掉;二是最小图斑剔除,把面积小于 3 个像素的图斑合并到周围面积最大的类别里。这两步能把视觉上的"椒盐噪声"清掉,对面积统计的影响通常在 1% 以内,但成图效果提升明显。
面积统计是全流程里最容易出错的一步。必须先把分类结果重投影到等积投影再数像素。在经纬度坐标系下,一个像素对应的实际面积随纬度变化,同样是 30 米,在赤道和高纬度的真实面积差很多。我的做法是用研究区中心纬线定制一个 Albers 等积投影,在这个投影下每像素 900 平方米,直接数像素乘以 900 就完事。
5.4 出图与结果表达
出图这一步看起来简单,其实决定了成果能不能被看懂。我一般准备三张图:一张是逐年建成区范围的制图,用同一条色带从浅到深表示年份;一张是新增建成区的空间分布,用不同颜色标出各年份的新增部分;第三张是扩张方向的雷达图或玫瑰图,把新增面积按八个方位统计后画出来,一眼就能看出城市往哪个方向长。
配色上有个教训:分类图不要用高饱和度的纯色。纯红纯绿纯蓝放在一起,在不同显示器上观感差异很大,打印出来更难看。用低饱和度的分类色板,配合清晰的类别图例和比例尺,专业感会好很多。另外,栅格图导出的时候把dpi提到 300 以上,做汇报和打印都够用。
如果需要把结果做成在线可交互的形式,可以在 Notebook 里直接叠加到地图控件上,设置一个透明度滑杆,让不同图层可以切换对比。这个功能在做汇报的时候特别好用,比静态图有说服力得多。
6. 六个真实踩坑现场与修复思路
6.1 面积算出来差了 15%:投影没换
这个坑前面提过,但它太常见了,值得单独说一遍。我第一次做全市建成区面积统计,用经纬度坐标直接数像素,结果算出来的面积比统计年鉴的数字小了将近 15%。当时以为是分类精度问题,回头查了半天才反应过来是投影的事。在纬度 30 度附近,经纬度网格的面积变形大概是 10% 到 15% 的量级,正好对上。
修复很简单,用reproject把结果转成等积投影再统计。但这里有个陷阱:如果你导出的时候已经写死了 30 米的分辨率,重投影之后分辨率会变成不均匀的,统计就不准了。所以顺序应该是先重投影到等积投影,再按等积投影下的固定分辨率导出和统计。
6.2 云掩膜写在合成之后,等于没做
有一段时间我图省事,把掩膜写在median()之后,逻辑上好像也对——先把一年影像合成一张,再对合成结果做云掩膜。结果在某些多云区域,合成图上出现了大片异常亮的斑块,分类的时候被误判成了裸地。
原因就是前面说的,中值合成之前云像素还参与计算。如果一年只有五景影像,其中三景有云,那么某一像素的中位数很可能就是一个云像素的值。修复的方法是把掩膜放在集合映射阶段,让它在合成前就生效。这不是性能问题,是正确性问题。
6.3 跨传感器对比:辐射定标与被遗忘的偏移量
做 2013 到 2023 年的对比,早年用的是 Landsat 8,后来加了 Landsat 9。两者都是 Collection 2 Level 2,理论上辐射是一致的,但实际上如果对其中一个忘了做缩放系数转换,NDVI 的整体偏移会很明显。我遇到过一年数据显示植被指数整体偏低 0.05 的情况,排查很久才发现是那批影像在预处理的某个分支里跳过了缩放步骤。
避免这类问题的办法是把预处理写成一个函数,所有数据源都走同一个函数,不要在流程里写分支。多花十分钟统一接口,能省掉后面几天的排查时间。跨传感器对比时,还可以用重叠期的影像做交叉标定,比如 2021 年 Landsat 8 和 9 都有数据,用同期的两套数据比较同一地物的反射率,如果系统性偏差超过 2%,就说明定标环节有问题。
6.4 物候错配导致的"假变化"
这是我见过的最隐蔽的一类错误。做变化检测时,如果两期影像一个是 6 月一个是 10 月,植被的物候差异会被模型识别成地物变化。一月份的农田是裸土反射率,七月份是茂盛植被,两者光谱差异极大,变化检测会把它们判成"从裸地变成植被"。
避免方法是尽量用相同时相窗口的影像,比如都限定在 7 月到 8 月。如果实在做不到,就在模型里加入物候校正,或者改用基于时序曲线的方法而不是两期对比。我现在的习惯是在变化检测的结果图上叠加一个"物候敏感性检查",把研究区内的农田区域单独拿出来看,如果农田区域变化特别剧烈,八成是物候问题而不是真的变化。
6.5 导出任务失败与分辨率陷阱
导出失败的原因我遇到过三类。一是输出尺寸超限,解决办法是分块导出;二是任务名重复,同一个description提交两次,第二次会被拒,解决办法是加版本号;三是并发数超限,一次提交太多任务被限流,解决办法是写个简单的循环加延时。
分辨率陷阱更隐蔽一些。有些平台在导出时会自动把分辨率对齐到数据源的网格,如果你请求的是 25 米,实际输出可能是 30 米,统计的时候按 25 米算就会出现偏差。所以导出后一定要检查输出文件的元数据,确认实际的分辨率、投影、范围都符合预期,别假设它跟你请求的一致。
6.6 样本画在混合像元上
前面提过纯像元原则,这里补充一个具体场景。在城乡交错带采样,如果经验不足,很容易把样本点落在"看起来像建设用地其实一半是菜地"的地方。这类样本进了训练集会显著拉低模型的边界判断能力,表现是验证精度上不去,但加样本也没用。
我的做法是先在目标区域的 Google 级别高分底图上判断,确认是均质区域再落点。另外,采样之后做一次样本特征的可分性检查(比如画各类样本在 NDVI-NDBI 平面上的散点),如果某一类样本在特征空间里和其他类别严重重叠,就说明采样有问题,需要重新标。
7. 免费额度与福利资源的正确用法
7.1 新用户资源包里最值钱的是什么
平台对新用户通常会提供一定的免费资源,形式可能是算力时长、存储空间或者特定模型的调用额度。这些东西里,最值钱的是算力时长,因为存储和公开数据的访问基本不构成瓶颈。算力时长用完了要么等下一个周期,要么就得走付费,所以在试错阶段把算力省着用是很实际的考虑。
我见过有人把免费额度拿去跑一个全国范围的初次实验,一次跑掉大半,后面调参的时候发现没额度了。这完全是策略问题,跟技术无关。
7.2 调试与生产的资源分配
我的资源分配原则是"粗调省、精跑贵",具体来说就是把整个项目分成三个阶段。第一个是探索阶段,用小范围、低分辨率(比如 300 米)、短时间窗口跑通整条链路,确认代码逻辑没问题,这个阶段消耗大概 5% 的额度。第二个是参数阶段,在研究区内选两三个有代表性的小区域,用中等分辨率跑十几种参数组合,比较结果,这个阶段消耗 20%。第三个是生产阶段,全区域、原分辨率、分块跑最终结果,这个阶段消耗剩下的 75%。
按这个节奏,即使免费额度不多,也能完整跑完一个地级市级别的项目。反过来说,如果一上来就在全区域跑全分辨率,第一次跑错一个参数,整批额度就没了。
7.3 比赛、训练营与公开课程
除了资源额度,平台上经常会有一些公开的活动,比如遥感相关的算法比赛、线上训练营、公开课程。这些东西的价值不止在于奖品,更在于它们通常会提供额外的算力资源和高质量的标注样本。我参加过一次水体提取的比赛,拿到的训练样本质量比我自己标的好很多,而且赛题设定逼着你把流程做得规范,赛后的代码可以直接复用。
另外一个容易被忽略的资源是平台上其他用户公开的 Notebook。很多常见任务都能找到现成的实现,你不需要从零开始写。我习惯的做法是找三四个类似的实现,对比它们的处理顺序和参数设置,看看差异在哪,然后挑最合理的部分组合成自己的流程。这比闷头自己写快得多,也能避免一些自己想不到的坑。
一些实际操作后的体会
用了几年下来,我觉得这类地球科学云平台真正的价值不在"AI"这两个字上,而在它把数据、算力和协作这三件事塞进了同一个环境里。AI 解译能力确实好用,但它更像是一个能帮你省掉 70% 重复劳动的工具,剩下的 30% 判断工作——定义分类体系、检查物候错配、验证精度、解释结果——依然得人来完成。
如果让我给刚开始用的人一条建议,那就是先别急着跑大区域。选一个你熟悉的地方,比如你老家的一个县,用一两个小时的影像跑一遍完整的流程,从检索到出图到精度验证全部走通。你会在这条小链路上遇到几乎所有后面会遇到的坑,但代价小得多。等这条链路跑顺了,再放大到流域或者省域,只是参数和分块策略的调整而已。
还有一个私心建议:把每次跑的 Notebook 都存一份带日期的备份。我吃过一次亏,半年前的一个项目需要重新出一版图,结果当时的代码在编辑过程中被改乱了,花了两天才复原。现在我每个项目目录下都有v1、v2、v3这样的版本快照,多占一点存储空间,换来的是随时能回到任意一个历史状态。