文章目录
论文笔记
摘要
- HSI分类的性能对空间和光谱信息都有很强的依赖性
- 空间3-D-CNN有助于从一堆光谱波段中进行联合空间-光谱特征表示
- 2-D-CNN进一步学习了更抽象的空间表示
- 混合CNN降低了模型的复杂性
介绍
高光谱图像 HSI
特点
- 高光谱像元引入了高的组内变异性,高的组间相似性表现出混合的土地覆盖类型
- 多波段
- 传达光谱信息、不同波段之间的空间相关性
手工设计特征提取技巧
- 基于局部自适应字典的联合协作表示方法减少了无用像素的不利影响,提高了ESHSI分类性能
- 对不同谱带之间的关系进行编码用局部协方差矩阵进行HSI训练,用支持向量机(SVM)进行分类
基于学习的特征提取
-
思想
1⃣️提取层次空间特征
2⃣️与支持向量机一起用于训练和分类 -
双程网络(DPN)结合剩余网络和密集卷积网络
-
无监督训练的greedylayerwise方法表示遥感图像
-
数据增强技术推广HSI分类的深度学习基于像素块对(PBP)
2-D-CNN
- 核心
对输入数据进行处理,以覆盖整个空间维度 - 将相关特征通过激活函数引入模型的非线性
- 卷积只应用在空间维度上
覆盖了前一层的所有特征图,计算二维特征图 - 不能处理光谱信息
对于HSI分类问题,需要捕获编码在多个波段中的光谱信息以及空间信息 - 由于增加了谱带间冗余度,在这个角度上是优于三维CNN
- 只使用二维CNN的缺点
缺少信道关系信息
无法从光谱维度中提取出具有良好识别能力的特征图
3-D-CNN
-
在HSI数据模型中
三维CNN核可以同时从HSI数据中提取光谱和空间特征 -
只使用三维CNN的缺点
模型非常复杂
性能很差
对在许多光谱带上具有相似纹理的类
由此就提出了混合CNN模型
组合二维CNN和三维CNN
充分利用光谱和空间特征图,以实现最大可能的效果准确
充分利用2-D和3-DCNN的自动特征学习能力
-
流程图
三个三维卷积,一个二维卷积,flatten 展评为一维向量,三个全连接层,输出为 16 个节点,是最终的分类类别数 -
所有的权值都是随机初始化的
-
通过使用tmaxloss函数的DAM优化器使用反向传播算法进行训练
-
消除谱冗余
1⃣️对原始HSI数据(I)沿谱带进行传统的主成分分析(PCA)
2⃣️将HSI数据立方体划分为小重叠的三维面片
实验和分析
公平比较
对不同的数据在输入体的三维面片中提取了相同的空间维数
分类结果的指标
- 总体准确度(OA)—表示总测试样本中正确分类的样本数
- 平均准确度(AA)—表示分类精度的平均值
- Kappa系数(Kappa)提供了关于地面真值图和分类图之间的强一致性的相互信息
混合神经网络模型
在几乎所有情况下都优于其他方法
结论
本文介绍的用于HSI分类的三维和二维混合模型以三维和二维卷积的形式结合了空间光谱和光谱的互补信息
……
优越性
- 在三个基准数据集上的实验结果与现有的方法进行了比较
- 比三维CNN模型具有更高的计算效率
- 对于较小的训练数据,它也显示出优越的性能
代码实现
取得数据
! wget http://www.ehu.eus/ccwintco/uploads/6/67/Indian_pines_corrected.mat
! wget http://www.ehu.eus/ccwintco/uploads/c/c4/Indian_pines_gt.mat
! pip install spectral
引入基本函数库
import numpy as np
import matplotlib.pyplot as plt
import scipy.io as sio
from sklearn.decomposition import PCA
from sklearn.model_selection import train_test_split
from sklearn.metrics import confusion_matrix, accuracy_score, classification_report, cohen_kappa_score
import spectral
import torch
import torchvision
import torch.nn as nn
import torch.nn.functional as F
import torch.optim as optim
根据流程图创建HybridSN 类
class HybridSN(nn.Module):
def __init__(self):
super(HybridSN, self).__init__()
#三维卷积
self.conv3d_1 = nn.Sequential(
nn.Conv3d(1, 8, kernel_size=(7, 3, 3), stride=1, padding=0),
nn.BatchNorm3d(8),
nn.ReLU(inplace = True),
)
self.conv3d_2 = nn.Sequential(
nn.Conv3d(8, 16, kernel_size=(5, 3, 3), stride=1, padding=0),
nn.BatchNorm3d(16),
nn.ReLU(inplace = True),
)
self.conv3d_3 = nn.Sequential(
nn.Conv3d(16, 32, kernel_size=(3, 3, 3), stride=1, padding=0),
nn.BatchNorm3d(32),
nn.ReLU(inplace = True)
)
#二维卷积
self.conv2d_4 = nn.Sequential(
nn.Conv2d(576, 64, kernel_size=(3, 3), stride=1, padding=0),
nn.BatchNorm2d(64),
nn.ReLU(inplace = True),
)
#flatten展平
self.fc1 = nn.Linear(18496,256)
#全连接层,都使用比例为0.4的 Dropout
self.fc2 = nn.Linear(256,128)
self.fc3 = nn.Linear(128,16)
self.dropout = nn.Dropout(p = 0.4)
def forward(self,x):
out = self.conv3d_1(x)
out = self.conv3d_2(out)
out = self.conv3d_3(out)
out = self.conv2d_4(out.reshape(out.shape[0],-1,19,19))
out = out.reshape(out.shape[0],-1)
out = F.relu(self.dropout(self.fc1(out)))
out = F.relu(self.dropout(self.fc2(out)))
#输出为 16 个节点,是最终的分类类别数
out = self.fc3(out)
return out
定义基本函数
# 对高光谱数据 X 应用 PCA 变换
def applyPCA(X, numComponents):
newX = np.reshape(X, (-1, X.shape[2]))
pca = PCA(n_components=numComponents, whiten=True)
newX = pca.fit_transform(newX)
newX = np.reshape(newX, (X.shape[0], X.shape[1], numComponents))
return newX
# 对单个像素周围提取 patch 时,边缘像素就无法取了,因此,给这部分像素进行 padding 操作
def padWithZeros(X, margin=2):
newX = np.zeros((X.shape[0] + 2 * margin, X.shape[1] + 2* margin, X.shape[2]))
x_offset = margin
y_offset = margin
newX[x_offset:X.shape[0] + x_offset, y_offset:X.shape[1] + y_offset, :