【问题标题】:How to train an SVM classifier on a satellite image using Python如何使用 Python 在卫星图像上训练 SVM 分类器
【发布时间】:2017-09-05 23:45:09
【问题描述】:

我正在使用scikit-learn 库对卫星图像执行监督分类(支持向量机分类器)。我的主要问题是如何训练我的 SVM 分类器。我在 youtube 上观看了很多视频,并阅读了一些关于如何在 scikit-learn 中训练 SVM 模型的教程。我看过的所有教程,都使用了著名的 Iris 数据集。为了在scikit-learn 中执行监督 SVM 分类,我们需要有标签。对于鸢尾花数据集,我们有Iris.target,这是我们试图预测的标签('setosa'、'versicolor'、'virginica')。通过阅读scikit-learn 文档,训练过程很简单。

就我而言,我必须训练在市区上空捕获的 SAR 卫星图像,并且需要对市区、道路、河流和植被进行分类(4 类)。该图像有两个波段,但我没有尝试预测的每个类别的标签数据,例如 Iris 数据。

所以,我的问题是,我是否必须手动创建向量数据(用于 4 个类)才能训练 SVM 模型?有没有比手动创建矢量数据更简单的方法来训练模型?在这种情况下我们该怎么办?

说实话,我有点困惑。我会很感激任何帮助

【问题讨论】:

  • 我不确定我是否理解您的问题。如果您没有标记数据,则无法使用监督学习技术……但也许我对卫星图像数据不太了解……
  • 您好 juanpa.arrivillaga,感谢您的回答。所以,我想我必须为我的卫星图像手动创建训练数据。训练过程让我有点坦白
  • 一种可能的方法是使用 openstreetmaps.org 生成测试数据来训练您的模型,因为您可能有图像的坐标。困难在于将 OSM 数据解析为您需要的类别,但格式有据可查,并且有库可以帮助您。
  • 感谢您的回答。

标签: python machine-learning scikit-learn svm k-means


【解决方案1】:

这是一个完整的示例,可以帮助您走上正轨。为简单起见,我们假设您的目标是将下面三波段图像上的像素分为三个不同的类别,即建筑物、植被和水。这些类别将分别以红色、绿色和蓝色显示。

我们首先读取图像并定义一些稍后将使用的变量。

import numpy as np
from skimage import io

img = io.imread('https://i.stack.imgur.com/TFOv7.png')

rows, cols, bands = img.shape
classes = {'building': 0, 'vegetation': 1, 'water': 2}
n_classes = len(classes)
palette = np.uint8([[255, 0, 0], [0, 255, 0], [0, 0, 255]])

无监督分类

如果您不想手动标记某些像素,那么您需要检测数据的底层结构,即您必须将图像像素拆分为n_classes 分区,例如通过k-means clustering

from sklearn.cluster import KMeans

X = img.reshape(rows*cols, bands)
kmeans = KMeans(n_clusters=n_classes, random_state=3).fit(X)
unsupervised = kmeans.labels_.reshape(rows, cols)

io.imshow(palette[unsupervised])

监督分类

或者,您可以为某些已知类别的像素分配标签(标记像素的集合通常称为ground truth)。在这个玩具示例中,ground truth 由三个 20×20 像素的硬编码方形区域组成,如下图所示:

supervised = n_classes*np.ones(shape=(rows, cols), dtype=np.int)

supervised[200:220, 150:170] = classes['building']
supervised[40:60, 40:60] = classes['vegetation']
supervised[100:120, 200:220] = classes['water']

ground truth(训练集)的像素用于拟合支持向量机。

y = supervised.ravel()
train = np.flatnonzero(supervised < n_classes)
test = np.flatnonzero(supervised == n_classes)

from sklearn.svm import SVC

clf = SVC(gamma='auto')
clf.fit(X[train], y[train])
y[test] = clf.predict(X[test])
supervised = y.reshape(rows, cols)

io.imshow(palette[supervised])

在训练阶段之后,分类器将类标签分配给剩余的像素(测试集)。分类结果如下:

最后的评论

结果似乎表明无监督分类比有监督分类更准确。然而,监督分类通常优于无监督分类。重要的是要注意,在分析的示例中,通过调整 SVM 分类器的参数可以显着提高准确性。通过扩大和细化基本事实可以实现进一步的改进,因为训练/测试比率非常小,并且红色和绿色块实际上包含不同类别的像素。最后,人们可以合理地预期,利用更复杂的特征,例如从强度级别计算的比率或指数(例如 NDVI)会提高性能。

【讨论】:

  • 这是对我的问题的一个非常完整且有趣的答案。你让我走上正轨。谢谢你的回答,我很感激。
  • 非常直接和完整的示例,适用于因网络上成千上万的参考资料而迷失的新人
【解决方案2】:

我的解决方案:-

手动处理:-

如果你的数据集很小,你可以手动创建一个矢量数据(也是可靠的,当它是你自己创建的时候)。如果不是,则很难应用 SVM 对图像进行分类。

自动处理:-

第 1 步:-

您可以使用“无监督图像聚类”技术将图像分为这 4 个类别,然后在聚类完成后将图像从 1 标记到 4。 (例如。K-Means 聚类算法)

第 2 步:-

目前,您拥有一个带标签图像的数据集。将它们拆分为训练测试数据。

第 3 步:-

现在应用 SVM 对您的测试图像进​​行分类并找出您的模型准确度。

【讨论】:

  • 我没有看到通过 k-means 聚类对像素进行分类然后在标记的像素上应用 SVM 分类器的意义。在某些情况下,将监督学习和非监督学习结合起来可能是有益的(有关详细信息,请参阅 this thread),但是 - 在我看来 - 您建议的 自动处理 方法没有意义。
  • 感谢您指出这个问题。但我只是以 k-means 为例。实际情况是,我们可以使用任何更好的无监督学习算法对不同的图像进行分组,然后可以根据图像聚类的组对它们进行标记。在此过程之后,每张图像都有自己的类别标签,因此我们可以将监督学习算法应用于分类过程。如果您还有任何疑问,请查看此回复旁边的帖子..
  • 如果您能够通过任何无监督学习算法正确标记像素,那么您无需通过监督学习重新分类像素。通过这样做,有监督分类的结果可能不如无监督分类的结果准确。顺便说一句,我是您推荐给我的帖子的作者 :-)
  • 哈哈..我从来没有看过作者的名字。你说的都是对的,毫无疑问。但是问题的方式是对图像进行“分类”。正如您所说,对于这种情况,无监督学习非常适合。我的目的不是为这个问题提供完美的解决方案,但如果可能的话,我可以。这就是为什么我得到这样的答案。如果您觉得答案很差,您显然可以按下投票按钮。
猜你喜欢
  • 1970-01-01
  • 2014-01-18
  • 2015-06-03
  • 1970-01-01
  • 2015-07-12
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2015-02-28
相关资源
最近更新 更多