遥感&机器学习入门实战教程|Sklearn案例⑳:支持向量机(SVM)分类

部署运行你感兴趣的模型镜像

本系列最后一篇,我们把目光放到 支持向量机 (Support Vector Machine, SVM)。 SVM 在高光谱遥感中被广泛应用,尤其在样本有限的情况下,常常是最稳健的传统方法之一

🧩 为什么 SVM 适合遥感?

  • 小样本友好:只依赖支持向量,避免过拟合。

  • 非线性可扩展:通过核函数(Kernel)映射到高维空间,实现复杂边界。

  • 可调灵活:核函数、惩罚系数、gamma 等超参数可针对数据分布优化。

⚙️ 关键参数详解

  • kernel:核函数

    • 'linear':线性分割,速度快;

    • 'rbf'(默认):高斯核,常用;

    • 'poly':多项式核,较少用;

    • 'sigmoid':类似神经网络激活函数。

  • C:惩罚系数(越大越注重减少误分类,风险是过拟合)。

  • gamma(RBF核特有):控制样本影响范围,越大越“紧”,越小越“松”。

  • probability:若设为 True,可输出类别概率(代价是训练更慢)。

💻 一键可跑代码(KSC:SVM 分类 + 参数对比 + 全图预测)

# -*- coding: utf-8 -*-
"""
Sklearn案例⑳:支持向量机(SVM)分类(KSC 数据)
"""

import os, numpy as np, scipy.io as sio, matplotlib.pyplot as plt, matplotlib
from matplotlib.colors import ListedColormap, BoundaryNorm

from sklearn.model_selection import train_test_split
from sklearn.preprocessing import StandardScaler
from sklearn.decomposition import PCA
from sklearn.svm import SVC
from sklearn.metrics import (confusion_matrix, classification_report,
                             accuracy_score, cohen_kappa_score)

# ===== 中文显示 =====
matplotlib.rcParams['font.family'] = 'SimHei'
matplotlib.rcParams['axes.unicode_minus'] = False

# ===== 参数 =====
DATA_DIR   = r"your_path"   # ← 修改为KSC数据路径
PCA_DIM    = 30
TRAIN_SIZE = 0.3
SEED       = 42

# ===== 1) 数据加载 =====
X_cube = sio.loadmat(os.path.join(DATA_DIR,"KSC.mat"))["KSC"].astype(np.float32)
Y_map  = sio.loadmat(os.path.join(DATA_DIR,"KSC_gt.mat"))["KSC_gt"].astype(int)
h, w, b = X_cube.shape
coords  = np.argwhere(Y_map!=0)
X_all   = X_cube[coords[:,0], coords[:,1]]
y_all   = Y_map[coords[:,0], coords[:,1]] - 1
num_classes = int(y_all.max()+1)
print(f"[INFO] 有标签像素: {len(y_all)}, 类别数: {num_classes}")

# ===== 2) 分层划分 & 无泄露预处理 =====
X_tr, X_te, y_tr, y_te = train_test_split(
    X_all, y_all, train_size=TRAIN_SIZE, stratify=y_all, random_state=SEED
)
scaler = StandardScaler().fit(X_tr)
pca    = PCA(n_components=PCA_DIM, random_state=SEED).fit(scaler.transform(X_tr))

def feat(X):return pca.transform(scaler.transform(X))
X_train, X_test = feat(X_tr), feat(X_te)

# ===== 3) SVM 模型 =====
clf = SVC(kernel="rbf", C=20, gamma=0.005, probability=False, random_state=SEED)
clf.fit(X_train, y_tr)
y_pred = clf.predict(X_test)

# ===== 4) 评估 =====
oa    = accuracy_score(y_te, y_pred)
kappa = cohen_kappa_score(y_te, y_pred)
cm    = confusion_matrix(y_te, y_pred, labels=np.arange(num_classes))
cmn   = cm / np.maximum(cm.sum(axis=1, keepdims=True), 1)

print(f"[SVM] OA={oa*100:.2f}%  Kappa={kappa:.4f}")
print(classification_report(y_te, y_pred, digits=4, zero_division=0))

