平移聚类算法实战教程

418 阅读7分钟

平均移动聚类算法是一种基于中心点的算法,有助于无监督学习的各种使用情况。它是用于图像处理计算机视觉的最佳算法之一它的工作原理是将数据点向中心点移动,使其成为该区域内其他点的平均值。它也被称为寻模算法。该算法的优点是,它为数据分配集群,而不需要根据定义的带宽自动定义集群的数量。

核心密度估计

和其他聚类算法一样,Mean shift是基于内核密度估计(KDE)的概念,这是一种估计随机变量的概率密度函数的方法。KDE是一个通过数据平滑来推断人口的问题。它通过为每个数据点提供权重来工作。权重函数被称为核。有许多种核,一种核是高斯核。将所有这些核加在一起,就形成了一个密度函数(概率面)。由此产生的密度函数的变化取决于所使用的带宽参数。

在下面的图片中,我们可以看到一些数据点在曲面图中的分布。

图片来源

而在下面的图片中,我们可以看到我们的数据点在曲面图中分布的KDE面(第一张图片)。丘陵可以被认为是内核。

图片来源

在KDE曲面的等高线图中,我们可以看到我们的数据点的精确平滑。

图片来源

从这些图片中,我们可以了解KDE是如何对数据集进行平滑处理,从而从数据点中进行推断的。随着图中圆圈大小的减少,数据点的密度也在增加,这意味着内核中的大多数点都试图在小圆圈上,在这里,均值偏移进入了画面,它试图增加或减少密度函数。

均值偏移

平均值移动是基于KDE的想法,但它的不同之处在于使用带宽参数。我们可以使点爬上坡,到达KDE表面上最近的峰值。因此,迭代地转移每一个点,使其爬上坡,达到峰值。

用来制作KDE表面的带宽参数在不同的尺寸上是不同的。例如,我们有一个高大瘦小的内核,这意味着一个小的内核带宽,而在内核的尺寸是短而胖的情况下,这意味着一个大的内核带宽。小的内核带宽使KDE表面更正式地保持每个数据点的峰值,即每个点都有它的集群;另一方面,大的内核带宽导致更少的内核或更少的集群。

图片来源

这里我们可以看到带宽值等于2的内核的形成。

图片来源

在图片中,我们可以看到带宽值低时的情况。

让我们考虑一个核函数𝐊(xi - x)给附近的点加权以定义平均值。因此,在窗口计算中,密度的加权平均值是由决定的。

图片来源

其中N(x)是x的邻域。

m(x)-x的值被称为均值移动。

正如前面所讨论的,从数学公式中,我们可以理解,均值偏移试图转移点,当迭代执行时,它将移动到KDE峰。

基本上,在整个算法中,在对数据点进行复制后,这些复制的点会对原始复制的点进行移位,以达到其内核面的峰值。接下来在文章中,我们将看到如何用Python实现这个算法,用随机产生的数据点来找出根据大小和带宽参数的集群。

在Python中的实现

导入库。

import numpy as np
import pandas as pd
from sklearn.cluster import MeanShift
from sklearn.datasets.samples_generator import make_blobs
import matplotlib.pyplot as plt
from mpl_toolkits.mplot3d import Axes3D

ordinates = [[2, 2, 3], [6, 7, 8], [5, 10, 13]]

X, _ = make_blobs(n_samples = 120, centers = cordinates,

cluster_std = 0.60)

设置坐标并在坐标周围生成随机数据。

将数据点可视化。

data_fig = plt.figure(figsize=(12, 10))  
ax = data_fig.add_subplot(111, projection ='3d')  
ax.scatter(X[:, 0], X[:, 1], X[:, 2], marker ='o',color ='green')  
plt.show()

输出。

这里我们可以看到数据在空间中的分布。在空间上,我们可以很容易地说,根据坐标作为数据的推断,可以有3个集群。现在我们将进行均值转移来预测聚类并定义聚类的中心点。Sklearn根据数据提供了带宽的估计函数,所以我们不需要担心带宽参数的问题。导入估计的带宽函数。

导入库。


from sklearn.cluster import  estimate_bandwidth
bandwidth = estimate_bandwidth(X, quantile=0.2, n_samples=500)

