谱聚类之python3实现

一、谱聚类原理及思想

这里我引用网上一个大佬的文章,原理啥的都写的很详细!

二、算法流程

1、根据输入的相似矩阵(样本间的距离矩阵)构建样本的相似矩阵
2、根据相似矩阵构建邻接矩阵(实际上这两个矩阵相同),构建度矩阵
3、计算拉普拉斯矩阵后再构建标准化的拉普拉斯矩阵 D − 1 / 2 L D − 1 / 2 D^{-1/2}LD^{-1/2} D1/2LD1/2
4、计算 D − 1 / 2 L D − 1 / 2 D^{-1/2}LD^{-1/2} D1/2LD1/2最小的 k 1 k_1 k1个特征值所对应的各自特征向量 f f f
5、将各自对应的特征向量组成的矩阵按行标准化,最终成 n × k 1 n \times k_1 n×k1维的特征矩阵 F F F
6、使用K-means聚类方法进行聚类,聚类维数为 k 2 k_2 k2
7、给到聚类划分

三、python实现部分

from sklearn import datasets
import numpy as np
from sklearn.cluster import KMeans
from matplotlib import pyplot as plt
from itertools import cycle, islice


# 产生内圈和外圈的两个圆环数据集
def makeTwoCircles(n_sample):
   x, label = datasets.make_circles(n_sample, factor=0.5, noise=0.05)
   return x, label


# 计算两个坐标之间的欧氏距离
def distance(x1, x2):
   res = np.sqrt(np.sum((x1 - x2) ** 2))
   return res


# 计算数据之间的距离矩阵,分别计算一个坐标与其他坐标间的距离
def distanceMatrix(X):
   M = np.array(X)
   Z = np.zeros((len(M), len(M)))
   for i in range(len(M)):
       for j in range(i + 1, len(M)):
           Z[i][j] = 1.0 * distance(X[i], X[j])
           Z[j][i] = Z[i][j]
   return Z


# 计算邻接矩阵,采用全连接法+高斯核函数
def adjacencyMatrix(Z, k, sigma=1.0):
   N = len(Z)
   A = np.zeros((N, N))
   for i in range(N):
       dist = zip(Z[i], range(N))  # 将Z矩阵的一行内的元素进行逐个标识下标(从小到大)
       dist_index = sorted(dist, key=lambda x: x[0])  # 根据一行的元素进行从小到大排序
       neibours_id = [dist_index[m][1] for m in range(k + 1)]  # 挑出排序前11的元素的下标索引
       for index in neibours_id:
           A[i][index] = np.exp(-Z[i][index] / (2 * sigma * sigma))
           A[index][i] = A[i][index]
   return A


# 计算拉普拉斯矩阵及其特征矩阵
def laplacianMatrix(A):
   # 计算度矩阵D
   D = np.sum(A, axis=1)
   # 计算拉普拉斯矩阵
   L = np.diag(D) - A
   # 计算标准化之后的拉普拉斯矩阵
   squareD = np.diag(1.0 / (D ** (0.5)))
   standardization_L = np.dot(np.dot(squareD, L), squareD)
   # 计算标准化拉普拉斯矩阵的特征值和特征向量
   x, V = np.linalg.eig(standardization_L)

   # 将特征值进行排序
   x = list(zip(x, range(len(x))))
   x = sorted(x, key=lambda x: x[0])

   # 按特征值排序后的索引将对应的特征向量重新组合
   H = np.vstack(V[:, i] for (v, i) in x[:500]).T
   return H


# 绘图函数
def plot(X, y_sp, y_km):
   colors = np.array(list(islice(cycle(['#377eb8', '#ff7f00', '#4daf4a',
                                        '#f781bf', '#a65628', '#984ea3',
                                        '#999999', '#e41a1c', '#dede00']),
                                 int(max(y_km) + 1))))
   plt.subplot(121)
   # 绘制散点图
   plt.scatter(X[:, 0], X[:, 1], s=10, color=colors[y_sp])
   plt.title("Spectral Clustering")
   plt.subplot(122)
   plt.scatter(X[:, 0], X[:, 1], s=10, color=colors[y_km])
   plt.title("Kmeans Clustering")
   plt.savefig(r"F:\DataBuilding\spectral_clustering.png")
   plt.show()



if __name__ == '__main__':
   data, label = makeTwoCircles(500)
   print(np.shape(np.array(data)))
   print(np.array(data)[2])
   Z = distanceMatrix(data)
   M = adjacencyMatrix(Z, 10)
   H = laplacianMatrix(M)

   # 谱聚类
   sp_Kmeans = KMeans(n_clusters=3).fit(H)
   # K-means聚类
   kmeans = KMeans(n_clusters=3).fit(data)
   print(sp_Kmeans.labels_, kmeans.labels_)  # 标签
   # 根据标签来填充散点的颜色,以达到标识分类效果
   plot(data, sp_Kmeans.labels_, kmeans.labels_)

四、 聚类的效果图

由此可见谱聚类的效果要比k-means聚类效果好一点。

在这里插入图片描述

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值