谱聚类算法步骤
整体来说,谱聚类算法要做的就是先求出相似性矩阵,然后对该矩阵归一化运算,之后求前个特征向量,最后运用K-means算法分类。 实际上,谱聚类要做的事情其实就是将高维度的数据,以特征向量的形式简洁表达,属于一种降维的过程。本来高维度用k-means不好分的点,在经过线性变换以及降维之后,十分容易求解。谱聚类的步骤如下:
1. 按照式计算相似性矩阵
2. 使用KNN计算邻接矩阵A,同时度矩阵D可以通过对A的每一行进行求和得到D = np.sum(A, axis=1)
3. 拉普拉斯矩阵
4.标准化
5. 对标准化的进行特征值分解,得到特征向量
6. 对进行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
对于输入数据,其相似度矩阵S为 ,S 的第 行()表示第 个元素与其他所有元素的相似度。
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