前置内容见链接:https://mp.weixin.qq.com/mp/appmsgalbum?__biz=MzkwMTE0MjI4NQ==&action=getalbum&album_id=3959684907432935425#wechat_redirect
前面的内容我们介绍了很多特征挖掘的内容,那么今天主要通过实验证明特征挖掘到底有没有用。
在遥感图像分类任务中,模型性能的提升往往离不开高质量的特征。当深度学习遇上传统特征工程,会碰撞出怎样的火花?今天我们就通过对比纯CNN模型与融合了形态学属性(Morphological Profiles, MP)的CNN模型,来探讨特征工程在遥感分类中的价值。
一、为什么要做特征挖掘?
遥感图像包含丰富的光谱、空间和纹理信息,但原始数据往往存在维度高、冗余多、噪声干扰等问题。直接将原始数据输入模型,不仅会增加计算负担,还可能因为无效信息过多而影响分类精度。
特征挖掘(特征工程)的核心价值在于:
- 降维提质:保留关键信息,剔除冗余噪声
- 显式建模:将领域知识转化为可量化的特征
- 辅助学习:为模型提供更易学习的表示形式
在遥感领域,形态学属性(MP)就是一种经典的特征工程方法——它通过数学形态学运算捕捉图像中的空间结构信息,非常适合处理遥感图像中常见的地物轮廓、纹理等特征。
二、实验设计:严格对比CNN与CNN+MP
我们以KSC(肯尼迪航天中心)高光谱数据集为研究对象,设计严格的对比实验:
- 数据集:KSC高光谱图像(含176个波段,614×512像素)及对应地物标签
- 核心对比:
- 仅使用PCA降维后的光谱特征(CNN模型)
- 融合PCA特征与多尺度形态学属性(CNN+MP模型)
- 评估指标:总体精度(OA)、平均精度(AA)、Kappa系数、推理速度
三、代码逐段解析
1. 基础工具与参数设置
首先导入必要的库并设置基础工具函数:
import os, time, random
import numpy as np
import scipy.io as sio
import scipy.ndimage as ndi
import pandas as pd
import torch
import torch.nn as nn
from torch.utils.data import Dataset, DataLoader
from sklearn.decomposition import PCA
from sklearn.preprocessing import StandardScaler
from sklearn.metrics import (classification_report, confusion_matrix, accuracy_score,
cohen_kappa_score)
from sklearn.model_selection import train_test_split
import matplotlib
if os.name == 'nt':
try:
matplotlib.use('TkAgg')
except Exception:
matplotlib.use('Agg')
else:
matplotlib.use('Agg')
import matplotlib.pyplot as plt
import seaborn as sns
matplotlib.rcParams['font.family'] = 'SimHei'
matplotlib.rcParams['axes.unicode_minus'] = False
plt.rcParams['figure.dpi'] = 120
sns.set_theme(context="notebook", style="whitegrid", font="SimHei")
torch.backends.cudnn.benchmark = True
基础工具函数:
set_seeds:固定随机种子,保证实验可复现average_accuracy:计算平均精度(AA)make_disk:生成形态学运算所需的圆形结构元素
def set_seeds(seed=42):
random.seed(seed); np.random.seed(seed)
torch.manual_seed(seed); torch.cuda.manual_seed_all(seed)
def average_accuracy(y_true, y_pred, num_classes):
cm = confusion_matrix(y_true, y_pred, labels=list(range(num_classes)))
with np.errstate(divide='ignore', invalid='ignore'):
per_class = np.diag(cm) / cm.sum(axis=1).clip(min=1)
return float(np.nanmean(per_class))
def make_disk(radius: int) -> np.ndarray:
if radius <= 0: return np.array([[1]], dtype=bool)
r = radius
y, x = np.ogrid[-r:r+1, -r:r+1]
return (x*x + y*y <= r*r)
2. 形态学属性(MP)特征构建
形态学属性通过多尺度的开运算(Opening)和闭运算(Closing)提取图像的空间结构特征:
- 开运算(去除小亮结构):先腐蚀后膨胀
- 闭运算(填充小暗区域):先膨胀后腐蚀
def build_morphological_profiles(X_pca_img: np.ndarray,
k_components: int = 8,
radii=(1, 3, 5, 7)) -> np.ndarray:
"""
输入:X_pca_img(H,W,C)。对前k个主成分做多尺度灰度开/闭,构造属性差分通道并拼接。
"""
H, W, C = X_pca_img.shape
k = int(min(k_components, C))
feats = []
for i in range(k):
pc = X_pca_img[..., i] # 取第i个主成分
for r in radii: # 多尺度处理
fp = make_disk(r) # 生成半径为r的圆形结构元素
opened = ndi.grey_opening(pc, footprint=fp) # 灰度开运算
closed = ndi.grey_closing(pc, footprint=fp) # 灰度闭运算
# 存储差分特征:原始-开运算(突出亮结构)、闭运算-原始(突出暗结构)
feats.append((pc - opened).astype(np.float32, copy=False))
feats.append((closed - pc).astype(np.float32, copy=False))
if not feats: # k=0时直接返回原始PCA特征
return X_pca_img
mp_stack = np.stack(feats, axis=-1).astype(np.float32, copy=False)
# 拼接原始PCA特征与形态学特征
return np.concatenate([X_pca_img, mp_stack], axis=-1).astype(np.float32, copy=False)
3. 数据集与模型定义
(1)高光谱图像补丁数据集
class HSIPatchDataset(Dataset):
def __init__(self, patches, labels):
# 转换为PyTorch张量,通道维度前置(H,W,C→C,H,W)
self.X = torch.tensor(patches, dtype=torch.float32).permute(0, 3, 1, 2)
self.y = torch.tensor(labels, dtype=torch.long)
def __len__(self): return len(self.y)
def __getitem__(self, idx): return self.X[idx], self.y[idx]
(2)简单CNN模型
采用轻量级CNN架构,适合高光谱图像分类任务:
class SimpleCNN(nn.Module):
def __init__(self, in_ch, num_classes, width=32):
super().__init__()
self.net = nn.Sequential(
# 第一组卷积:输入通道→32通道
nn.Conv2d(in_ch, width, 3, padding=1, bias=

最低0.47元/天 解锁文章
1170

被折叠的 条评论
为什么被折叠?



