代码参考:谱聚类 - 简书 (jianshu.com)https://www.jianshu.com/p/d35aea90ec5d详细算法推导参考:
(6条消息) 谱聚类(spectral clustering)及其实现详解_杨铖的博客-CSDN博客_谱聚类实现https://blog.csdn.net/yc_1993/article/details/52997074
算法思路理解下面是我的一些理解(看了很多博文,还是理解不了推导过程,所以用一个小例子按公式计算,或许对理解算法思想有帮助,但不严谨)
算法的大致思路:对n个样本进行k近邻计算,构造邻接矩阵和度矩阵;计算拉普拉斯矩阵;计算归一化的拉布拉斯矩阵的特征;取(除0外)的k个较小特征值的特征向量作为n个样本的k维特征,进行KMeans聚类(即对原始的n个n维向量的计算转化为n个k维向量的计算)
简单的代码示例:声明:
1、代码中对邻接矩阵的构造是:x和y互为近邻则为1,只有一方为近邻则为0.5
2、在求特征时,会出现复数无法计算的报错,所以对特征值和特征向量进行取实部的计算(例子中复数的虚部为0·j;你也可以用abs()求均值)
import numpy as np from sklearn import datasets from matplotlib import pyplot as plt
# 原始数据 noisy_circles, _ = datasets.make_circles(n_samples=300, noise=0.1, factor=.3, random_state=10) plt.scatter(noisy_circles[:,0], noisy_circles[:,1], color='b')
print(noisy_circles.shape) # 输出:(300, 2),即300个形如(x,y)的点
# K均值效果 from sklearn.cluster import KMeans plt.scatter(noisy_circles[:,0], noisy_circles[:,1], c=KMeans(n_clusters=2).fit_predict(noisy_circles))
# 生成300个点的邻接矩阵
# K-近邻方法计算无向图中边对应的相似度权重
def knn_similarity_matrix(data, k):
zero_matrix = np.zeros((len(data), len(data))) # 创建0矩阵用来存储距离较小的点的连边关系
w = np.zeros((len(data), len(data)))
for i in range(len(data)):
for j in range(i + 1, len(data)):
zero_matrix[i][j] = zero_matrix[j][i] = np.linalg.norm(data[i] - data[j]) # 计算欧式距离
for i, vector in enumerate(zero_matrix):
vector_i = np.argsort(vector) # 排序后输出由小到大的排序序号
w[i][vector_i[1 : k + 1]] = 1 # 对k个比较近的点连边
w = (np.transpose(w) + w)/2
return w
# 用谱聚类方法降维,并用k均值聚类,输出1*300的分类结果
from sklearn.cluster import KMeans
def spectral_clustering(data, k, n):
# 计算近邻矩阵、度矩阵的0.5次方、对称拉普拉斯矩阵
A_matrix = knn_similarity_matrix(data, k)
D_matrix = np.diag(np.power(np.sum(A_matrix, axis=1), -0.5))
L_matrix = np.eye(len(data)) - np.dot(np.dot(D_matrix, A_matrix), D_matrix)
# 计算特征值和特征向量
eigvals, eigvecs = np.linalg.eig(L_matrix)
# np.linalg.eig的计算结果是复数,会报错,且不能进行real提取实部
# 所以构造了x_val和x_vec保存eigvals, eigvecs的实部
x_val = []
x_vec = np.zeros((len(eigvecs[:,0]),len(eigvecs[0])))
for l in range(len(eigvecs[:,0])):
for m in range(len(eigvecs[0])):
x_vec[l][m] = eigvecs[l][m].real
for k in range(len(eigvals)):
x_val.append(eigvals[k].real)
# 选择前n个最小的特征向量
indices = np.argsort(x_val)[: n]
k_eigenvectors = x_vec[:, indices[: n]]
# 使用 K-Means 完成聚类
clusters = KMeans(n_clusters=n).fit_predict(k_eigenvectors)
return clusters
sc_clusters = spectral_clustering(noisy_circles, k=5, n=2) plt.scatter(noisy_circles[:,0], noisy_circles[:,1], c=sc_clusters)用sklearn的SpectralClustering模块进行谱聚类
参数详解参考:(7条消息) 数据挖掘——谱聚类(spectral clustering)基本原理及python实现_潘多拉星系的博客-CSDN博客https://blog.csdn.net/liujh845633242/article/details/103699787
1、全连接法
from sklearn.cluster import SpectralClustering y_pred = SpectralClustering(gamma=0.1,n_clusters=2).fit_predict(noisy_circles) plt.scatter(noisy_circles[:,0], noisy_circles[:,1], c=y_pred)
2、k近邻法
y_pred2 = SpectralClustering(affinity='nearest_neighbors',n_neighbors=5,n_clusters=2).fit_predict(noisy_circles) plt.scatter(noisy_circles[:,0], noisy_circles[:,1], c=y_pred2)



