一、 谱聚类
谱聚类是一种基于图论和矩阵特征分解(谱分析)的聚类方法。它的核心思想是将数据点视为图中的节点,通过计算数据之间的相似度矩阵,分析图的拉普拉斯矩阵(Laplacian Matrix)的谱(特征值和特征向量),从而在低维嵌入空间中进行聚类。谱聚类的特点:适用于复杂形状的数据(如环形、流形结构),而传统方法(如K-means)仅适用于凸分布数据。基于全局结构,通过图拉普拉斯矩阵捕捉数据的整体连通性,而非局部距离。依赖相似度矩阵,计算开销较大,适用于中小规模数据集。优点与局限性:能发现非凸分布的簇。对噪声和离群点有一定鲁棒性。局限性:计算复杂度高((O(n^3)),适用于中小数据。相似度矩阵和参数的选择影响结果。应用场景:图像分割、社交网络分析、文本聚类等复杂结构数据。
二、算法解释
主要想法是把所有的数据看作空间中的点,这些点之间的边连接起来。距离较远的两个点之间的边权重值较低,而距离较近的两个点之间的边权重值高,通过对所有数据点组成的图进行切图,让切图后不同的子图边权重。
算法的具体技术思路:
1、把数据组织成无向权重图并计算链接矩阵W、度矩阵D、拉普拉斯矩阵L。用数据样本点表示节点V(vertex),用样本之间有无连接表示有无边连接,用样本间的权重(用不同距离计算公式表示)的等于0与否表示有无连接,不为0的权重就是边的权重。
图 2-1 数据的图嵌入
import numpy as np
# np.set_printoptions(threshold=np.inf)
from sklearn.cluster import KMeans
import math
import matplotlib.pyplot as plt
def load_data(filename):
........
def getW(data, k):
"""
获的邻接矩阵 W
:param data: 样本集合
:param k : KNN参数
:return: W
"""
n = len(data)
dist_matrix = get_dist_matrix(data)
W = np.zeros((n, n))
for idx, item in enumerate(dist_matrix):
idx_array = np.argsort(item) # 每一行距离列表进行排序,得到对应的索引列表
W[idx][idx_array[1:k+1]] = 1 # 权值直接取1 而不是其他的核函数;
transpW =np.transpose(W)
return (W+transpW)/2 # 这里的邻接矩阵采用的是K邻近法,并且是只要满足一个邻接即为相邻的K邻近法
def plotRes(data, clusterResult, clusterNum):
........
def cluster(data, cluster_num, k):
# ratio 方法
data = np.array(data)
W = getW(data, k)
D = getD(W)
L = getL(D,W)
# RatioCut方法
# eigvec = getEigen(L, cluster_num)
# 这里采用 n_cut 方法
# n n_cut
# print(np.diag(D))
temp_D = np.diag(np.diag(D) ** (-1/2))
New_L= np.dot(np.dot(temp_D,L),temp_D)
eigvec = getEigen(New_L, cluster_num)
#对 eigvec 标准化
eigvec_normalized = eigvec / np.linalg.norm(eigvec, axis=0, keepdims=True)
clf = KMeans(n_clusters=cluster_num)
s = clf.fit(eigvec_normalized) # 聚类
label = s.labels_
return label
if __name__ == '__main__':
cluster_num = 3
knn_k = 6
filename = 'output.txt'
data = load_data(filename=filename)
data = data[0:-1] # 取全部数据
label = cluster(data, cluster_num, knn_k)
plotRes(data, label, cluster_num)
def getD(W):
.......
def getEigen(L, cluster_num):
"""
获得拉普拉斯矩阵的特征矩阵
:param L:
:param cluter_num: 聚类数目
:return:
"""
eigval, eigvec = np.linalg.eig(L)
ix = np.argsort(eigval)[0:cluster_num]
return eigvec[:, ix]
聚类前数据:
聚类后数据:
四、参考文献
1、数据挖掘——谱聚类(spectral clustering)基本原理及python实现_谱聚类算法原理与实现-CSDN博客
2、理解谱聚类 https://zhuanlan.zhihu.com/p/57369475