ARTICLE DETAIL

资讯详情

深耕网站视觉设计与运营推广的一线实战洞察。

GEE监督分类全流程实战:从样本制作到随机森林调参与精度验证

GEE监督分类全流程实战:从样本制作到随机森林调参与精度验证 第一次在GEE里跑通土地利用监督分类已经是好几年前的事了。之前我刚从一个被遥感影像预处理折磨得头疼的项目里解脱出来转头发现原来Landsat影像不用下载、大气校正不用自己算连分类器都内置在云端几百行脚本就能出一个县域的土地利用分类图。那种体验上的代差有点像从翻盖手机换到智能手机——功能一直都有只是你没找到门。这篇文章想把GEE监督分类这件事从头到尾讲透。适合两类人看一是刚注册好GEE账号、想学着做土地利用分类但不知道从哪里下手的二是已经跑通过一版流程但验证精度卡在七八成上不去的。我会按照自己的实际使用习惯把类别体系设计、训练样本制作、特征组合、随机森林调参、精度验证这些环节逐一拆开顺带把我踩过的坑和判断依据都交代清楚。1. 从桌面软件到云端GEE把流程压缩到了什么程度1.1 传统土地利用分类流程的隐性成本做土地利用分类的人基本都经历过一套固定的“手工活”流程。先去USGS或者国内的数据平台挑影像Landsat 8一景一景往下下研究区如果跨了两三景轨道还得处理数据重叠和条带问题。影像到手后辐射定标、大气校正是个大坎FLAASH参数稍微设置不对出来的反射率就带着明显条纹后面整个分类都会被带偏。做完预处理还要镶嵌、裁剪、云掩膜处理每步都在桌面软件里手工点选步骤一多就容易乱。这套流程最大的问题不是技术难度而是时间成本和复现成本。处理一景Landsat影像的十几个波段普通笔记本跑到镶嵌和主成分分析的时候就有点喘了更别提做省级、国家级的大范围制图。而且一旦换一个研究区、换一期影像整套预处理流程得重新来一遍中间任何一个参数改动了结果就未必能复现。很多刚入门的朋友还没走到分类那一步就倒在了预处理上。1.2 GEE替我们做了什么GEE的核心价值是把数据、算力和算法变成了公共服务。数据目录里直接躺着Landsat Collection 2 Surface Reflectance、Sentinel-2 L2A、MODIS这些科学级产品表面反射率已经算好了质量评估波段也给了你要做的只是筛选和调用。算力方面GEE在云端集群上做并行计算处理一个县或者一个省的影像脚本跑起来通常就是几十秒到几分钟的事。算法栈方面随机森林、CART、SVM这些分类器都是内置方法不需要自己去实现。还有一个容易被低估的点可复现性。一段脚本就是一套完整流程研究区变了、时间变了只要改几行参数就能重新跑结果还能用seed固定随机种子来保持可复现。这在传统桌面软件流程里是很难做到的。1.3 监督分类为什么仍然是GEE土地利用制图的主力现在深度学习做遥感分类确实很火但在GEE内置能力范围内监督分类依然是土地利用制图最主流、最落地的方法。原因很直接监督分类对样本量的要求远没有深度学习那么高一个县域的项目每类一百来个样本点就能训练出不错的结果随机森林、SVM这些经典方法在Landsat 30米、Sentinel-2 10米这种中低分辨率影像上精度已经相当能打而且分类器学到的规则还可以通过特征重要性、混淆矩阵去解释出了问题好排查。哪怕是看起来和土地利用分类不搭边的任务比如“提取淹没范围”本质上也可以归到监督分类的框架里——把水体和非水体当成两个类别去做分类比单纯靠阈值分割往往更稳。所以把监督分类的基础打牢很多延伸需求自然就通了。2. 监督分类的本质分类器到底学到了什么2.1 像“批改过的例题”一样的学习过程很多新手把监督分类理解成一个“滤镜”觉得把影像丢进去就能自动出分类结果这是最大的误解。监督分类的学习过程其实特别像老师带着学生做练习题你手里有一堆没有答案的试卷也就是影像里每一个待分类的像元每道题目的关键信息是各波段的反射率数值你希望分类器这个“学生”去判断每道题属于哪个类别但在这之前你得先给它几套批改过标准答案的例题也就是训练样本。分类器做的事情就是从这些带标签的样本里总结出一套规则什么样的波段组合像水体什么样的波段组合像林地什么样的组合更像建设用地。等它学完这套规则再去给整景影像里每一个像元“判题”。这里有个隐含前提——像元之间的光谱差异要能反映出地表覆盖类型的差异。比如水体在近红外波段反射率普遍偏低植被在近红外波段反射率明显抬升建设用地则在短波红外波段有特殊表现。如果两类地物的光谱一模一样人眼都分不出来分类器自然也很难分对。2.2 特征空间一个被很多人忽略的基本概念有人问我为什么分类结果总是不稳定换几个样本点结果就天差地别很大程度上是因为没理解特征空间。拿两个波段举例每一个像元就是二维平面上的一个点横坐标是波段A的反射率纵坐标是波段B的反射率。同类地物的点往往聚在一起形成一簇一簇的点群不同类别分布在不同的区域。分类器要做的就是找出能把不同点群分开的边界线。波段越多特征空间的维度就越高理论上可分性越好但所需的样本量也会指数级上升——这就是常说的“维数灾难”。这也是为什么我不建议一上来就往特征里堆十几个波段特征不是越多越好关键是每个特征都要有区分度。2.3 GEE内置分类器怎么选GEE里常用的监督分类器就那几种我整理了一个对比参考分类器特点适用场景CART单棵决策树训练快、可解释但容易过拟合快速预实验、教学示例随机森林多棵决策树集成抗过拟合稳定性强绝大多数土地利用分类首选SVM小样本、高维特征下效果好但大数据量耗时样本少、类别少、特征维度高GradientTreeBoost提升树精度潜力高对参数和噪声敏感数据干净、样本充足时尝试朴素贝叶斯假设特征相互独立简单但精度上限低实际地物分类中很少用我的习惯是默认随机森林后面所有参数调优也都围绕它展开。不是说其他分类器不能用而是随机森林在样本量不算大、特征维度不算低、地物光谱存在重叠的典型场景下综合表现最稳训练速度也可以接受。3. 训练样本是命门从类别体系到采集细节3.1 先设计类别体系再去划样本我见过不少朋友打开GEE就开始画样本画到一半才想起来“哎我这个研究区到底要分哪几类”这是本末倒置。类别体系是整个分类项目的地基必须在一开始就定清楚。实际项目里我一般把土地利用类型合并成5到8类比如水体、林地、草地、耕地、不透水面建设用地、裸地。为什么控制在这个范围第一类别越多每类需要的训练样本量就成倍增加第二类别之间的光谱重叠度会变高例如旱地、裸土、低覆盖草地这三者在特定季节光谱非常接近强行细分只会把整体精度拖下水。一个朴素的判断标准如果你自己看高分辨率影像都拿不准某个像元属于哪一类那分类器大概率也学不会这种类别划分本身就有问题。3.2 用GEE制作样本点的完整姿势在GEE Code Editor里做训练样本最常用的是直接在编辑器左侧的几何图形工具里画点或多边形每个类别存成一个独立的geometry变量然后用FeatureCollection给每个几何要素打上类别属性。// 假设你已经在编辑器里画好了四类地物的几何图形 var waterGeo /* 画好的水体多边形或点集 */; var forestGeo /* 画好的林地区域 */; var cropGeo /* 画好的耕地区域 */; var builtGeo /* 画好的建设用地范围 */; var water ee.FeatureCollection(waterGeo).map(function(f) { return f.set(landcover, 0); // 水体 }); var forest ee.FeatureCollection(forestGeo).map(function(f) { return f.set(landcover, 1); // 林地 }); var crop ee.FeatureCollection(cropGeo).map(function(f) { return f.set(landcover, 2); // 耕地 }); var built ee.FeatureCollection(builtGeo).map(function(f) { return f.set(landcover, 3); // 建设用地 }); var allSamples water.merge(forest).merge(crop).merge(built);如果你手里有现成的野外调查点或者历史土地利用现状图也可以直接在本地转成Shapefile或者GeoJSON传到GEE的Assets里上传后会自动变成一个FeatureCollection后续操作和手绘样本完全一致。3.3 样本采集里的“潜规则”样本数量方面我的经验是每类最少50个点起步可靠的做法是每类做到100到300个点。但数量绝对不是第一位的样本点在空间上的覆盖广度才是关键。同一类地物在不同区域光谱特征会不一样同样是林地山区的阔叶林和丘陵区的针叶林在影像上的色调差异可能很大同样是水体浑浊的河流和清澈的水库反射率曲线完全是两回事。如果你把某一类的样本全部集中在一个角落分类器只学到了这一类“在局部区域的长相”到了研究区其他地方就会误分。所以我在画样本时有个强制性习惯每个类别在研究区的不同方位、不同地形条件下都要有分布尽量覆盖这一类的光谱变化范围。样本点不要落在像元边界和混合像元上。Landsat一个像元是30米乘30米如果一个像元一半是水一半是植被它的光谱是两种地物的混合给这种点打标签等于把一道错题当成标准答案教给分类器。我习惯在画点的时候把高分辨率影像叠加到底图上避开明显的边界线和混合区域。3.4 训练集和验证集划分最容易被忽视的环节这是老生常谈但依然大量存在的问题不要用训练样本直接报告精度。分类器在训练样本上拟合得再好也不能代表它对没见过的像元也能分对。合理的做法是把样本随机切分成两部分七成用来训练三成用来验证。var sampleData allSamples.randomColumn(random); var trainingSet sampleData.filter(ee.Filter.lt(random, 0.7)); var validationSet sampleData.filter(ee.Filter.gte(random, 0.7));注意randomColumn生成的随机数每次运行都会变化如果你在调试过程中频繁重跑建议给randomColumn加一个seed参数保证每次划分方式一致否则很难判断精度变化到底是分类器引起的还是样本划分变了引起的。4. 特征工程光谱、指数、地形与时间怎么组特征4.1 影像合成与基础波段准备特征的第一步是生成研究区时间范围内的无云影像合成。单景影像难免有云和云影直接用单景分类云区和云影区的像元会被分得乱七八糟。我一般用生长季范围内的中值合成这样既能保证影像整体干净又能保留地表覆盖类型的典型光谱特征。function maskL8sr(image) { var qa image.select(QA_PIXEL); var cloudBitMask 1 3; // Cloud var cloudShadowBitMask 1 4; // Cloud Shadow var mask qa.bitwiseAnd(cloudBitMask).eq(0) .and(qa.bitwiseAnd(cloudShadowBitMask).eq(0)); return image.updateMask(mask).select(SR_B2,SR_B3,SR_B4,SR_B5,SR_B6,SR_B7); } var l8 ee.ImageCollection(LANDSAT/LC08/C02/T1_SR) .filterBounds(roi) .filterDate(2022-06-01, 2022-09-30) .filter(ee.Filter.lt(CLOUD_COVER, 20)) .map(maskL8sr); var image l8.median().clip(roi);这里我顺手做了两件事一是用QA_PIXEL波段做了云和云影掩膜二是只保留了蓝、绿、红、近红外、两个短波红外共六个波段。海岸波段和全色波段我一般不往特征里放前者对地物分类贡献有限后者分辨率和其他波段不一致混在一起反而添乱。Landsat Collection 2 SR产品的波段名带SR_前缀这个细节别忽略。4.2 指数特征把专家知识塞进特征空间指数特征本质上是光谱波段的数学组合手工加入这些指数相当于把遥感领域积累了几十年的经验直接注入到特征空间里省去了分类器自己从原始波段里“重新发现规律”的负担。// 先转成真实反射率便于计算包含常数项的指数 var optical image.select([SR_B2,SR_B3,SR_B4,SR_B5,SR_B6,SR_B7]) .multiply(0.0000275).subtract(0.2) .rename([blue,green,red,nir,swir1,swir2]); var ndvi optical.normalizedDifference([nir, red]).rename(NDVI); var ndwi optical.normalizedDifference([green, nir]).rename(NDWI); var evi optical.expression( 2.5 * ((NIR - RED) / (NIR 6 * RED - 7.5 * BLUE 1)), { NIR: optical.select(nir), RED: optical.select(red), BLUE: optical.select(blue) }).rename(EVI); var bsi optical.expression( ((SWIR1 RED) - (NIR BLUE)) / ((SWIR1 RED) (NIR BLUE)), { SWIR1: optical.select(swir1), RED: optical.select(red), NIR: optical.select(nir), BLUE: optical.select(blue) }).rename(BSI); var features optical.addBands(ndvi).addBands(ndwi).addBands(evi).addBands(bsi);NDVI对植被敏感NDWI对水体和湿润地表敏感EVI在高植被覆盖区不容易饱和BSI对裸地有很好的指示性。这几类指数加进去之后分类器在区分耕地、林地、水体、裸地时的把握会明显增强。有人问指数能不能不加能但代价是可能需要更多样本才能达到同等精度。指数特征相当于给分类器发了“参考书”让它少走弯路。4.3 地形特征与时间维度容易被忽略的加分项在山区做分类如果不加地形特征等于少了一双眼睛。SRTM 30米高程数据在GEE里直接调用几行代码就能把高程、坡度、坡向全部算出来var srtm ee.Image(USGS/SRTMGL1_003); var terrain srtm.select(elevation) .addBands(ee.Terrain.slope(srtm)) .addBands(ee.Terrain.aspect(srtm)) .rename([elevation, slope, aspect]); var featuresWithTerrain features.addBands(terrain);为什么要加地形山区的阳坡和阴坡植被类型差异很大建设用地往往集中分布在低海拔平坝区而裸岩和裸土虽然光谱接近海拔分布却明显不同。高程、坡度这些特征能帮分类器把“光谱相近但地形位置不同”的类别更好地分开。时间维度同样重要。耕地里的作物一年四季光谱变化极大林地的光谱相对稳定。单时相影像看到的只是某个瞬间的状态多时相数据反映的是变化规律。我做华北平原的分类时会把春季和秋季的影像都做成合成加入特征春灌期的农田和冬季的裸地光谱差异非常大加入时间维之后耕地和裸地几乎不会再混淆。如果你处理的是物候差异明显的区域强烈建议至少合成两个关键物候期的影像特征。4.4 特征组合到底行不行用特征重要性说话随机森林训练完之后可以直接查看每个特征对分类的贡献var importance ee.Dictionary(classifier.explain()).get(importance); print(Feature Importance:, importance);我每次跑完分类都会打印特征重要性。经验来看NDVI、短波红外波段、EVI通常排在最前面蓝波段因为容易受大气散射影响贡献往往靠后。特征重要性有两个用途一是帮助判断特征组合是否合理如果某个理论上很重要的指数贡献极低就要检查是不是波段选择或者公式写错了二是帮助精简特征那些贡献极低而且和其他特征高度相关的变量可以考虑去掉有时候反而能提升验证精度。5. 随机森林调参实测先调样本再调参数5.1 为什么是随机森林随机森林本质上是一群决策树“投票”表决每棵树都是基于训练样本的随机子集bootstrap抽样和随机特征子集训练出来的。这种“双随机”机制让它在抗过拟合方面非常出色即使个别树学到了噪声集成投票时噪声也会被抵消。对土地利用分类这种训练样本有限、类别光谱存在重叠的任务来说随机森林是性价比最高的选择。同时它还能输出特征重要性、支持可复现的随机种子这些都是实际项目里很实用的能力。大数据量下SVM可能越跑越慢随机森林的训练速度则相对稳定。5.2 四个核心参数的真实影响随机森林在GEE里最常用的几个参数我逐个说清楚。numberOfTrees是树的数量。从50棵增加到200棵验证精度通常会有明显提升超过200棵之后边际收益很小训练时间倒是线性增长。我一般固定在200。minLeafPopulation是叶节点最小样本数默认是1。这个参数很多人忽略但恰恰是最值得调的。默认值1意味着决策树可以不断细分直到每片叶子只有一个样本训练集精度会非常好看但泛化能力通常不行。把它增大到5甚至10决策边界会更平滑验证精度往往会提高。bagFraction是每棵树随机抽样的比例默认0.5。如果你的样本量本身不大或者某一类样本特别少可以尝试把bagFraction调高到0.8让每棵树都能见到更多样本。maxNodes限制最大节点数相当于限制树的深度。它对过拟合也有抑制作用但实际中我用得相对少通常通过minLeafPopulation就够调节了。另外seed参数一定要设置。固定了随机种子每次运行结果才一致调试参数时才能确保唯一变量是参数本身。5.3 一次典型的调参记录直接上一组我实际测过的数据。研究区是华北某县Landsat影像样本每类约150个点特征包括6个反射率波段加4个指数。训练集和验证集划分完全固定只改参数。numberOfTreesminLeafPopulation训练精度验证精度结论5010.970.81明显过拟合10010.960.84仍有过拟合20010.960.85趋于稳定20050.930.87验证精度提升200100.900.86边界过度平滑50050.930.87与200棵差异不大这张表很有代表性。训练精度从0.97降到0.93看起来是“退步”但验证精度的提升才是真正有价值的进步。调参的唯一目标应该是泛化能力而不是训练集上的完美表现。另外还要注意参数之间的交互作用不要孤立地调某一个参数我的习惯是先固定numberOfTrees200把minLeafPopulation从1调到5、8、10各跑一遍再看特征重要性决定要不要增删特征最后再回头微调树的数量。6. 精度不是跑出来的验证的三个陷阱与实战坑6.1 混淆矩阵的正确读法分类跑完后验证精度的标准动作是用验证样本算混淆矩阵var validation validationSet.classify(classifier); var errorMatrix validation.errorMatrix({ actual: landcover, predicted: classification }); print(Validation Error Matrix:, errorMatrix); print(Overall Accuracy:, errorMatrix.accuracy()); print(Kappa:, errorMatrix.kappa());不过很多人拿到混淆矩阵只看总体精度和Kappa两个指标超过85%就觉得万事大吉。这样够吗远远不够。混淆矩阵里最有价值的是各类别的制图精度Producers Accuracy和用户精度Users Accuracy。制图精度低说明真实存在的这一类地物被漏分走了比如水体制图精度只有62%意味着不少真实水体像元被分到了其他类别典型原因是细小的河流、沟渠在30米像元下占比太小光谱被周围植被平均掉了。用户精度低说明这类地物被误分进来了比如建设用地用户精度只有58%意味着分类结果里有一大片“伪建设用地”常见原因是裸土和某些建筑用地的光谱过于接近。查混淆矩阵时把这两组数字逐类过一遍比盯着OA和Kappa有用得多。6.2 精度虚高的三个常见陷阱第一个陷阱是拿训练集精度当最终精度这个前面已经说过跳过。第二个陷阱是训练样本和验证样本空间上高度聚集。这类样本间的空间自相关很强一个像元被打上“林地”标签它周边几十个像元大概率也是林地光谱高度相似。如果训练集和验证集都从同一块聚类的样本里随机抽验证时相当于在考“跟例题长得差不多的题”精度虚高是必然的。更严谨的做法是空间分块验证——把研究区划分成若干格网一部分格网出训练样本另一部分格网出验证样本模拟“完全没见过这个区域”的预测场景。第三个陷阱是总体精度被大类主导。研究区如果有90%是农田农林分得再好水体、建设用地这些少数类分得再烂总体精度依然能被农田样本的规模拉高。这时候要单独看少数类的用户精度和制图精度必要时加一个F1分数来辅助判断。6.3 那些把分类结果搞乱的“玄学”问题分类结果出现大面积怪异斑块很多时候不是分类器的问题而是数据预处理没做好。云和云影没清干净是最常见的原因之一。一朵没被掩膜掉的薄云在影像上就是一大片异常高亮的像元分类器只能硬着头皮给它归类结果自然是一团糟。用QA_PIXEL做云掩膜是底线操作前面的maskL8sr函数必须包裹在影像集合映射里确保每一景参与合成的影像都先做掩膜。地形阴影区也容易被误分。山谷里的大片阴影光谱特征和深色水体非常相似很多分类结果里水体会顺着沟谷“爬上”山坡就是阴影捣的鬼。解决思路是在特征里加入地形特征同时检查云阴影掩膜是否覆盖了这些区域。影像和样本的时间不一致也是容易被忽略的坑。用2022年6月到9月的影像训练样本却来自2020年的野外调查地物早就变了分类精度无从谈起。样本的时间属性和影像时间必须对得上。最后是分类结果的“椒盐噪声”——大片同类别地块里出现零星散落的异类像元。这往往是因为30米混合像元和地物边界效应导致的。轻微的后处理可以缓解var smoothed classification.focalMode({ radius: 1, kernelType: square });注意后处理会改变分类边界如果你对边界位置的精度有要求focalMode的radius不要超过1也别在精度验证之前做平滑。7. 从Landsat影像到分类成图完整流程串联7.1 一次可直接照搬的分类主流程把前面所有环节串起来我以华北某县域为例写了一个完整可跑的流程。假设你已经在GEE里画好了研究区ROI以及水体、林地、耕地、建设用地四类地物的样本几何体变量名对应替换成你自己在编辑器里保存的geometry名称。// 1. 研究区与时间范围 var roi ee.FeatureCollection(你的研究区Asset路径); var startDate 2022-06-01; var endDate 2022-09-30; // 2. Landsat 8 SR云掩膜函数 function maskL8sr(image) { var qa image.select(QA_PIXEL); var cloudBitMask 1 3; var cloudShadowBitMask 1 4; var mask qa.bitwiseAnd(cloudBitMask).eq(0) .and(qa.bitwiseAnd(cloudShadowBitMask).eq(0)); return image.updateMask(mask); } // 3. 影像合成与特征构建 var l8 ee.ImageCollection(LANDSAT/LC08/C02/T1_SR) .filterBounds(roi) .filterDate(startDate, endDate) .filter(ee.Filter.lt(CLOUD_COVER, 20)) .map(maskL8sr) .select(SR_B2,SR_B3,SR_B4,SR_B5,SR_B6,SR_B7); var image l8.median().clip(roi) .multiply(0.0000275).subtract(0.2) .rename([blue,green,red,nir,swir1,swir2]); var ndvi image.normalizedDifference([nir, red]).rename(NDVI); var ndwi image.normalizedDifference([green, nir]).rename(NDWI); var evi image.expression( 2.5 * ((NIR - RED) / (NIR 6 * RED - 7.5 * BLUE 1)), { NIR: image.select(nir), RED: image.select(red), BLUE: image.select(blue) }).rename(EVI); var bsi image.expression( ((SWIR1 RED) - (NIR BLUE)) / ((SWIR1 RED) (NIR BLUE)), { SWIR1: image.select(swir1), RED: image.select(red), NIR: image.select(nir), BLUE: image.select(blue) }).rename(BSI); var features image.addBands(ndvi).addBands(ndwi).addBands(evi).addBands(bsi); var srtm ee.Image(USGS/SRTMGL1_003); var terrain srtm.select(elevation) .addBands(ee.Terrain.slope(srtm)) .addBands(ee.Terrain.aspect(srtm)) .rename([elevation, slope, aspect]); features features.addBands(terrain); // 4. 训练样本与划分 var water ee.FeatureCollection(waterGeo).map(function(f) { return f.set(landcover, 0); }); var forest ee.FeatureCollection(forestGeo).map(function(f) { return f.set(landcover, 1); }); var crop ee.FeatureCollection(cropGeo).map(function(f) { return f.set(landcover, 2); }); var built ee.FeatureCollection(builtGeo).map(function(f) { return f.set(landcover, 3); }); var allSamples water.merge(forest).merge(crop).merge(built); var sampleData features.sampleRegions({ collection: allSamples, properties: [landcover], scale: 30, tileScale: 4 }).randomColumn(random); var trainingSet sampleData.filter(ee.Filter.lt(random, 0.7)); var validationSet sampleData.filter(ee.Filter.gte(random, 0.7)); // 5. 训练随机森林并分类 var classifier ee.Classifier.smileRandomForest({ numberOfTrees: 200, minLeafPopulation: 5, bagFraction: 0.5, seed: 42 }).train({ features: trainingSet, classProperty: landcover, inputProperties: features.bandNames() }); var classification features.classify(classifier); // 6. 精度验证 var validation validationSet.classify(classifier); var matrix validation.errorMatrix({ actual: landcover, predicted: classification }); print(OA:, matrix.accuracy()); print(Kappa:, matrix.kappa()); print(Matrix:, matrix); // 7. 后处理与导出 var smoothed classification.focalMode({ radius: 1, kernelType: square }); Export.image.toDrive({ image: smoothed.clip(roi).uint8(), description: landcover_result, scale: 30, region: roi, crs: EPSG:4326, maxPixels: 1e13 });7.2 运行后的几个检查要点代码能跑通只是第一步。每次出结果我会按顺序做三件事第一先打印混淆矩阵逐类看用户精度和制图精度找出最容易混淆的类别对。如果耕地和林地大量互混大概率是特征里缺乏物候信息需要补充另一个季节的影像合成如果水体大量混入阴影就要检查地形特征有没有加进去、云阴影掩膜有没有漏。第二把分类结果图叠加到高分辨率影像上做目视检查。重点看三个区域样本点分布稀疏的区域、地形复杂的山区、水体与阴影交界的边缘。精度评价是统计意义上的它告诉你“平均而言”分得好不好但交付的是一张空间分布图局部区域的分错同样不能接受。第三检查异常斑块。如果分类结果里出现大量孤立破碎的像元考虑是不是30米混合像元导致的椒盐噪声再决定要不要用focalMode轻度平滑如果出现大范围的怪异连续区块就要怀疑数据源本身比如影像拼接缝、未掩膜干净的云区。最后再分享一个小经验。很多人跑完分类验证精度到了85%就觉得任务结束了但不要忘了分类结果最终是要拿出来用的。我会把分类结果按类别叠加统计面积和当地统计年鉴或者土地利用现状数据进行粗比对。如果某类面积和参考资料差得离谱哪怕验证精度再高也要回去查样本和特征而不是急着出图。这种交叉验证的办法在实战里帮我发现过好几次样本打错标签的问题——验证精度看着还行但面积一比对就露馅了。分类这件事功夫永远在分类器之外。
返回列表