1. 项目概述与核心挑战高光谱数据分类这个听起来有点学术的词其实就是给遥感卫星拍回来的“超级照片”里的每一个像素点打上它代表什么地物的标签。比如这片是玉米地那片是水体那块是建筑区。这活儿是遥感领域最基础也最核心的任务之一从农业估产、环境监测到城市规划都离不开它。但这事儿干起来有个老大难的问题标注数据太少了也太难搞了。高光谱图像动辄几百个光谱波段数据维度高得吓人一个像素点就包含了几百个特征值。想让机器学习模型学会分辨这些特征传统方法需要海量已经标好类别的像素点也就是有标签数据去“喂”它。然而给高光谱图像做标注可不是在电脑上点点鼠标那么简单。它往往需要领域专家跑到实地去对照着卫星图像一寸一寸地确认地物类型成本极高、耗时极长还容易出错。这就导致我们手里头有海量的高光谱图像数据无标签数据但能用来训练模型的“标准答案”有标签数据却少得可怜。面对这个“数据饥渴”的困境研究者们主要从两个方向找突破口。一条路是设计更“聪明”的模型让它在只有少量标注样本的情况下也能学得好这就是小样本学习的思路。另一条路是改变学习范式不只用那一点点标注数据而是把海量的、没标注的数据也利用起来让模型从数据自身的结构中学习这就是半监督学习。我最近深入实践并验证了一种将这两条路优势结合的方法基于张量嵌入的图半监督学习。简单来说就是先用一个特别擅长从小样本中提取特征的张量神经网络把原始的高维像素块转换成一组更精炼、信息更密集的“特征向量”这就是张量嵌入。然后我们用这些高质量的特征向量来构建一个“关系网”图在这个网上让已有的少数标签像水波一样扩散开来去“感染”和预测那些没有标签的像素点。实测下来这套组合拳在多个公开数据集上只用极少的标注样本比如每类只给10-30个就能取得比单纯用张量网络好得多的分类效果真正做到了“四两拨千斤”。2. 核心思路拆解为什么是“张量嵌入”“图学习”2.1 张量嵌入为高光谱数据“瘦身增肌”高光谱图像天生就是个三维张量长空间x 宽空间x 波段数光谱。传统方法往往粗暴地把它拉平成一个超长的一维向量这就像把一本立体的书压成一张纸很多宝贵的空间结构和光谱间的关联信息就在这个过程中丢失了。张量方法的精髓在于它尊重数据的原始结构。我们使用的核心模型叫做Rank-R 前馈神经网络。它的关键创新在于其第一层连接输入和隐藏层的权重矩阵被强制约束为一种叫做CP分解的形式。你可以把它想象成一个庞大的权重矩阵连接所有输入特征和隐藏神经元被拆解成了几个小得多的因子矩阵的乘积。这么做的巨大优势是什么参数爆炸式减少假设输入是一个 7x7x200 的像素块共9800个原始特征一个普通的全连接层如果有100个神经元就需要近100万个参数。而通过低秩CP分解例如秩R5参数数量可能骤降到几千个。这直接对抗了过拟合——模型不会去死记硬背那寥寥几个训练样本的噪声而是去学习更本质、更泛化的特征。保留结构信息分解过程隐式地建模了空间维度和光谱维度之间的交互让提取的特征嵌入即隐藏层的输出天然地融合了光谱-空间信息。所以张量嵌入扮演了“特征精炼师”的角色。它把原始高维、冗余、可能含有噪声的像素块压缩成一个低维、紧凑、但信息密度更高的特征向量。这个向量就是我们后续所有操作的基石。2.2 图半监督学习让标签在“关系网”中流动有了好的特征表示下一步就是利用无标签数据。图学习是半监督学习中非常直观有效的一派。它的核心思想是“物以类聚”。建图我们把每个像素点现在用它的张量嵌入向量表示看作图中的一个“节点”。然后计算节点之间的相似度比如用高斯核函数如果两个节点特征向量很相似我们就在它们之间连一条“边”边的权重代表相似程度。这样所有数据点有标签无标签就构成了一张关系网。标签传播现在少数有标签的节点就像几个染了色的水源。标签传播算法会让这些颜色标签信息沿着图的边根据边的权重相似度逐渐扩散到整个网络。相似度高的节点之间颜色更容易流动。经过迭代最终每个无标签节点都会根据其邻居节点的标签和连接强度获得一个预测标签。这个过程的美妙之处在于它完全是无监督地利用了整个数据集的内在几何结构。模型不再仅仅看孤立的样本而是看样本在特征空间中的“邻里关系”来做出判断。2.3 协同增效112 的逻辑那么为什么要把这两者结合起来单独用图学习直接用原始像素特征建图不行吗实测下来真的不行或者说效果不好。高光谱原始数据维度太高、噪声大直接计算相似度构建的图质量很差会包含大量错误的连接把不同类别的点连在一起。垃圾进垃圾出在这样的图上做标签传播效果自然不理想。而张量嵌入正是解决这个问题的钥匙。Rank-R FNN 通过小样本训练后其产生的嵌入向量是经过网络“理解”和“提纯”后的特征。在这个嵌入空间里同类样本会聚集得更紧密。异类样本会分得更开。数据的流形结构更加清晰。用这样的高质量嵌入来构建相似度图图的精度会大幅提升。一个更干净的图意味着标签传播的路径更准确最终分类性能的飞跃也就水到渠成。这就好比你要在一个城市里找人分类如果给你一张标注了少数地标有标签数据的精确地图高质量嵌入构建的图你很容易推理出其他位置是什么但如果地图本身画得歪歪扭扭、错误百出低质量原始特征建的图你就很可能迷路。3. 实操全流程从数据到结果纸上谈兵终觉浅下面我结合实验中的具体设置拆解整个实现流程。你需要准备的“食材”包括高光谱数据集、Python环境如PyTorch/TensorFlow、以及图学习库如scikit-learn扩展或专门的图学习包。3.1 数据准备与预处理我们以公开的Indian Pines数据集为例。它有 145 个光谱波段16 种地物类别共约1万个已标注像素。第一步构建空间-光谱样本块直接对单个像素分类会丢失空间上下文信息。我们采用一个滑动窗口以目标像素为中心截取一个s x s大小的空间邻域形成一个s x s x 145的三维张量块X_x,y。这里s是奇数如5或7。我们假设这个小块的中心像素标签代表了整个小块的标签。这是合理且常见的做法能有效引入空间信息。import numpy as np def extract_patches(data, labels, window_size5): 从高光谱图像中提取以每个标注像素为中心的块。 data: 高光谱图像 (height, width, bands) labels: 标注图像 (height, width) window_size: 块的空间尺寸奇数 half window_size // 2 patches, patch_labels [], [] # 获取所有有标注的像素坐标 rows, cols np.where(labels 0) for r, c in zip(rows, cols): # 提取块处理边界这里用0填充 r_start, r_end r - half, r half 1 c_start, c_end c - half, c half 1 patch np.pad(data, ((half, half), (half, half), (0,0)), modeconstant)[r_start:r_end, c_start:c_end, :] patches.append(patch) patch_labels.append(labels[r, c]) return np.array(patches), np.array(patch_labels) - 1 # 标签通常从0开始第二步数据集划分与极小样本设置这是模拟现实困境的关键。我们不能用太多标注数据。将总数据按类别分层采样分成6份6-fold cross-validation。对于每一折的训练集我们进行极度稀疏采样从每类中随机抽取 α 个样本例如 α 10, 20, 30作为有标签训练集。再额外抽10个/类作为验证集用于控制张量网络训练如早停。该折剩下的训练集样本和整个测试集都作为无标签数据池。我们会从这个池子里按比例如20% 40% 60%抽取数据加入到图学习的构建中。注意这里的“无标签”在评估时是有真实标签的只是不用于初始训练。我们以此来模拟真实世界中大量无标签数据可用的场景。第三步数据归一化将每个样本块X_x,y在光谱维度上进行最小-最大归一化到 [0, 1] 区间加速网络收敛。def min_max_normalize(patches): 对每个样本块进行逐波段的归一化 # patches shape: (n_samples, height, width, bands) min_vals patches.min(axis(1,2), keepdimsTrue) max_vals patches.max(axis(1,2), keepdimsTrue) normalized (patches - min_vals) / (max_vals - min_vals 1e-10) return normalized3.2 阶段一训练Rank-R FNN获取张量嵌入这是整个流程的特征工程核心。我们需要实现或找到一个支持CP分解权重约束的神经网络层。网络结构简述输入层接收形状为[batch_size, s, s, bands]的张量。CP分解层自定义层这是关键。该层不直接使用一个大权重矩阵W而是存储D个小的因子矩阵W_d对于三维输入D3。前向传播时通过Khatri-Rao积实时计算vec(W)再与拉平的输入做内积。输出维度是隐藏神经元数量q。隐藏层激活对CP层的输出使用ReLU等激活函数。输出层一个普通的全连接层接Softmax输出类别概率。训练要点目标我们不是追求这个网络本身的分类精度达到极致而是要它学到一个好的特征转换器。因此验证集的损失或精度用于早停即可。关键超参数分解秩 R控制模型的容量和参数效率。R太小模型欠拟合R太大可能过拟合且计算量增加。实验表明对于高光谱数据R3或5通常是个不错的起点。隐藏神经元数 q即嵌入向量的维度。它决定了输出特征的尺寸。并非越大越好需要平衡信息保留和后续图构建的计算复杂度。q50或75是常见选择。输出嵌入训练完成后我们丢弃最后的输出层。将预处理后的数据包括所有有标签和无标签样本输入网络并提取CP层激活后的输出即隐藏层的值。这个q维的向量就是每个样本的“张量嵌入”。# 伪代码示意提取嵌入 def get_tensor_embeddings(model, dataloader): model.eval() embeddings, all_labels [], [] with torch.no_grad(): for patches, labels in dataloader: # 前向传播至隐藏层 hidden_activation model.cp_layer(patches) # 假设cp_layer是返回隐藏层输出的方法 embeddings.append(hidden_activation.cpu().numpy()) all_labels.append(labels.cpu().numpy()) return np.vstack(embeddings), np.concatenate(all_labels)3.3 阶段二基于嵌入构建图并应用SSL算法现在我们有了所有样本少量有标签L大量无标签U的q维嵌入向量。接下来进入图学习阶段。第一步构建相似度图我们采用最常用的k-最近邻k-NN图或ε-邻域图。这里以k-NN图为例计算所有样本嵌入向量两两之间的欧氏距离或余弦相似度。对于每个节点i找到距离它最近的k个节点不包括自己。在节点i和这k个邻居之间建立无向边。边的权重W_ij通常用高斯热核函数计算W_ij exp(-||x_i - x_j||^2 / (2σ^2))其中σ是尺度参数可以取所有成对距离的中位数。from sklearn.neighbors import kneighbors_graph import scipy.sparse as sp def build_knn_graph(embeddings, k10, sigmaNone): 构建k-NN相似度图 n_samples embeddings.shape[0] # 计算k-NN连接性矩阵二进制表示是否邻居 connectivity kneighbors_graph(embeddings, n_neighborsk, modeconnectivity, include_selfFalse) # 计算距离矩阵这里kneighbors_graph不直接返回距离需另算 from sklearn.metrics.pairwise import euclidean_distances dist_matrix euclidean_distances(embeddings) # 将距离转换为相似度权重仅对k-NN连接应用 if sigma is None: # 启发式设置sigma取所有距离的中位数 sigma np.median(dist_matrix[dist_matrix 0]) similarity np.exp(-dist_matrix**2 / (2 * sigma**2)) # 只保留k-NN连接的权重 adjacency connectivity.multiply(similarity) # 点乘非连接处为0 # 通常使矩阵对称因为k-NN可能不对称 adjacency (adjacency adjacency.T) / 2 return adjacency第二步应用图半监督学习算法我们将构建好的图邻接矩阵W、有标签节点的索引及其真实标签、无标签节点的索引输入到SSL算法中。实验对比了多种算法其中基于拉普拉斯正则化的方法表现最为稳健。以经典的Label Propagation (LP)算法为例其核心思想是迭代地让每个节点的标签向其邻居加权平均更新而有标签节点的标签在迭代过程中会被“钳制”回初始值。# 伪代码示意Label Propagation 核心迭代 def label_propagation(adjacency, labels, labeled_mask, max_iter1000, tol1e-3): adjacency: 相似度矩阵已归一化如对称归一化拉普拉斯相关 labels: 初始标签矩阵one-hot形式无标签处为0 labeled_mask: 布尔数组True表示该节点有标签 n_nodes adjacency.shape[0] # 初始化预测标签 Y labels.copy() for it in range(max_iter): Y_new adjacency Y # 标签传播步骤 # 钳制有标签节点的值 Y_new[labeled_mask] labels[labeled_mask] # 检查收敛 if np.linalg.norm(Y_new - Y) tol: break Y Y_new # 对于多分类取概率最大的类作为预测 predictions np.argmax(Y, axis1) return predictions在实际实验中我们测试了多达11种图SSL算法包括拉普拉斯相关Lap, LapRePo, LapWNL泊松方程PoCG, PoSpe随机游走LaWaMBO方案MMBO, VMBO稀疏标签传播SpLap-拉普拉斯p-Lap3.4 性能评估与对比评估采用分层6折交叉验证重复多次以消除随机性。核心评估指标是F1-score宏平均因为它能更好地处理类别不平衡问题高光谱数据中各类别像素数通常差异很大。对比基线Rank-R FNN本身作为一个纯监督模型仅使用那极少量的有标签数据训练和预测。核心发现嵌入质量至关重要使用 Rank-R FNN 提取的嵌入相比原始像素特征能显著提升所有图SSL算法的性能。这证实了高质量嵌入能构建更优的图。算法差异性并非所有SSL算法都能同等受益。基于拉普拉斯正则化的方法如Lap, LapWNL和随机游走LaWa表现最稳定、最优。而一些更复杂的方法如MBO变体在不平衡数据上提升有限甚至可能因参数敏感而表现不佳。无标签数据量的收益递减增加用于图构建的无标签数据比例从20%到60%初期能提升分类精度但达到一定比例后如40%性能提升变得微乎其微而计算成本建图复杂度O(n²)却显著增加。这表明存在一个“性价比”最高的无标签数据用量阈值。统计显著性通过配对t检验像Lap这样的方法相比纯监督的Rank-R FNN在F1分数上的提升是统计显著的p值远小于0.001。4. 关键参数、调优与避坑指南在实际复现和应用这个方法时以下几个点的把握直接决定了成败。4.1 张量网络训练的关键Rank (R) 与隐藏层大小 (q) 的权衡这不是越大越好。我们的实验表明对于Indian Pines和Salinas数据集R5, q50 与 R5, q75 效果接近但后者参数更多。建议从较小的R和q开始如R3q50如果欠拟合训练集和验证集损失都高再逐步增加。盲目增大不仅增加训练时间还可能在小样本上导致过拟合。样本块大小 (s)我们测试了5和7。s5在大多数情况下已经足够捕获局部空间纹理且计算负担更小。s7可能引入更多来自邻域不同类别的噪声特别是对于边缘像素。除非地物目标非常大否则优先选择s5。训练技巧由于标签数据极少务必使用早停Early Stopping耐心值patience设小一点如5-10轮。强烈建议使用权重衰减L2正则化和Dropout即使在隐藏层后来进一步抑制过拟合。学习率不宜过大使用学习率调度器如ReduceLROnPlateau是稳妥的选择。4.2 图构建的陷阱与技巧相似度度量与尺度参数 σ欧氏距离高斯核是最常用的。σ 的选择非常关键。一个稳健的启发式方法是取所有成对距离的中位数。也可以尝试取第k近邻距离的平均值。如果 σ 太小图变得稀疏信息无法有效传播σ 太大图过于稠密不同类别可能被错误连接。近邻数 kk 决定了图的局部连通性。k 太小图不连通标签无法传播到孤立区域k 太大图包含太多不相关连接引入噪声。一个经验法则是从k log(n)或k10左右开始尝试观察性能变化。可以将其视为一个需要轻微调优的超参数。图的归一化在将邻接矩阵W输入给许多SSL算法如Label Propagation前需要进行归一化例如对称归一化D^{-1/2} W D^{-1/2}其中D是度矩阵。这能提高算法的数值稳定性和收敛速度。处理大规模数据当无标签数据量很大时n 10000构建全连接k-NN图O(n²)会内存爆炸。此时必须使用近似最近邻搜索如Annoy, Faiss, HNSW来高效构建稀疏图。或者可以考虑锚点图方法用远少于n的锚点来构建图将复杂度从 O(n²) 降至 O(nm)其中m是锚点数量。4.3 SSL算法选择与使用心得首选拉普拉斯类方法如果你的目标是稳定、可解释的提升从标准的Label Propagation或基于拉普拉斯正则化的方法开始。它们实现简单超参数少主要就是传播的迭代次数和停止容差且在我们的实验中表现最稳健。警惕计算复杂度MBO、p-Laplace等方法虽然数学上很优雅但计算成本通常更高且对超参数如p-Laplace中的p值更敏感。在类别严重不平衡的数据集上它们可能表现不稳定。不建议在初次尝试或生产环境首选这些复杂方法。“无标签数据越多越好”是个误区我们的实验清晰地表明当无标签数据量达到总数据量的一个比例例如40%-50%后性能增长曲线会极度平缓。盲目使用全部无标签数据只会徒增计算时间而不会带来显著精度提升。建议进行一个简单的消融实验绘制不同无标签数据比例下的性能曲线找到那个“拐点”。标签置信度与迭代在标签传播中有标签节点的标签是“硬钳制”的。但在一些改进算法中可以考虑对有标签节点的置信度进行软性约束或者引入“标签吸收”的概念让传播过程更平滑。5. 常见问题与排查实录在实际跑通这个流程的过程中你肯定会遇到各种问题。下面是我踩过的一些坑和解决方案。Q1: 张量网络训练损失不下降或者很快过拟合。检查点首先确认你的数据预处理归一化是否正确。输入数据是否在合理范围如[0,1]。学习率这是最常见的问题。对于小样本训练学习率必须设得非常小例如1e-4或1e-5。尝试使用学习率查找器LR Finder或简单地以10倍为单位逐步调小。正则化你是否使用了足够的正则化增加权重衰减系数如1e-4在CP层后或隐藏层后加入Dropout如0.3-0.5。Rank R是否太小如果损失从一开始就很高且不降可能是模型容量不足欠拟合。尝试将R从3增加到5。验证集划分确保验证集是从与训练集同分布的有标签数据中划分出来的并且没有数据泄露。Q2: 图SSL算法预测结果全是同一个类别。检查图连通性你的图可能是由几个不连通的子图组成的而标签只存在于其中一个小子图里。计算图的连通分量。确保k值足够大使得整个图是连通的或者至少大多数节点在一个大连通分量内。检查相似度权重如果σ设置得极大所有边的权重都接近1会导致标签迅速均匀化。如果σ设置得过小权重矩阵几乎为零标签无法传播。打印出权重矩阵的统计信息均值、方差确保它是一个合理的稀疏矩阵有明确的大小差异。算法收敛问题有些迭代算法可能不收敛。增加最大迭代次数并打印每次迭代后预测值的变化范数观察其是否趋于稳定。Q3: 整体流程跑通了但效果比论文里报告的差很多。复现一致性首先确保你使用的数据集版本、训练/验证/测试集的划分比例、以及评价指标是整体精度OA还是每类F1的宏平均与论文完全一致。高光谱数据集的预处理如去除水汽吸收波段版本不同结果差异会很大。超参数差异论文中可能经过了细致的超参数调优。请仔细核对样本块大小s、RankR、隐藏层大小q、图构建的k和σ、SSL算法的内部参数如正则化系数。随机性由于采样选取有标签样本、划分数据具有随机性单次运行的结果可能有波动。务必进行多次运行例如10次并报告平均性能和标准差这才是可靠的比较。实现细节张量网络的CP分解层实现是否正确前向传播计算是否与公式对应图构建时是否对邻接矩阵进行了正确的对称化和归一化这些细节的偏差都会导致性能损失。Q4: 面对新的高光谱数据集如何确定一套可行的启动参数这是一个非常实际的问题。我的建议是建立一个参数搜索基线张量网络固定s5尝试(R, q)组合[(3,50), (5,50), (3,75), (5,75)]。使用极小的有标签数据如每类5个快速训练看哪个组合在验证集上收敛最快且损失最低。图构建固定使用表现稳健的Lap算法。对于k尝试[5, 10, 15]。对于σ先用“距离中位数”的启发式方法然后在其0.5倍和2倍附近微调。无标签数据量从20%开始增加到40%观察性能增益。如果增益明显再试60%如果增益很小则40%可能已足够。这个方法的核心优势在于其模块化和可解释性。你可以清晰地看到是张量嵌入的提升带来了图质量的提升进而带来了最终分类性能的提升。它不像一个端到端的黑箱模型其每个环节都有调整和优化的空间。虽然它涉及两个阶段看起来比单一模型复杂但在标注数据极其稀缺的现实约束下这种“精心准备食材嵌入再巧妙烹饪图学习”的策略往往是达成高精度结果的更务实、更可靠的路径。
高光谱图像分类:融合张量嵌入与图半监督学习应对小样本挑战
发布时间:2026/5/26 21:02:51
1. 项目概述与核心挑战高光谱数据分类这个听起来有点学术的词其实就是给遥感卫星拍回来的“超级照片”里的每一个像素点打上它代表什么地物的标签。比如这片是玉米地那片是水体那块是建筑区。这活儿是遥感领域最基础也最核心的任务之一从农业估产、环境监测到城市规划都离不开它。但这事儿干起来有个老大难的问题标注数据太少了也太难搞了。高光谱图像动辄几百个光谱波段数据维度高得吓人一个像素点就包含了几百个特征值。想让机器学习模型学会分辨这些特征传统方法需要海量已经标好类别的像素点也就是有标签数据去“喂”它。然而给高光谱图像做标注可不是在电脑上点点鼠标那么简单。它往往需要领域专家跑到实地去对照着卫星图像一寸一寸地确认地物类型成本极高、耗时极长还容易出错。这就导致我们手里头有海量的高光谱图像数据无标签数据但能用来训练模型的“标准答案”有标签数据却少得可怜。面对这个“数据饥渴”的困境研究者们主要从两个方向找突破口。一条路是设计更“聪明”的模型让它在只有少量标注样本的情况下也能学得好这就是小样本学习的思路。另一条路是改变学习范式不只用那一点点标注数据而是把海量的、没标注的数据也利用起来让模型从数据自身的结构中学习这就是半监督学习。我最近深入实践并验证了一种将这两条路优势结合的方法基于张量嵌入的图半监督学习。简单来说就是先用一个特别擅长从小样本中提取特征的张量神经网络把原始的高维像素块转换成一组更精炼、信息更密集的“特征向量”这就是张量嵌入。然后我们用这些高质量的特征向量来构建一个“关系网”图在这个网上让已有的少数标签像水波一样扩散开来去“感染”和预测那些没有标签的像素点。实测下来这套组合拳在多个公开数据集上只用极少的标注样本比如每类只给10-30个就能取得比单纯用张量网络好得多的分类效果真正做到了“四两拨千斤”。2. 核心思路拆解为什么是“张量嵌入”“图学习”2.1 张量嵌入为高光谱数据“瘦身增肌”高光谱图像天生就是个三维张量长空间x 宽空间x 波段数光谱。传统方法往往粗暴地把它拉平成一个超长的一维向量这就像把一本立体的书压成一张纸很多宝贵的空间结构和光谱间的关联信息就在这个过程中丢失了。张量方法的精髓在于它尊重数据的原始结构。我们使用的核心模型叫做Rank-R 前馈神经网络。它的关键创新在于其第一层连接输入和隐藏层的权重矩阵被强制约束为一种叫做CP分解的形式。你可以把它想象成一个庞大的权重矩阵连接所有输入特征和隐藏神经元被拆解成了几个小得多的因子矩阵的乘积。这么做的巨大优势是什么参数爆炸式减少假设输入是一个 7x7x200 的像素块共9800个原始特征一个普通的全连接层如果有100个神经元就需要近100万个参数。而通过低秩CP分解例如秩R5参数数量可能骤降到几千个。这直接对抗了过拟合——模型不会去死记硬背那寥寥几个训练样本的噪声而是去学习更本质、更泛化的特征。保留结构信息分解过程隐式地建模了空间维度和光谱维度之间的交互让提取的特征嵌入即隐藏层的输出天然地融合了光谱-空间信息。所以张量嵌入扮演了“特征精炼师”的角色。它把原始高维、冗余、可能含有噪声的像素块压缩成一个低维、紧凑、但信息密度更高的特征向量。这个向量就是我们后续所有操作的基石。2.2 图半监督学习让标签在“关系网”中流动有了好的特征表示下一步就是利用无标签数据。图学习是半监督学习中非常直观有效的一派。它的核心思想是“物以类聚”。建图我们把每个像素点现在用它的张量嵌入向量表示看作图中的一个“节点”。然后计算节点之间的相似度比如用高斯核函数如果两个节点特征向量很相似我们就在它们之间连一条“边”边的权重代表相似程度。这样所有数据点有标签无标签就构成了一张关系网。标签传播现在少数有标签的节点就像几个染了色的水源。标签传播算法会让这些颜色标签信息沿着图的边根据边的权重相似度逐渐扩散到整个网络。相似度高的节点之间颜色更容易流动。经过迭代最终每个无标签节点都会根据其邻居节点的标签和连接强度获得一个预测标签。这个过程的美妙之处在于它完全是无监督地利用了整个数据集的内在几何结构。模型不再仅仅看孤立的样本而是看样本在特征空间中的“邻里关系”来做出判断。2.3 协同增效112 的逻辑那么为什么要把这两者结合起来单独用图学习直接用原始像素特征建图不行吗实测下来真的不行或者说效果不好。高光谱原始数据维度太高、噪声大直接计算相似度构建的图质量很差会包含大量错误的连接把不同类别的点连在一起。垃圾进垃圾出在这样的图上做标签传播效果自然不理想。而张量嵌入正是解决这个问题的钥匙。Rank-R FNN 通过小样本训练后其产生的嵌入向量是经过网络“理解”和“提纯”后的特征。在这个嵌入空间里同类样本会聚集得更紧密。异类样本会分得更开。数据的流形结构更加清晰。用这样的高质量嵌入来构建相似度图图的精度会大幅提升。一个更干净的图意味着标签传播的路径更准确最终分类性能的飞跃也就水到渠成。这就好比你要在一个城市里找人分类如果给你一张标注了少数地标有标签数据的精确地图高质量嵌入构建的图你很容易推理出其他位置是什么但如果地图本身画得歪歪扭扭、错误百出低质量原始特征建的图你就很可能迷路。3. 实操全流程从数据到结果纸上谈兵终觉浅下面我结合实验中的具体设置拆解整个实现流程。你需要准备的“食材”包括高光谱数据集、Python环境如PyTorch/TensorFlow、以及图学习库如scikit-learn扩展或专门的图学习包。3.1 数据准备与预处理我们以公开的Indian Pines数据集为例。它有 145 个光谱波段16 种地物类别共约1万个已标注像素。第一步构建空间-光谱样本块直接对单个像素分类会丢失空间上下文信息。我们采用一个滑动窗口以目标像素为中心截取一个s x s大小的空间邻域形成一个s x s x 145的三维张量块X_x,y。这里s是奇数如5或7。我们假设这个小块的中心像素标签代表了整个小块的标签。这是合理且常见的做法能有效引入空间信息。import numpy as np def extract_patches(data, labels, window_size5): 从高光谱图像中提取以每个标注像素为中心的块。 data: 高光谱图像 (height, width, bands) labels: 标注图像 (height, width) window_size: 块的空间尺寸奇数 half window_size // 2 patches, patch_labels [], [] # 获取所有有标注的像素坐标 rows, cols np.where(labels 0) for r, c in zip(rows, cols): # 提取块处理边界这里用0填充 r_start, r_end r - half, r half 1 c_start, c_end c - half, c half 1 patch np.pad(data, ((half, half), (half, half), (0,0)), modeconstant)[r_start:r_end, c_start:c_end, :] patches.append(patch) patch_labels.append(labels[r, c]) return np.array(patches), np.array(patch_labels) - 1 # 标签通常从0开始第二步数据集划分与极小样本设置这是模拟现实困境的关键。我们不能用太多标注数据。将总数据按类别分层采样分成6份6-fold cross-validation。对于每一折的训练集我们进行极度稀疏采样从每类中随机抽取 α 个样本例如 α 10, 20, 30作为有标签训练集。再额外抽10个/类作为验证集用于控制张量网络训练如早停。该折剩下的训练集样本和整个测试集都作为无标签数据池。我们会从这个池子里按比例如20% 40% 60%抽取数据加入到图学习的构建中。注意这里的“无标签”在评估时是有真实标签的只是不用于初始训练。我们以此来模拟真实世界中大量无标签数据可用的场景。第三步数据归一化将每个样本块X_x,y在光谱维度上进行最小-最大归一化到 [0, 1] 区间加速网络收敛。def min_max_normalize(patches): 对每个样本块进行逐波段的归一化 # patches shape: (n_samples, height, width, bands) min_vals patches.min(axis(1,2), keepdimsTrue) max_vals patches.max(axis(1,2), keepdimsTrue) normalized (patches - min_vals) / (max_vals - min_vals 1e-10) return normalized3.2 阶段一训练Rank-R FNN获取张量嵌入这是整个流程的特征工程核心。我们需要实现或找到一个支持CP分解权重约束的神经网络层。网络结构简述输入层接收形状为[batch_size, s, s, bands]的张量。CP分解层自定义层这是关键。该层不直接使用一个大权重矩阵W而是存储D个小的因子矩阵W_d对于三维输入D3。前向传播时通过Khatri-Rao积实时计算vec(W)再与拉平的输入做内积。输出维度是隐藏神经元数量q。隐藏层激活对CP层的输出使用ReLU等激活函数。输出层一个普通的全连接层接Softmax输出类别概率。训练要点目标我们不是追求这个网络本身的分类精度达到极致而是要它学到一个好的特征转换器。因此验证集的损失或精度用于早停即可。关键超参数分解秩 R控制模型的容量和参数效率。R太小模型欠拟合R太大可能过拟合且计算量增加。实验表明对于高光谱数据R3或5通常是个不错的起点。隐藏神经元数 q即嵌入向量的维度。它决定了输出特征的尺寸。并非越大越好需要平衡信息保留和后续图构建的计算复杂度。q50或75是常见选择。输出嵌入训练完成后我们丢弃最后的输出层。将预处理后的数据包括所有有标签和无标签样本输入网络并提取CP层激活后的输出即隐藏层的值。这个q维的向量就是每个样本的“张量嵌入”。# 伪代码示意提取嵌入 def get_tensor_embeddings(model, dataloader): model.eval() embeddings, all_labels [], [] with torch.no_grad(): for patches, labels in dataloader: # 前向传播至隐藏层 hidden_activation model.cp_layer(patches) # 假设cp_layer是返回隐藏层输出的方法 embeddings.append(hidden_activation.cpu().numpy()) all_labels.append(labels.cpu().numpy()) return np.vstack(embeddings), np.concatenate(all_labels)3.3 阶段二基于嵌入构建图并应用SSL算法现在我们有了所有样本少量有标签L大量无标签U的q维嵌入向量。接下来进入图学习阶段。第一步构建相似度图我们采用最常用的k-最近邻k-NN图或ε-邻域图。这里以k-NN图为例计算所有样本嵌入向量两两之间的欧氏距离或余弦相似度。对于每个节点i找到距离它最近的k个节点不包括自己。在节点i和这k个邻居之间建立无向边。边的权重W_ij通常用高斯热核函数计算W_ij exp(-||x_i - x_j||^2 / (2σ^2))其中σ是尺度参数可以取所有成对距离的中位数。from sklearn.neighbors import kneighbors_graph import scipy.sparse as sp def build_knn_graph(embeddings, k10, sigmaNone): 构建k-NN相似度图 n_samples embeddings.shape[0] # 计算k-NN连接性矩阵二进制表示是否邻居 connectivity kneighbors_graph(embeddings, n_neighborsk, modeconnectivity, include_selfFalse) # 计算距离矩阵这里kneighbors_graph不直接返回距离需另算 from sklearn.metrics.pairwise import euclidean_distances dist_matrix euclidean_distances(embeddings) # 将距离转换为相似度权重仅对k-NN连接应用 if sigma is None: # 启发式设置sigma取所有距离的中位数 sigma np.median(dist_matrix[dist_matrix 0]) similarity np.exp(-dist_matrix**2 / (2 * sigma**2)) # 只保留k-NN连接的权重 adjacency connectivity.multiply(similarity) # 点乘非连接处为0 # 通常使矩阵对称因为k-NN可能不对称 adjacency (adjacency adjacency.T) / 2 return adjacency第二步应用图半监督学习算法我们将构建好的图邻接矩阵W、有标签节点的索引及其真实标签、无标签节点的索引输入到SSL算法中。实验对比了多种算法其中基于拉普拉斯正则化的方法表现最为稳健。以经典的Label Propagation (LP)算法为例其核心思想是迭代地让每个节点的标签向其邻居加权平均更新而有标签节点的标签在迭代过程中会被“钳制”回初始值。# 伪代码示意Label Propagation 核心迭代 def label_propagation(adjacency, labels, labeled_mask, max_iter1000, tol1e-3): adjacency: 相似度矩阵已归一化如对称归一化拉普拉斯相关 labels: 初始标签矩阵one-hot形式无标签处为0 labeled_mask: 布尔数组True表示该节点有标签 n_nodes adjacency.shape[0] # 初始化预测标签 Y labels.copy() for it in range(max_iter): Y_new adjacency Y # 标签传播步骤 # 钳制有标签节点的值 Y_new[labeled_mask] labels[labeled_mask] # 检查收敛 if np.linalg.norm(Y_new - Y) tol: break Y Y_new # 对于多分类取概率最大的类作为预测 predictions np.argmax(Y, axis1) return predictions在实际实验中我们测试了多达11种图SSL算法包括拉普拉斯相关Lap, LapRePo, LapWNL泊松方程PoCG, PoSpe随机游走LaWaMBO方案MMBO, VMBO稀疏标签传播SpLap-拉普拉斯p-Lap3.4 性能评估与对比评估采用分层6折交叉验证重复多次以消除随机性。核心评估指标是F1-score宏平均因为它能更好地处理类别不平衡问题高光谱数据中各类别像素数通常差异很大。对比基线Rank-R FNN本身作为一个纯监督模型仅使用那极少量的有标签数据训练和预测。核心发现嵌入质量至关重要使用 Rank-R FNN 提取的嵌入相比原始像素特征能显著提升所有图SSL算法的性能。这证实了高质量嵌入能构建更优的图。算法差异性并非所有SSL算法都能同等受益。基于拉普拉斯正则化的方法如Lap, LapWNL和随机游走LaWa表现最稳定、最优。而一些更复杂的方法如MBO变体在不平衡数据上提升有限甚至可能因参数敏感而表现不佳。无标签数据量的收益递减增加用于图构建的无标签数据比例从20%到60%初期能提升分类精度但达到一定比例后如40%性能提升变得微乎其微而计算成本建图复杂度O(n²)却显著增加。这表明存在一个“性价比”最高的无标签数据用量阈值。统计显著性通过配对t检验像Lap这样的方法相比纯监督的Rank-R FNN在F1分数上的提升是统计显著的p值远小于0.001。4. 关键参数、调优与避坑指南在实际复现和应用这个方法时以下几个点的把握直接决定了成败。4.1 张量网络训练的关键Rank (R) 与隐藏层大小 (q) 的权衡这不是越大越好。我们的实验表明对于Indian Pines和Salinas数据集R5, q50 与 R5, q75 效果接近但后者参数更多。建议从较小的R和q开始如R3q50如果欠拟合训练集和验证集损失都高再逐步增加。盲目增大不仅增加训练时间还可能在小样本上导致过拟合。样本块大小 (s)我们测试了5和7。s5在大多数情况下已经足够捕获局部空间纹理且计算负担更小。s7可能引入更多来自邻域不同类别的噪声特别是对于边缘像素。除非地物目标非常大否则优先选择s5。训练技巧由于标签数据极少务必使用早停Early Stopping耐心值patience设小一点如5-10轮。强烈建议使用权重衰减L2正则化和Dropout即使在隐藏层后来进一步抑制过拟合。学习率不宜过大使用学习率调度器如ReduceLROnPlateau是稳妥的选择。4.2 图构建的陷阱与技巧相似度度量与尺度参数 σ欧氏距离高斯核是最常用的。σ 的选择非常关键。一个稳健的启发式方法是取所有成对距离的中位数。也可以尝试取第k近邻距离的平均值。如果 σ 太小图变得稀疏信息无法有效传播σ 太大图过于稠密不同类别可能被错误连接。近邻数 kk 决定了图的局部连通性。k 太小图不连通标签无法传播到孤立区域k 太大图包含太多不相关连接引入噪声。一个经验法则是从k log(n)或k10左右开始尝试观察性能变化。可以将其视为一个需要轻微调优的超参数。图的归一化在将邻接矩阵W输入给许多SSL算法如Label Propagation前需要进行归一化例如对称归一化D^{-1/2} W D^{-1/2}其中D是度矩阵。这能提高算法的数值稳定性和收敛速度。处理大规模数据当无标签数据量很大时n 10000构建全连接k-NN图O(n²)会内存爆炸。此时必须使用近似最近邻搜索如Annoy, Faiss, HNSW来高效构建稀疏图。或者可以考虑锚点图方法用远少于n的锚点来构建图将复杂度从 O(n²) 降至 O(nm)其中m是锚点数量。4.3 SSL算法选择与使用心得首选拉普拉斯类方法如果你的目标是稳定、可解释的提升从标准的Label Propagation或基于拉普拉斯正则化的方法开始。它们实现简单超参数少主要就是传播的迭代次数和停止容差且在我们的实验中表现最稳健。警惕计算复杂度MBO、p-Laplace等方法虽然数学上很优雅但计算成本通常更高且对超参数如p-Laplace中的p值更敏感。在类别严重不平衡的数据集上它们可能表现不稳定。不建议在初次尝试或生产环境首选这些复杂方法。“无标签数据越多越好”是个误区我们的实验清晰地表明当无标签数据量达到总数据量的一个比例例如40%-50%后性能增长曲线会极度平缓。盲目使用全部无标签数据只会徒增计算时间而不会带来显著精度提升。建议进行一个简单的消融实验绘制不同无标签数据比例下的性能曲线找到那个“拐点”。标签置信度与迭代在标签传播中有标签节点的标签是“硬钳制”的。但在一些改进算法中可以考虑对有标签节点的置信度进行软性约束或者引入“标签吸收”的概念让传播过程更平滑。5. 常见问题与排查实录在实际跑通这个流程的过程中你肯定会遇到各种问题。下面是我踩过的一些坑和解决方案。Q1: 张量网络训练损失不下降或者很快过拟合。检查点首先确认你的数据预处理归一化是否正确。输入数据是否在合理范围如[0,1]。学习率这是最常见的问题。对于小样本训练学习率必须设得非常小例如1e-4或1e-5。尝试使用学习率查找器LR Finder或简单地以10倍为单位逐步调小。正则化你是否使用了足够的正则化增加权重衰减系数如1e-4在CP层后或隐藏层后加入Dropout如0.3-0.5。Rank R是否太小如果损失从一开始就很高且不降可能是模型容量不足欠拟合。尝试将R从3增加到5。验证集划分确保验证集是从与训练集同分布的有标签数据中划分出来的并且没有数据泄露。Q2: 图SSL算法预测结果全是同一个类别。检查图连通性你的图可能是由几个不连通的子图组成的而标签只存在于其中一个小子图里。计算图的连通分量。确保k值足够大使得整个图是连通的或者至少大多数节点在一个大连通分量内。检查相似度权重如果σ设置得极大所有边的权重都接近1会导致标签迅速均匀化。如果σ设置得过小权重矩阵几乎为零标签无法传播。打印出权重矩阵的统计信息均值、方差确保它是一个合理的稀疏矩阵有明确的大小差异。算法收敛问题有些迭代算法可能不收敛。增加最大迭代次数并打印每次迭代后预测值的变化范数观察其是否趋于稳定。Q3: 整体流程跑通了但效果比论文里报告的差很多。复现一致性首先确保你使用的数据集版本、训练/验证/测试集的划分比例、以及评价指标是整体精度OA还是每类F1的宏平均与论文完全一致。高光谱数据集的预处理如去除水汽吸收波段版本不同结果差异会很大。超参数差异论文中可能经过了细致的超参数调优。请仔细核对样本块大小s、RankR、隐藏层大小q、图构建的k和σ、SSL算法的内部参数如正则化系数。随机性由于采样选取有标签样本、划分数据具有随机性单次运行的结果可能有波动。务必进行多次运行例如10次并报告平均性能和标准差这才是可靠的比较。实现细节张量网络的CP分解层实现是否正确前向传播计算是否与公式对应图构建时是否对邻接矩阵进行了正确的对称化和归一化这些细节的偏差都会导致性能损失。Q4: 面对新的高光谱数据集如何确定一套可行的启动参数这是一个非常实际的问题。我的建议是建立一个参数搜索基线张量网络固定s5尝试(R, q)组合[(3,50), (5,50), (3,75), (5,75)]。使用极小的有标签数据如每类5个快速训练看哪个组合在验证集上收敛最快且损失最低。图构建固定使用表现稳健的Lap算法。对于k尝试[5, 10, 15]。对于σ先用“距离中位数”的启发式方法然后在其0.5倍和2倍附近微调。无标签数据量从20%开始增加到40%观察性能增益。如果增益明显再试60%如果增益很小则40%可能已足够。这个方法的核心优势在于其模块化和可解释性。你可以清晰地看到是张量嵌入的提升带来了图质量的提升进而带来了最终分类性能的提升。它不像一个端到端的黑箱模型其每个环节都有调整和优化的空间。虽然它涉及两个阶段看起来比单一模型复杂但在标注数据极其稀缺的现实约束下这种“精心准备食材嵌入再巧妙烹饪图学习”的策略往往是达成高精度结果的更务实、更可靠的路径。