谱聚类Python代码详解

谱聚类算法步骤

整体来说,谱聚类算法要做的就是先求出相似性矩阵,然后对该矩阵归一化运算,之后求前个特征向量,最后运用K-means算法分类。 实际上,谱聚类要做的事情其实就是将高维度的数据,以特征向量的形式简洁表达,属于一种降维的过程。本来高维度用k-means不好分的点,在经过线性变换以及降维之后,十分容易求解。谱聚类的步骤如下:


1. 按照式计算相似性矩阵 
2. 使用KNN计算邻接矩阵A,同时度矩阵D可以通过对A的每一行进行求和得到D = np.sum(A, axis=1)
3. 拉普拉斯矩阵L=D-A

4.标准化L_1=D^{-\frac{1}{2}}LD^{-\frac{1}{2}}

5. 对标准化的L_1进行特征值分解,得到特征向量 H
6. 对H进行k-means聚类。

谱聚类Python代码

1. 相似度矩阵

def euclidDistance(x1, x2, sqrt_flag=False):
    res = np.sum((x1-x2)**2)
    if sqrt_flag:
        res = np.sqrt(res)
    return res

def calEuclidDistanceMatrix(X):
    X = np.array(X)
    S = np.zeros((len(X), len(X)))
    for i in range(len(X)):
        for j in range(i+1, len(X)):
            S[i][j] = 1.0 * euclidDistance(X[i], X[j])
            S[j][i] = S[i][j]
    return S

对于输入数据n\times 1,其相似度矩阵S为 n\times n ,S 的第 i 行(i\in n)表示第i 个元素与其他所有元素的相似度。

2. 邻接矩阵

构建邻接矩阵 A 的方法有三类:ϵ-邻近法,K邻近法(KNN)和全连接法。目前最常用就是KNN和全连接法。

def myKNN(S, k, sigma=1.0):
    N = len(S)
    A = np.zeros((N,N))

    for i in range(N):
        dist_with_index = zip(S[i], range(N))
        dist_with_index = sorted(dist_with_index, key=lambda x:x[0])
        neighbours_id = [dist_with_index[m][1] for m in range(k+1)] # xi's k nearest neighbours

        for j in neighbours_id: # xj is xi's neighbour
            A[i][j] = np.exp(-S[i][j]/2/sigma/sigma)
            A[j][i] = A[i][j] # mutually

    return A

3. 标准化的拉普拉斯矩阵

def calLaplacianMatrix(adjacentMatrix):

    # compute the Degree Matrix: D=sum(A)
    degreeMatrix = np.sum(adjacentMatrix, axis=1)

    # compute the Laplacian Matrix: L=D-A
    laplacianMatrix = np.diag(degreeMatrix) - adjacentMatrix

    # normailze
    # D^(-1/2) L D^(-1/2)
    sqrtDegreeMatrix = np.diag(1.0 / (degreeMatrix ** (0.5)))
    return np.dot(np.dot(sqrtDegreeMatrix, laplacianMatrix), sqrtDegreeMatrix)

拉普拉斯矩阵是半正定对称矩阵有如下性质:

  • 对称矩阵一定n个线性无关的特征向量
  • 半正定矩阵的特征值一定非负
  • 对阵矩阵的特征向量相互正交,即所有特征向量构成的矩阵为正交矩阵

4. 特征值分解

lam, H = np.linalg.eig(Laplacian) # H'shape is n*n

5. K-means

from sklearn.cluster import KMeans
def spKmeans(H):
    sp_kmeans = KMeans(n_clusters=2).fit(H)
    return sp_kmeans.labels_

参考:https://blog.csdn.net/songbinxu/article/details/80838865 

https://www.zhihu.com/question/54504471

你可能感兴趣的:(谱聚类,Spectral,Clustering)