引子
传说有个叫机器学习的星球,星球上除了海水,还分布着三个大陆,他们的名字分别是监督学习、无监督学习以及半监督学习。每个大陆都有很多王国,像回归啊,分类啊,这些王国都位于监督学习大陆。而在无监督学习的大陆上,聚类王国占据了相当大的领地,而在聚类王国里,又有很多分封的诸侯,最老牌的诸侯如K-means,可谓家喻户晓,在国际上也有举足轻重的地位,今天我们不采访他,而是关注他的邻居,谱聚类,介绍一下谱聚类的原理,以及他对社会所作的贡献。
聚类王国里每一个国家都有一个共同的经济目标,对其国内的经济实体按内在相似性划分为多个类别,使类别内的实体相似度较大而类别间的实体相似度较小。当然,每一个国家或诸侯会采用不同的方法来实现这个目标。
聚类的衡量指标
1、同一性(Homogeneity):一个簇中只包含一个类别的样本,则满足均一性
2、完整性(Completeness):同类别样本被归类到相同簇中,则满足完整性
3、V-Measure:均一性和完整性的加权平均
这些指标可谓是聚类王国的GDP指标了,他反应了这个国家的综合经济实力,哈哈
谱聚类原理
在谱聚类的诸侯国中,有一条很重要的宪法,这就是谱聚类的原理。它的大致内容是这样的:
每个实体,即每条数据,用空间中的一个点来代表,将这些点用边连接,距离较远的两个点之间的边权重较低,而距离较近的两个点之间的边权重较高,通过对所有数据点组成的图进行切图,让切图后的不同的子图间边权重之和尽可能小(即距离远),而子图内的边权重之和尽可能高(即距离近),这个过程也可以叫做求图的最小割。
具体做法如下:
这里加入一些小编总结,对相似度图进行切割的过程,即求最小割的过程,和求特征向量的过程是等价的,亦即,使用特征向量来代表原数据就能使相似度图的子图间边权重之和最小,而子图内的边权重之和最大。
详细讲述谱聚类原理的文章很多,这里只是做了简单的总结以及个人理解,不过瘾的读者可以深入研究。下面上案例
案例:对特殊形状区域数据的聚类
代码如下:
import numpy as np import matplotlib.pyplot as plt import matplotlib.colors from sklearn.cluster import SpectralClustering from sklearn.metrics import euclidean_distances from sklearn import datasets if __name__ == "__main__": matplotlib.rcParams['font.sans-serif'] = ['SimHei'] matplotlib.rcParams['axes.unicode_minus'] = False # 在平面中制作一个包含较小圆圈的大圆圈 x1, _ = datasets.make_circles(n_samples=500, noise=0.06, factor=0.2) # 将圆圈图像整体上移,便于与下面的半圆数据分开 x1[:, 1] = x1[:, 1] + 3.5 # 生成两个交错的半圆 x2, _ = datasets.make_moons(n_samples=200, noise=0.06) # 将两种数据集叠加 data = np.vstack((x1, x2)) # 簇的个数 n_clusters = 4 # 计算每两个点之间的欧氏距离 m = euclidean_distances(data, squared=True) # 绘图准备 plt.figure(figsize=(12, 8), facecolor="w") plt.suptitle("谱聚类应用", fontsize=15) # 采用全连接法构造相似度图,两点的相似度采用高斯核函数,并且对比采用不同4种标准差时的聚类结果 for i, s in enumerate(np.logspace(-2, 0, 4)): print(s) # 相似度图 affinity = np.exp(-m ** 2 / (s ** 2)) + 1e-6 # 谱聚类模型 model = SpectralClustering(n_clusters=n_clusters, affinity="precomputed", assign_labels="kmeans", random_state=1) # 对相似度图进行预测 y_hat = model.fit_predict(affinity) # 绘制聚类结果 plt.subplot(2, 2, i+1) plt.scatter(data[:, 0], data[:, 1], s=40, c=y_hat, cmap=plt.cm.Spectral, edgecolors="k") plt.grid(visible=True, ls=":", color="#606060") plt.title(r"高斯核函数标准差$\sigma$ = %.2f" % s, fontsize=11) plt.tight_layout() # plt.show() plt.savefig('sc.png', dpi=800)
运行结果如下:
故事先讲到这里,期待后面的精彩故事吧!
作者这水平有限,有不足之处欢迎留言指正