ARTICLE DETAIL

资讯详情

深耕郑州网站建设与运营推广的一线实战洞察。

小样本高光谱图像分类实战:数据增强与原型网络提升精度

小样本高光谱图像分类实战:数据增强与原型网络提升精度 简介本资源是一套面向深度学习初学者与进阶研究者的高光谱图像分类实践方案聚焦小样本条件下的模型构建与训练难题适用于本科毕设、课程设计、工程实训及科研入门场景。压缩包共38个文件含6个核心Python脚本如demo.py主入口、hyper_net.py网络定义、10个npy格式高光谱数据集涵盖Indian Pines、PaviaU、Salinas等经典数据、6张可视化结果图png、5个标注XML文件及模型权重pt、说明文档md等整体大小62.19MB结构清晰、模块解耦便于快速复现与二次开发。已有238人学习下载。用户可直接运行demo.py启动训练流程支持自定义网络结构——参考hyper_net.py模板即可扩展新模型所有非npy格式的高光谱数据均可通过专用库读取后转为ndarray并保存为npy实现无缝接入。 直接开写。高光谱图像分类一直是遥感领域的老大难问题尤其是标注样本稀缺的场景下训练深度学习模型简直就是戴着镣铐跳舞。这篇博文我就拿自己做的一个完整小项目来复盘把从数据预处理、模型设计、训练策略到实验对比的全过程掰开揉碎讲清楚也把那些论文里从来不写、但实际跑起来一定会踩的坑一并交代干净。1. 小样本高光谱分类问题到底难在哪先给刚接触这个方向的朋友交代一下背景。高光谱图像和普通RGB图像最大的区别在于波段数RGB只有3个波段而高光谱相机一次成像能捕获几百个连续窄波段的光谱信息。也就是说图像里的每一个像素都对应一条接近连续的光谱曲线。这类数据通常用三维立方体来描述长、宽代表空间维度深度代表光谱维度。分类任务的目标是给每个像素打上地物类别标签比如建筑物、植被、水体、道路等。传统做法是提取光谱特征或空间纹理特征再喂给SVM、随机森林这类浅层模型。后来深度学习崛起CNN在处理这类问题时表现确实更好因为CNN既能挖掘光谱维度的深层次抽象特征又能同时利用像素周围的空间上下文信息。但问题很快暴露了。高光谱图像的标注成本极其昂贵一个像素的类别标签往往需要实地勘查或者依赖高精度参考数据来确定不可能像ImageNet那样动辄百万张标注图片。实际项目中每个类别能拿到的训练样本可能只有几个到几十个像素这就是典型的小样本场景。在这种条件下硬上深度模型会立刻撞上两个致命问题。第一个是过拟合模型参数量远大于样本量训练几轮之后loss就趋近于零但验证集的准确率反而在下跌纯粹是死记硬背。第二个是维度灾难高光谱数据的特征维度高动辄上百维而样本量又小特征空间被撑得极其稀疏分类器根本找不到可靠的决策边界。所以这个项目的核心命题就变成了如何在仅有的少量标注样本约束下让深度学习模型学到具有泛化能力的特征表示。这需要从数据增强、模型结构、训练策略、分类机制四个层面同时发力而不是简单套一个现成的CNN框架就完事。2. 整体方案选型与设计思路2.1 路线选择生成更多样本还是榨干已有样本小样本学习的解决思路大致能分成两派。一派认为既然样本少那就想办法生成更多样本对应的技术是各种数据增强手段和生成对抗网络。另一派则认为应该改进模型本身让它在少量样本上也能学到高效特征对应的是度量学习、元学习、迁移学习这类方法。两条路线各有适用场景。生成对抗网络在高光谱领域其实不太好使因为光谱数据的高维特性导致生成器很难稳定训练生成的光谱曲线常常在物理上就不合理比如出现负反射率或者超出传感器响应范围的值而且训练GAN本身就需要大量数据在极端小样本下容易崩塌。我更倾向于两派都用一点但以度量学习作为主骨架。具体来说方案设计成三个模块的组合数据层面设计针对高光谱数据特性的光谱-空间联合增强策略让小样本在训练时能呈现出更多样的形态。模型层面用CNN做特征提取器但分类头不用传统的Softmax换成原型网络Prototype Network的度量分类方式。训练层面采用分段训练策略先在大规模无标注数据上做自监督预训练再用少量标注样本做微调。这里面最核心的设计决策是把Softmax分类头换成原型网络。传统Softmax分类器本质上是在学习一个线性决策边界在类别多、样本少的情况下这个决策边界会被拉到非常扭曲的位置。原型网络的做法是每个类别只用所有支撑样本的特征向量取平均得到一个类别原型Prototype分类时直接计算查询样本特征与每个原型的欧氏距离距离最近的那个类别就是预测结果。这种基于距离度量而不是线性分界面的分类方式天然更适应小样本场景道理就像你判断一个人是哪个地方的看他和哪个地方的人群特征最相似比硬画一条分界线要稳健得多。2.2 数据集选择与评估基准实验我选了两个公开标准数据集一个是Indian Pines另一个是Pavia University。选它们的理由有两个一是这两个数据集在遥感分类领域被所有论文用烂了结果可对比性强二是它们的场景差异大Indian Pines是农业场景Pavia University是城市场景类别数和空间分辨率都不一样能检验方法的泛化能力。小样本的设置是这样构造的每个类别随机抽取5个、10个、15个样本作为训练集剩下的样本全部作为测试集。这里有个虽然简单但很重要的细节高光谱像素之间具有很强的空间自相关性相邻像素大概率属于同一类别。如果随机采样时不小心把训练样本和测试样本取成了空间邻居那测试准确率会虚高论文里管这叫信息泄漏。为了避免这个问题我用了专利和论文里常见的做法——按区域分块采样确保训练集和测试集之间至少间隔一段距离。3. 数据预处理与增强实现细节3.1 维度压缩PCA保留多少主成分才合理高光谱数据的原始维度通常在200个波段左右Indian Pines是200波段Pavia University是103波段。这些相邻波段之间存在极强的相关性直接全部喂给网络不仅计算量大而且冗余信息会干扰特征学习。我用PCA做降维但这里有个很多人容易忽略的问题降维不是越多越好。保留的主成分太少会丢失有判别力的细粒度光谱信息保留太多又起不到抑制噪声和冗余的效果。在实际实验中我做了个主成分数量的对比实验分别尝试了10、20、30、40、50个主成分在相同模型结构下观察分类效果。结果是Indian Pines这个数据集上30个主成分效果最好Pavia University上25到30个主成分就足够。再增加主成分数量分类准确率不仅不再提升反而略微下降。原因在于后面的主成分对应的特征值已经很小主要是传感器噪声把它们加进来等于给模型引入噪声特征。所以最终方案是将原始光谱降到30个主成分同时保留解释方差比例这个指标作为参考一般达到98%以上就说明降维基本没有损失有效信息。3.2 空间邻域抽取为什么用11x11的patch而不是单像素高光谱分类有两种基本输入模式一种是只取单个像素的光谱向量作为输入叫光谱分类另一种是以目标像素为中心取一个固定大小的空间窗口patch连同窗口内的空间邻域信息一起输入模型叫光谱-空间联合分类。单像素输入在早期研究中很常见做法简单但信息量确实不够。真实地物不是孤立存在的建筑物周围大概率有道路或者植被这种空间上下文关系对于判别中心像素非常关键。就好比你判断一张照片里某个物体是什么不可能只看那一个像素的颜色而是会看它周围的环境。我采用以目标像素为中心的11x11空间patch作为输入。这个窗口大小是通过对比实验确定的选了7x7、9x9、11x11、13x13、15x15五档对比发现11x11和13x13效果接近但11x11的计算开销更小。窗口太小空间上下文信息不足窗口太大会引入远离中心像素的无关地物反而产生干扰而且会加剧边界像素的混合效应。这里需要特别提醒一个操作细节在构造训练集时取窗口会碰到图像边界。对边缘像素常见的做法是零填充或者镜像填充。实测下来镜像填充比零填充效果好因为零填充会在窗口里引入大量黑色区域相当于人为制造了不存在的特殊地物模型会学到这种假特征。3.3 光谱与空间增强策略高光谱小样本场景下的数据增强和普通图像增强不完全一样。普通图像可以直接翻转、旋转、裁剪、加噪声但高光谱数据如果胡乱增强很容易破坏光谱曲线的物理合理性。比如把某个波段的反射率整体增强那这个像素就不再是任何真实地物的光谱特征了。我的增强策略分成光谱维度和空间维度两组训练时随机组合使用。光谱维度的增强手段包括以下四种光谱噪声注入在光谱曲线上添加高斯噪声标准差设定为该像素光谱均值的1%到2%模拟传感器噪声。光谱插值扰动随机选择一对相邻波段用线性插值替换这两个波段的原始值模拟光谱分辨率的变化。增益扰动对整条光谱曲线乘以一个在0.95到1.05之间随机采样的缩放系数模拟光照条件差异。波段丢弃随机丢弃5%的波段并用相邻波段的均值填补模拟波段损坏的情况。空间维度的增强手段相对常规一些包括水平翻转、垂直翻转、旋转90度、180度、270度以及随机裁剪加填充。这一类操作不会改变每个像素的光谱曲线本身只是改变空间排列所以安全无害。这些增强手段的综合效果相当于把原本只有5个样本的类别在训练视角下扩展成了几十种不同的形态大幅缓解了过拟合问题。4. 模型结构设计与核心代码实现4.1 特征提取网络残差连接与注意力机制的组合特征提取骨干网络是整个模型的承重墙。考虑到输入是30通道的11x11patch数据规模不大我选择了轻量级的3D-CNN加2D-CNN混合结构而不是直接上ResNet这种重模型。理由很直接输入尺寸只有11x11ResNet在这个尺度上发挥不出深层网络的威力反而容易过拟合。网络结构分三阶段第一阶段用3D卷积同时提取光谱维度和空间维度的特征第二阶段把3D特征降维成2D特征图交给2D卷积处理等效于先做光谱信息融合再做空间特征提取第三阶段接入注意力模块让网络自动聚焦对分类最有判别力的特征通道。这里我加了两个细节设计。第一个是残差连接在每个卷积块中引入跳跃连接缓解梯度消失问题的同时也能让梯度在小样本条件下更容易传播到浅层。第二个是通道注意力模块借鉴了SENet的思路对特征图的每个通道计算全局平均池化得到通道描述向量再经过两层全连接得到每个通道的权重最后把权重乘回原始特征图。这个模块的作用是让模型学会哪些光谱特征重要、哪些不重要在高光谱分类中特别有效因为不同地物的区分往往只依赖少数几个特征波段注意力机制正好能强化这些关键波段的作用。4.2 原型网络分类头的实现分类部分是整个方案和普通CNN的最大差异点。传统CNN的最后一层是Softmax分类器输出每个类别的概率。原型网络的做法是在训练时对每个类别把该类所有支撑样本的特征向量取平均得到该类的原型向量。分类时把测试样本的特征向量与所有原型向量计算欧氏距离距离最近的类别就是预测结果。这里实现的时候有个关键技巧原型的计算必须用支持集support set和查询集query set分离的方式。训练时每个batch从训练集里随机抽取N个类别每个类别抽K个样本作为支持集再抽Q个样本作为查询集。利用支持集样本计算原型然后用原型去预测查询集的标签计算损失并更新网络参数。这种episodic的训练方式和传统的按batch直接训练不同它让网络在每次迭代中都处在一个小样本分类的任务场景里逼着特征提取器学习对度量分类友好的特征表示。核心训练逻辑的PyTorch代码大致长这样def prototypical_loss(features, labels, n_support, n_classes): # features: 所有样本的特征向量shape [batch_size, feat_dim] # labels: 对应的类别标签 # n_support: 每个类别的支持集样本数 feat_dim features.shape[1] # 分离支持集和查询集 support_features features[:n_classes * n_support] query_features features[n_classes * n_support:] # 计算每个类别的原型取平均 prototypes support_features.view(n_classes, n_support, feat_dim).mean(dim1) # 计算查询样本到所有原型的欧氏距离 dists torch.cdist(query_features, prototypes) # 用log_softmax计算负对数似然损失 query_labels torch.arange(n_classes).repeat( (features.shape[0] - n_classes * n_support) // n_classes ) log_p (-dists).log_softmax(dim1) loss -log_p.gather(1, query_labels.unsqueeze(1)).mean() return loss, prototypes欧氏距离的选择不是拍脑袋决定的。我对比过余弦距离和欧氏距离在Indian Pines数据集上欧氏距离的OA准确率比余弦距离高出2到3个百分点。原因可能是高光谱特征经过网络提取后特征向量的模长本身就携带了类别判别信息欧氏距离能同时利用方向和模长两个维度的差异余弦距离只关注方向丢掉了一部分信息。4.3 预训练与微调的两阶段训练策略虽然原型网络架构本身对小样本友好但如果特征提取器完全从随机初始化开始训练小样本下仍然很难收敛到理想状态。所以我采用了两阶段训练策略。第一阶段是自监督预训练。利用训练集中所有无标注的高光谱数据构造了一个简单的自监督任务随机遮挡patch中心区域让网络预测被遮挡部分的光谱特征。这个预训练任务的本质是让网络学会理解高光谱数据的基本分布规律形成对光谱-空间特征的初步感知。实现上并不复杂就是在特征提取网络后面接一个解码器用重建损失约束。这个阶段不需要任何人工标注因此可以利用的数据量远大于带标签的样本量。第二阶段是原型网络微调。把预训练好的特征提取网络权重当作初始值接上原型分类头用带标签的小样本集做端到端训练。这时学习率要调小预训练阶段我用的是1e-3微调阶段降到1e-4到5e-5防止大步长更新破坏预训练学到的特征分布。这个策略的效果很显著单独对比可以发现随机初始化直接训练原型网络OA大约在78%左右加上自监督预训练后同一条件下的OA能提升到85%以上。预训练阶段虽然增加了总训练时间但对于小样本场景来说完全是值得的。5. 实验设置、结果分析与对比5.1 评估指标OA、AA、Kappa各代表什么高光谱图像分类的评估标准我用了三件套总体分类精度OA、平均分类精度AA和Kappa系数。三者各有侧重。OA是所有测试样本中分类正确的比例直观但容易被样本量大的类别主导AA是先算每个类别的分类精度再取平均对样本量小的类别更公平Kappa系数衡量的是分类结果和随机标注之间的一致性差异数值越高说明分类器的真实判别能力越强。在实际报告结果时这三者必须同时给出。只看OA会掩盖小类别的糟糕表现只看AA又可能被边缘类别拖累。结合来看才能全面评估模型的真实水平。5.2 对比实验与SVM、标准CNN、现有方法的差距为了验证方案的有效性我设置了三组对照实验第一组是SVM加径向基核函数代表传统浅层方法的水平第二组是标准CNN加Softmax分类头代表朴素深度学习方法第三组是本文方案预训练加原型网络加数据增强。在Indian Pines数据集、每类10个训练样本的条件下结果是这样的方法OA (%)AA (%)KappaSVM (RBF核)61.2355.870.576CNN Softmax73.4568.320.706本文方案86.7282.150.847SVM在这个场景下表现最差原因并不意外。虽然SVM在小样本下有一定优势但高光谱数据的高维性和非线性特征对核方法提出了太高要求RBF核的参数在小样本下难以调优而且SVM只能利用光谱维度的信息无法建模空间上下文。标准CNN加Softmax比SVM好了不少说明深度特征提取确实有效但73%的OA距离实用还有很大距离。最核心的问题就是Softmax分类头在每类10个样本的条件下学不到稳健的决策边界。本文方案全面领先OA达到86.72%Kappa系数比CNN加Softmax高出0.14。这个增益主要来自三个层面自监督预训练提供了合理的特征初始化让模型在微调阶段能更快收敛到更优解原型网络的度量分类机制比Softmax更适合小样本数据增强让有限样本在训练中呈现出更多样化的形态。我还进一步做了不同样本量下的梯度实验。从每类5个样本到每类15个样本本文方案的OA从82.1%提升到89.35%而CNN加Softmax从68.5%提升到78.6%。差距在极端小样本下更明显说明度量学习机制在训练数据极度匮乏时发挥的作用更突出。5.3 消融实验每个模块贡献了多少光有最终结果还不够还得搞清楚每个模块各自贡献了多少这既是学术严谨性的要求实际调试时也很有价值。我做了一组消融实验基线是CNNSoftmax无预训练、无增强然后逐步叠加模块。配置OA (%)基线 (CNNSoftmax)73.45 数据增强77.82 原型网络81.36 自监督预训练86.72数据增强贡献了约4.4个百分点的提升说明小样本场景下数据的多样性确实重要。把Softmax换成原型网络又带来约3.5个百分点的提升验证了度量学习在小样本分类中的核心价值。自监督预训练的贡献最大约5.4个百分点说明特征初始化的质量对极端小样本条件下的模型收敛有决定性的影响。6. 训练过程中的坑与排查技巧6.1 类别不均衡引发的训练崩坏高光谱数据集的类别分布极其不均衡。Indian Pines里大豆类别有超过2000个样本而某些类别比如草树、燕麦只有几十个甚至几个样本。在做小样本采样时这种不均衡被进一步放大少数类可能连凑齐5个样本都困难。我一开始直接用原始分布采样结果模型几乎把所有测试样本都预测成了大类OA看起来还行但AA很低Kappa也上不去因为小类别基本全军覆没。后来改成在episodic训练过程中强制保证每个batch里采样的类别覆盖所有类别并且每个类别的支持集和查询集样本数一致。这样一来每个训练任务都是类别均衡的模型不会偏向任何一方。这属于训练策略上的小改动但对AA和Kappa的改善非常明显AA从74.3%直接升到82.15%。6.2 损失函数降不下去的几个排查方向训练过程中如果发现loss一直降不下去或者降得很慢不要急着调学习率先按以下顺序排查。第一步看数据确认PCA降维后的数据是否有NaN或异常值高光谱数据偶尔会出现死波段全部为零或全部为负的情况这些波段如果不清理会持续给loss注入噪声。第二步看特征提取器输出的特征分布如果特征向量的数值范围忽大忽小说明网络初始化可能有问题或者BatchNorm的momentum参数设置不合理。第三步再看学习率如果上述都没问题再考虑学习率是否过大导致loss震荡或者过小导致收敛缓慢。我实际遇到的典型问题是自监督预训练阶段loss降到一定程度后就不再变化一开始以为是数据集太小导致欠拟合。排查半天才发现是解码器在重建时对30个通道等权看待而实际高光谱数据中不同通道的像素值方差差异很大。解决办法是在重建损失里按通道方差的倒数加权让网络优先学好方差小的通道这些通常是信息丰富但数值变化平缓的光谱区域。6.3 类别原型漂移问题与对策训练进入后期时我注意到一个有趣的现象验证集准确率会周期性地出现小幅回落然后又自动恢复。排查后发现这是类别原型在训练后期发生了漂移。因为在微调阶段支持集样本的特征仍在缓慢更新导致原型向量也在不断移动。如果某个时刻的梯度方向恰好让查询样本到原型的距离变远就会造成准确率短暂回落。解决办法是加了一个原型稳定性约束在训练后期让支持集特征在一个较小范围内波动具体做法是对支持集特征做梯度截断或者直接减小微调阶段的学习率。我选择了把微调阶段的学习率在训练后期按余弦退火的方式逐步降到零这样原型向量在后期趋于稳定验证集准确率的周期性波动也随之消失。7. 实际工程部署的几点心得模型训练完成后工程部署阶段还有几个问题需要考虑。参数量方面整个模型只有约280万个参数在GPU上单张11x11patch的推理时间大约0.8毫秒CPU上大约15毫秒。对于一块标准的高光谱影像通常尺寸在几百乘几百像素量级逐像素滑窗推理需要遍历所有像素并提取patch这个计算量不可小觑。如果面对的是数千乘数千像素的大幅影像建议在推理阶段做优化比如对patch提取做批量预处理一次提取全部像素的patch并按batch喂入模型能比单像素循环快10倍以上。模型导出方面PyTorch模型部署时建议用TorchScript或者ONNX格式导出推理时不再依赖Python环境。我用ONNX导出后在CPU上的推理速度又提升了20%左右。另外有个细节值得分享在实际处理整幅高光谱影像时不能只取影像中心的11x11patch边界像素要特殊处理。我的做法是先把整幅影像做镜像扩展pad 5个像素然后对所有位置取patch这样得到的预测结果维度刚好和原始影像一致不需要额外的后处理修正。还有一点小样本模型在单个数据集上表现好不代表换一个场景仍然好用。我用Indian Pines训练的模型直接拿去跑Pavia University的数据效果非常差因为两个数据集的光谱响应范围和地物类别完全不同。所以在实际场景中如果目标域的标注数据极少建议做一次轻量的域适应比如用目标域的无标注数据对预训练阶段做一次微调再配合极少量标注数据做原型网络训练效果比直接迁移好很多。回头来看这个项目的整体感受是小样本条件下的高光谱分类单点技术突破带来的收益有限真正有效的是把数据增强、特征预训练、度量分类这个组合拳打完。每个模块单独拿出来都不算稀奇但组合在一起之后在小样本条件下取得了接近实用的分类精度。如果你也在做类似的方向建议按照这个思路去搭自己的方案针对具体数据集的特性再做调整遇到问题的时候从数据、模型、训练策略三个层面逐个排查应该会比直接套现成网络快不少。本文还有配套的精品资源点击获取
返回列表