# 混淆矩阵
fig, axes = plt.subplots(1, 2, figsize=(11, 4.2), constrained_layout=True)
im0 = axes[0].imshow(cm, cmap=plt.cm.YlGnBu, alpha=0.9)
axes[0].set_title("混淆矩阵(计数)"); axes[0].set_xlabel("预测"); axes[0].set_ylabel("真实")
for i in range(num_classes):
    for j in range(num_classes):
        axes[0].text(j, i, str(cm[i,j]), ha='center', va='center',
                     color='black'if cm[i,j]<cm.max()/2else'white', fontsize=9)
fig.colorbar(im0, ax=axes[0], fraction=0.046, pad=0.04)
im1 = axes[1].imshow(cmn, vmin=0, vmax=1, cmap=plt.cm.OrRd, alpha=0.9)
axes[1].set_title("混淆矩阵(归一化)"); axes[1].set_xlabel("预测"); axes[1].set_ylabel("真实")
for i in range(num_classes):
    for j in range(num_classes):
        axes[1].text(j, i, f"{cmn[i,j]*100:.1f}%", ha='center', va='center', color='black', fontsize=9)
fig.colorbar(im1, ax=axes[1], fraction=0.046, pad=0.04)
plt.show()

# ===== 5) 整图预测 =====
X_flat = X_cube.reshape(-1, b)
pred_map = clf.predict(feat(X_flat)).reshape(h, w) + 1

base_cmap  = plt.get_cmap('tab20')
colors     = [base_cmap(i % 20) for i in range(num_classes)]
cmap       = ListedColormap(colors)
boundaries = np.arange(0.5, num_classes+1.5, 1)
norm       = BoundaryNorm(boundaries, cmap.N)

plt.figure(figsize=(8.6,6.4))
im = plt.imshow(pred_map, cmap=cmap, norm=norm)
plt.title("SVM 整图预测结果")
plt.axis("off")
cbar = plt.colorbar(im, boundaries=boundaries,
                    ticks=np.arange(1,num_classes+1,max(1,num_classes//12)),
                    fraction=0.046, pad=0.04)
cbar.set_label("类别ID", rotation=90)
plt.show()

# ===== 6) 参数对比(C / gamma)=====
cands = [
    ("C=10,g=0.01",  SVC(kernel="rbf", C=10, gamma=0.01, random_state=SEED)),
    ("C=20,g=0.005", SVC(kernel="rbf", C=20, gamma=0.005, random_state=SEED)),
    ("C=50,g=0.001", SVC(kernel="rbf", C=50, gamma=0.001, random_state=SEED)),
]
names, accs = [], []
for n, model in cands:
    model.fit(X_train, y_tr)
    accs.append(accuracy_score(y_te, model.predict(X_test))*100)
    names.append(n)

plt.figure(figsize=(8,8))
x = np.arange(len(names))
plt.plot(x, accs, marker='o', linewidth=2.2)
plt.xticks(x, names, rotation=20, ha='right'); plt.ylabel("OA (%)")
plt.title("SVM 参数对比(C/gamma)")
plt.grid(alpha=0.3, linestyle='--'); plt.tight_layout(); plt.show()

🔍 结果解读

  • 混淆矩阵:对比各类识别情况;难分类的地物往往光谱相似。

     

    图片

  • 整图预测:SVM 结果通常边界清晰、噪声较少。

图片

  • 参数对比

    • C 越大 → 更强约束 → 边界更贴合训练 → 容易过拟合;

    • gamma 越大 → 影响范围小 → 更复杂边界;过小 → 欠拟合。

图片

✅ 总结

  • SVM 是遥感分类的黄金基线,特别适合样本不足或类间边界复杂的情况。

  • 超参选择很关键,建议:

    • 先 kernel='rbf'

    • 网格搜索 C, gamma

    • 样本多时可先 PCA。

  • 实战里,SVM 常被用来和随机森林、神经网络等方法做对比。

👉 至此,本系列 20 篇 Sklearn × 遥感实战教程 就全部结束啦! 从 预处理 → 分类器 → 集成 → 半监督 → 可视化 → SVM终章,我们完成了一个完整的 传统机器学习 & 遥感 入门路径。

接下来我会从最基础开始写一系列小工具和进阶内容教程,如深度学习等。

欢迎大家关注下方公众号获取更多内容!

您可能感兴趣的与本文相关的镜像

TensorFlow-v2.15

TensorFlow-v2.15

TensorFlow

TensorFlow 是由Google Brain 团队开发的开源机器学习框架,广泛应用于深度学习研究和生产环境。 它提供了一个灵活的平台,用于构建和训练各种机器学习模型

评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

遥感AI实战

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值