
如果把高光谱图像分类当成一个普通的机器学习问题绝大多数人的第一反应是“分类器够不够强、网络够不够深”。但真正在高光谱遥感数据上跑过实验的人都知道制约精度的瓶颈通常不是模型而是标签。高光谱影像上的一个像素对应的是地面上几米到几十米的一块区域同时带有一条几十到几百维的光谱曲线。要给这样的像素打标签需要结合实地调查资料、区域地物知识和高分影像来判读成本远高于普通图片分类里的“人动动鼠标”。这篇博客要解读的论文标题是Fermat Active Laplace Learning for Semi-Supervised Hyperspectral Image Classification。为了方便叙述后面把它缩写为 FALL。它要解决的问题有两个第一如何用很少的标注像素结合大量无标注像素在半监督框架下完成高光谱图像分类第二如何在迭代过程中主动挑出“最值得标注”的像素把有限的标注预算花在刀刃上。我的判断是FALL 在技术路径上给了我们一个很稳的思路——用 Fermat 距离改善图结构用 Laplace Learning 做标签扩散用 Active Learning 控制标注成本。它不一定在每个数据集上都把精度推到最高但它把“半监督 主动学习 图几何”这条可解释的路线完整串了起来。读完这篇文章你会搞清楚 Fermat 距离到底改进了什么拉普拉斯学习为什么适合高光谱以及如果你想复现或者改造它核心步骤和容易踩坑的地方在哪里。1. 高光谱图像分类真正难的是“标注”高光谱图像不同于普通 RGB 图像。RGB 图像每个像素只有三个波段高光谱影像常见的波段数是几十到几百个。以常用的机载高光谱数据集为例Indian Pines 的常见版本有 200 个波段左右Pavia University 的常见版本有 100 多个波段。每个像素的光谱曲线相当于一个高维向量理论上足够区分很多细类地物比如不同作物、不同含水量土壤、不同矿物成分。但波段多不一定是好事。几百个波段带来的第一个问题是高维样本少时非常容易过拟合第二个问题是波段间强相关很多相邻波段的信息是冗余的。更关键的是高光谱像素级标注的成本极高。一张 Indian Pines 影像只有约两万个像素但逐像素标注真值需要结合当年的地面调查记录和区域地物知识。把这一过程放大到整景大影像上标注工作量会迅速超过模型训练本身。所以高光谱分类的研究长期沿着两条线推进一条线是用更复杂的分类器比如 SVM、随机森林、深度学习网络把特征表达做好另一条线是降低对标注样本的依赖让模型能在十几、几十个标签像素的条件下也能学起来。半监督学习和主动学习都属于后者。这里需要强调的是两者的侧重点不同。半监督学习假设的是标签虽然少但整个数据集就在那里数据自身的结构信息可以借来用。主动学习假设的是我有一笔标注预算我要决定先标哪几个像素最划算。两者组合起来才是完整地应对“标注贵”的方案。FALL 正是把这条组合路线落地成一个具体方法。2. 拉普拉斯学习半监督分类的地基拉普拉斯学习是图上半监督学习的经典方法。先说直觉把每个像素看成图上的一个节点如果两个像素特征相似就在它们之间连一条边边的权重表示相似度。有了这张图之后有标签节点的标签作为“已知答案”通过图结构把信息扩散到无标签节点上。和邻居越像节点的预测结果就越倾向于和邻居一致。用一个最简单的高光谱场景来解释一小块农田区域里的相邻像素光谱曲线通常都来自同一类作物。如果其中有 3 个像素有标签另外 47 个像素没有就可以把有标签像素当种子让标签沿着高相似度的边向外扩散。数学上拉普拉斯学习通常写成求解下面这个优化问题min_f f^T L f μ ||f_L - y_L||^2其中 L 是图拉普拉斯矩阵f 是要求解的标签函数y_L 是有标签像素的已知标签μ 是平衡两项的权重。第一项让相邻节点的预测结果尽量平滑第二项让有标签节点的预测结果不要偏离真实标签。这是一个二次优化问题把 f 求导置零后可以得到线性方程组在无标签节点数量可控时可以直接求闭式解不需要训练深度网络。在高光谱场景里拉普拉斯学习有两个明显优势。第一它不需要像深度学习那样吃大量数据几十个标签就能推动求解。第二它把分类问题变成了“图的几何结构”问题也就是说能不能分类准很大程度上取决于图建得好不好。这也是 FALL 选择在这一层做改进的核心动机与其换更大的分类器不如先把“图上哪些像素应该连在一起”这个问题解决得更准。这里有一个容易混淆的概念拉普拉斯学习和标签传播Label Propagation经常被放在一起比较。标签传播是一种迭代算法反复把邻居标签加权平均传给当前节点拉普拉斯学习则是在全局能量函数上直接求最优解。两者最终效果相近但拉普拉斯学习在数学上更有“全局最优”的保证。在高光谱这种噪声较大的场景中全局平滑比逐轮迭代更容易稳定。3. Fermat 距离把图从“度量近”升级成“流形近”既然图的质量决定了拉普拉斯学习的上限那“节点之间应该怎么连”就是整个方法成败的关键。常见的做法是用欧氏距离特征向量越接近边权越大。但高光谱数据在高维空间里有一个麻烦波段多、噪声多两个同类像素的欧氏距离可能因为某个噪声波段的抖动而变得很大两个来自不同地物的像素却可能靠得很近。欧氏距离对高维噪声非常敏感。测地线距离比欧氏距离更进了一步。它考虑的是在数据流形上沿着高密度区域走从一点到另一点要“实际走多远”。比如两类地物在光谱特征空间里被一条低密度区域隔开如果走欧氏直线可能很快穿过低密度区但走测地线需要绕过高密度区的边界距离会明显拉长。这符合分类直觉同一类像素之间应该有密集的过渡不同类像素之间应该有稀疏的“鸿沟”。Fermat 距离可以看作测地线距离的一种推广。它通常会在路径代价里引入一个控制参数对边权做非线性的幂变换再计算“最划算的路径”。从效果上看它会让路径更倾向于穿过高相似度、高密度的区域而不是走一条穿过低密度区域的“捷径”。这样计算出来的节点间距离比欧氏距离更贴近数据的流形结构。用通俗类比来理解你在一个陌生城市出行直线距离最近不等于实际代价最小。如果某条直线要穿过一个荒芜的片区你宁愿绕行人多的商业街。欧氏距离只看“图上两点之间直线多长”Fermat 距离则是“在数据密度地图上绕开低覆盖率区域之后最短要花多少代价”。高光谱数据的分类边界通常就存在于低密度区域所以用 Fermat 距离构建图更容易让同类像素在图上聚在一起让异类像素之间的连边被压低。需要特别说明Fermat 距离在论文中的具体定义和参数设置要以论文原文为准。从方法族看它的核心是在路径代价中引入一个可调节的指数参数 γ。γ 较小时路径倾向于走短距离γ 较大时路径更愿意绕行以换取整条路径上都有较高的相似度。实际实验里γ 通常需要和近邻数 K、相似度核宽度 σ 一起调参。引入 Fermat 距离之后FALL 的图构建流程大致是先对高光谱特征做主成分这类降维再在降维后的特征上构建初始邻接图然后计算 Fermat 距离矩阵用这个距离矩阵重新定义节点间相似度最后交给拉普拉斯学习使用。4. 主动学习把标注预算花在最有价值的像素上半监督方法可以降低“需要多少标签”但没有解决“标签从哪里来”。如果初始种子标签选得不好比如所有标签都集中在影像左下角的一块区域那模型对影像其他区域几乎没有约束。主动学习解决的是另一个问题假设每一轮只能增加几个标注样本该优先标注哪些像素才能让分类精度提升最大。常见的查询策略大致有几类。不确定性采样选模型预测概率最接近均匀分布的样本也就是模型最拿不准的那些投票委员会训练多个模型让它们对未标注样本投票选分歧最大的多样性采样选特征空间里最能代表大面积区域的样本避免重复标注相似像素。真正实用的策略常常是“不确定性 多样性”的折中既要有信息量又不能全挤在一个簇里。FALL 的设计逻辑很强的一点在于主动学习不是随便接一个通用策略而是和前面的几何结构配合起来用已训练的拉普拉斯模型给无标签节点打分从中挑选不确定性高、同时又处于近邻图中具有代表性的节点被选中的像素交付标注后加入有标签集合再重新构建或更新图进入下一轮。高光谱数据里的主动学习有一个特殊性地物类别通常极不平衡。城市化区域中以建筑和道路为主的像素很多而某些稀有地物可能只有几百个像素。如果只看不确定性模型会反复挑难分类但本质上就是噪声的边界像素导致一个类别被反复标注却对整体精度帮助有限。因此在实现 FALL 时比较稳妥的做法是给类别预算设一个上限每轮每个类别最多选若干个样本并尽量让选择分布覆盖整个影像空间。也可以把主动学习看作“以人类标注预算为约束的优化问题”。假设总预算是一个像素数上限那么每一轮迭代本质上是在回答新增的这几个像素能不能最大程度减少图中无标签节点的预测不确定度。好的查询策略会比随机采样少用一半标签同时达到同样的总体精度。这也是主动学习在高光谱分类里长期受欢迎的原因。5. FALL 整体流程拆解半监督、几何、采样如何串起来从工程视角看FALL 不是一个一次性前馈的深度学习模型而是一个迭代流程。理解这个流程比背公式更重要。下面按步骤拆解。Step 1数据准备。把高光谱影像按像素展开成特征矩阵每个像素是一个样本点同时对标签做规范化只保留有标签和无标签两部分。如果影像尺寸较大通常先做 PCA 降维既能去噪又能降低图构建的内存压力。Step 2初始图构建。在降维特征上通过 K 近邻找到每个像素的邻居用径向基函数等核函数计算边权形成邻接矩阵。Step 3Fermat 距离计算。对边权做幂变换以变换后的权重计算任意两点之间的最短路径距离得到 Fermat 距离矩阵。Step 4图增强与拉普拉斯求解。根据 Fermat 距离重建相似度矩阵构建拉普拉斯矩阵在少量种子标签约束下求解标签函数 f。得到的 f 对每个无标签像素给出一个连续预测值。Step 5主动学习采样。利用当前模型的预测结果在无标签像素中按设计好的查询策略选出一批样本交给标注者打标签。Step 6更新与迭代。把新标注的像素并入有标签集合回到 Step 2 重新构建图继续下一轮。迭代直到达到标注预算上限或者分类精度不再明显提升。这个流程中真正决定最终效果的是 Step 3 和 Step 5。Step 3 决定图的质量Step 5 决定每一轮增加的标签有没有价值。两者缺一不可图建得再好如果主动学习每轮都在选重复像素标签预算就被浪费了主动学习选得再好如果图参数不合理拉普拉斯扩散的路径也会出错。需要注意论文的原始实现可能会对某些步骤做细节调整比如 K 近邻中 K 的选择、Fermat 距离 γ 的取值、主动学习是否批量选择样本等。以上流程是这一类方法的通用骨架复现时建议先去找论文作者的官方代码再对照公式逐行核对避免在细节上跑偏。6. 从公式到代码FALL 的核心模块怎么落地这一节给出一个教学演示框架用来理解 FALL 三个核心模块的实现思路。以下代码不是论文的官方实现而是用 NumPy / SciPy 写的通用逻辑重点是展示数据在每一步之间如何流转。6.1 构建 KNN 图并计算 Fermat 距离# 文件fermat_graph.py import numpy as np from scipy.spatial import cKDTree from scipy.sparse import csr_matrix from scipy.sparse.csgraph import shortest_path def build_knn_adjacency(X, k8, sigma1.0): 基于特征矩阵 X 构建 KNN 邻接矩阵。 X: (n_samples, n_features) 返回稀疏对称邻接矩阵。 n X.shape[0] tree cKDTree(X) dist, idx tree.query(X, kk 1) # 第 0 列是自身 row np.repeat(np.arange(n), k) col idx[:, 1:].reshape(-1) val np.exp(-(dist[:, 1:].reshape(-1) ** 2) / (2 * sigma * sigma)) adj csr_matrix((val, (row, col)), shape(n, n)) adj (adj adj.T) / 2.0 return adj def fermat_distance(adj, gamma1.5): 对边权做幂变换后计算最短路径距离得到 Fermat 距离矩阵。 注意返回的是稠密矩阵节点数过大时请使用近似方法。 adj_mod adj.copy() adj_mod.data adj_mod.data ** gamma return shortest_path(csgraphadj_mod, directedFalse)关键逻辑Fermat 距离和普通 Dijkstra 最短路径的区别在于计算前对边权做了 w^γ 变换。γ 越大低权重边被惩罚得越狠路径就越倾向于避开低相似度区域。这一行变换就是 Fermat 距离的核心。6.2 拉普拉斯学习的闭式解# 文件laplace_learning.py import numpy as np def laplace_learning(X, y, labeled_idx, k8, sigma1.0, eps1e-6): adj build_knn_adjacency(X, kk, sigmasigma) deg np.array(adj