现在我们可以定义均值偏移聚类模型,并将其适合于我们的数据。

msc = MeanShift(bandwidth=bandwidth, bin_seeding=True)
msc.fit(X)
cluster_centers = msc.cluster_centers_
labels = msc.labels_
cluster_label = np.unique(labels)
n_clusters = len(labels_unique)
n_clusters

输出。

这里我们可以看到它已经被预测了,因为我们估计应该有3个聚类。

可视化聚类。

msc_fig = plt.figure(figsize=(12, 10))

ax = msc_fig.add_subplot(111, projection ='3d')

ax.scatter(X[:, 0], X[:, 1], X[:, 2], marker ='o',color ='yellow')

ax.scatter(cluster_centers[:, 0], cluster_centers[:, 1],
           cluster_centers[:, 2], marker ='o', color ='green',
          s = 300, linewidth = 5, zorder = 10)
plt.title('Estimated number of clusters: %d' % n_clusters)  
plt.show()

输出。

在这里,我们可以看到绿色的聚类中心点,很容易将数据分成3个聚类。正如我们已经讨论过的,它对图像处理和计算机视觉非常有用。接下来,我将使用均值移动聚类算法来分离图像的颜色。更正式地说,我们可以称它为使用均值移动的图像分割,因为我们知道任何图像中的像素值都是基于图像中存在的颜色。在这里,我使用热像仪作为图像,因为这个图像中的颜色分布很好,而且颜色的数量不够,所以在这个过程中,我们不会感到困惑。

导入库。

import numpy as np
from sklearn.cluster import MeanShift, estimate_bandwidth
from sklearn.datasets.samples_generator import make_blobs
from itertools import cycle
from PIL import Image
import matplotlib.pyplot as plt
import matplotlib.pylab as pylab
%matplotlib inline

使用PIL和Matplotlib加载图像并使其可视化。

输入。

img = Image.open('/content/drive/MyDrive/Yugesh/Mean Shift Clustering Algo/Thermography_results_sm.jpg')

img = np.array(image)

# saving the image shape
shape = img.shape

# reshaping image 
reshape_img = np.reshape(image, [-1, 3])

#plotting the image
plt.imshow(image)
plt.title(img.shape)

输出。

在这里,我们可以看到图像和它的大小作为图像的标题。我们对图像进行了重塑,使其扁平化,这样我们就可以得到模型所需的数组的大小。由于我们在这里讨论了sklearn的带宽函数,我正在使用该函数定义带宽。

输入。

bandwidth = estimate_bandwidth(reshape_img, quantile=0.1, n_samples=100)
bandwidth

输出。

拟合reshape_img上的meanshitt。

msc = MeanShift(bandwidth=bandwidth, bin_seeding=True)
msc.fit(reshape_img)

输出。

检查模型的洞察力,这样我们就可以知道后面的情况了。

print("shape of labels : %d" % msc.labels_.shape)
print( msc.cluster_centers_.shape)
print("number of estimated clusters : %d" % len(np.unique(msc.labels_)))

输出。

在这里我们可以看到,它产生了8个聚类,这意味着图像已经聚类成8个颜色段--改变了标签的形状,相当于原始图像的形状。

labels = msc.labels_
result_image = np.reshape(labels, shape[:2])

让我们来画出图像的原始和分段。


fig = plt.figure(2, figsize=(14, 12))
ax = fig.add_subplot(121)
ax = plt.imshow(img) 
ax = fig.add_subplot(122)
ax = plt.imshow(result_image)  
plt.show()

输出。

这里我们可以看到原始图像和结果图像。利用图像的像素大小,我们使用平均移动算法生成了集群。它为我们提供了图像像素值的聚类(注意--像素值在0到255之间)。这是解决 图像分割和其他图像处理问题的最简单的技术之一。我们在前面的主题中已经看到它是如何工作的,并为数据点提供中心点,同时我们也看到它是如何使用KDE表面的平均移动的。这种算法有很多优点,比如没有离群值的影响,对复杂结构的数据集的效率,以及不需要在几个集群之间进行迭代。

参考文献

The postHands-On Tutorial on Mean Shift Clustering Algorithmappeared first onAnalytics India Magazine.