谱聚类(Spectal

Clustering)算法是聚类算法的一种,比起传统的K-Means聚类算法,谱聚类算法的效果更优秀,其计算量也小很多,除了谱聚类和K-Means聚类算法,另外还有密度聚类和层次聚类算法,本节主要讨论谱聚类算法,预备知识:最好有K-Means聚类算法的基础。

谱聚类是一种不断发展的聚类算法,在很多情况下都优于传统的聚类算法,它将每个数据点视为一个图节点,从而将聚类问题转化为图分区的问题,一个典型的谱聚类的实现包括以下三个基本步骤:

建立相似度图:该步骤以邻接矩阵的形式建立相似度图,邻接矩阵用A表示:

邻域图:一个参数事先是固定的,然后每个点都与半径内的所有点相连。如果任意两点之间的距离在比例上是相似的,则通常不存储边缘的权值(即两点之间的距离),因为它们不提供任何附加信息。因此,在本例中,构建的图是一个无向的、未加权的图。

K临近算法:参数k事先是固定的,接下来的两个顶点u和v,优势是直接从u v只有再邻居u。请注意,这导致的形成加权有向图,因为它并非总是如此,对于每个u v再邻近之一,它将是相同的理由再邻近之间的v在u。要使此图无向,可以采用以下方法之一:-

如果v在u的k近邻中,或者u在v的k近邻中,则将一条边从u指向v,并从v指向u。

如果v在u的k近邻中,且u在v的k近邻中,则将一条边从u指向v,从v指向u。

全连通图:要构建这个图,每个点都与一个无向边连接,边权值由两个点到另一个点的距离决定。由于该方法用于建立局部邻域关系的模型,因此通常使用高斯相似度度量来计算距离。

将数据投影到较低的纬度空间:这一步骤是为了考虑同一星系团的成员在给定维度空间中可能很远的可能性。这样就减少了维数空间,使得这些点在维数空间中更接近,从而可以用传统的聚类算法将这些点聚在一起。它是通过计算图拉普拉斯矩阵来实现的。要计算它,首先需要定义节点的度。第i个节点的度由:


注意,w{ij}是上面邻接矩阵中定义的节点i和j之间的边。度矩阵定义如下:


因此,图拉普拉斯矩阵定义为:


然后,为了提高数学效率,对这个矩阵进行标准化。为了减小维数,首先计算特征值和相应的特征向量。如果簇的个数是k,那么第一个特征值和它们的特征向量就被取下来并堆成一个矩阵,这样特征向量就是列。

聚类数据:该过程主要是利用传统的聚类技术(通常是K-Means聚类)对约简后的数据进行聚类。首先,给每个节点分配一个图拉普拉斯矩阵的归一化行。然后使用任何传统技术对这些数据进行聚类。为了转换聚类结果,保留节点标识符。

特点:

无假设:与其他传统技术不同,这种聚类技术不假定数据遵循某些属性。因此,这使得该技术可以回答更一般的一类聚类问题。

易于实现和速度更快:该算法比其他聚类算法更容易实现,而且由于它主要由数学计算组成,速度也非常快。

不可伸缩:由于它涉及到矩阵的构建和特征值和特征向量的计算,因此对于密集的数据集来说是非常耗时的。

下面的步骤演示了如何使用Sklearn实现光谱聚类。以下步骤的数据是可以从Kaggle下载的信用卡数据。

1、导入所需的库

import pandas as pd

import matplotlib.pyplot as plt

from sklearn.cluster import SpectralClustering

from sklearn.preprocessing import StandardScaler, normalize

from sklearn.decomposition import PCA

from sklearn.metrics import silhouette_score

2、加载和清理数据

# 将工作空间的路径改为数据的路径
cd "C:\Users\Desktop\Credit_Card"
# 加载数据
X = pd.read_csv('CC_GENERAL.csv')
# 从数据中删除CUST_ID一列
X = X.drop('CUST_ID', axis = 1)
# 处理丢失的值(如果有的话)
X.fillna(method ='ffill', inplace = True)
X.head()


3、预处理数据,使数据可视化

# 预处理数据,使数据可视化
# 数据比例伸缩
scaler = StandardScaler()
X_scaled = scaler.fit_transform(X)
# 规范化数据
X_normalized = normalize(X_scaled)
# 将numpy数组转换为pandas DataFrame
X_normalized = pd.DataFrame(X_normalized)
# 减少数据的纬度
pca = PCA(n_components = 2)
X_principal = pca.fit_transform(X_normalized)
X_principal = pd.DataFrame(X_principal)
X_principal.columns = ['P1', 'P2']
X_principal.head()

4、建立聚类模型并可视化聚类

在下面的步骤中,两种不同的谱聚类模型具有不同的参数affinity的值。你可以在这里阅读有关光谱聚类的文档。

A、affinity = ‘rbf’
# 构建聚类模型
spectral_model_rbf = SpectralClustering(n_clusters = 2, affinity ='rbf')
# 训练模型并存储预测的聚类标签
labels_rbf = spectral_model_rbf.fit_predict(X_principal)
filter_none
brightness_4
# 建立标签到颜色的映射
colours = {}
colours[0] = 'b'
colours[1] = 'y'
# 为每个数据点构建颜色向量
cvec = [colours[label] for label in labels_rbf]
# 绘制聚类散点图
b = plt.scatter(X_principal['P1'], X_principal['P2'], color ='b');
y = plt.scatter(X_principal['P1'], X_principal['P2'], color ='y');
plt.figure(figsize =(9, 9))
plt.scatter(X_principal['P1'], X_principal['P2'], c = cvec)
plt.legend((b, y), ('Label 0', 'Label 1'))
plt.show()


B、affinity = ‘nearest_neighbors’

# 构建聚类模型
spectral_model_nn = SpectralClustering(n_clusters = 2, affinity ='nearest_neighbors')
# 训练模型并存储预测的聚类标签
labels_nn = spectral_model_nn.fit_predict(X_principal)

5、评估性能

# affinity不同值的列表
affinity = ['rbf', 'nearest-neighbours']
# 剪影分数一览表
s_scores = []
# 工作性能评估
s_scores.append(silhouette_score(X, labels_rbf))
s_scores.append(silhouette_score(X, labels_nn))
print(s_scores)


6、比较性能

# 绘制条形图来比较模型
plt.bar(affinity, s_scores)
plt.xlabel('Affinity')
plt.ylabel('Silhouette Score')
plt.title('Comparison of different Clustering Models')
plt.show()