譜聚類和Kmeans聚類演算法實現(python的sklearn)
Kmeans演算法大家都基本耳熟能詳了,而譜聚類演算法的過程如下
- 構建樣本相似度矩陣S
- 根據S構建度矩陣H
- 計算拉普拉斯矩陣L=H-S
- 構建標準化拉普拉斯矩陣 H(-1/2)LH(-1/2)
- 計算 L 的最小的K個特徵值對應的特徵向量(K為cluster數量)
- 將向量按照行進行標準化(每個元素除以本行所有元素的平方和在開根號)得到N*K的矩陣F,N為樣本點數
- F中每一行作為一個樣本,共N個樣本,對其進行聚類
- 得到cluster{C1,C2,…Ck}
起始本質就是得到特徵矩陣之後在對特徵矩陣執行 聚類
程式碼如下(jupyter執行)
import numpy as np
import matplotlib.pyplot as plt
import random
import heapq
from sklearn.cluster import KMeans
import sklearn
import pyamg
#引數初始化
N=20 #使用者數
distance=2000 #距離
sigma_d=100
K=4 #無人機數量
users=np.random.randint(0,distance+1,(N,2))#0-2000隨機20個點
scatter_x=[]
scatter_y=[]
for i in range(N):
scatter_x.append(users[i][0])
scatter_y.append(users[i][1])
#矩陣S
matric_S=np.zeros((N,N))
for i in range(N):
for j in range(N):
matric_S[i][j]=np.exp(-((scatter_x[i]-scatter_x[j])**2+(scatter_x[i]-scatter_x[j])**2)/(2*sigma_d**2))
#矩陣H(度矩陣)
matric_H=np.zeros((N,N))
for i in range(N):
for j in range(N):
matric_H[i][i]=matric_H[i][i]+matric_S[i][j]
#矩陣H(度矩陣負二分之一次冪)
matric_H_ = np.sqrt(np.linalg.inv(matric_H))
#將陣列轉化為矩陣
matric_S=np.mat(matric_S)
matric_H=np.mat(matric_H)
matric_H_=np.mat(matric_H_)
#拉普拉斯矩陣
matric_L=np.dot(np.dot(matric_H_,(matric_H-matric_S)),matric_H_)
求解特徵值 w 和特徵向量 v
w, v = np.linalg.eigh(matric_L)
print(w)
w=list(w)
min_4 = map(w.index, heapq.nsmallest(K, w))
min_4=list(min_4)
min_4.sort()
print(min_4)
#特徵值矩陣U
matric_U=np.zeros((N,K))
for i in range(N):
for j in range(K):
matric_U[i,j]=v[i,min_4[j]]
#特徵值歸一化矩陣T
matric_T=np.zeros((N,K))
for i in range(N):
for j in range(K):
matric_T[i,j]=matric_U[i,j]/np.sqrt((matric_U[i,0]**2+matric_U[i,1]**2+matric_U[i,2]**2+matric_U[i,3]**2))
#對特徵值進行Kmeans聚類
kmeans = KMeans(n_clusters=4, init='k-means++', random_state=1,n_init=100).fit(matric_T)
colors = []
for i in range(kmeans.labels_.shape[0]):
if kmeans.labels_[i] == 1:
colors.append('red')
elif kmeans.labels_[i] == 2:
colors.append('blue')
elif kmeans.labels_[i] == 3:
colors.append('green')
else:
colors.append('purple')
#對原始資料進行Kmeans聚類
kmeans_=KMeans(n_clusters=4, init='k-means++', random_state=1,n_init=100).fit(users)
colors_ = []
for i in range(kmeans_.labels_.shape[0]):
if kmeans_.labels_[i] == 1:
colors_.append('red')
elif kmeans_.labels_[i] == 2:
colors_.append('blue')
elif kmeans_.labels_[i] == 3:
colors_.append('green')
else:
colors_.append('purple')
#視覺化
plt.figure(dpi=720,figsize=(24,8))
plt.subplot(131)
plt.title('random users')
plt.grid()
plt.scatter(scatter_x,scatter_y)
# plt.scatter(scatter_x,scatter_y,color='',edgecolors='blue')
plt.subplot(132)
plt.title('kmeans ')
plt.grid()
# plt.scatter(scatter_x, scatter_y, color='',edgecolors=colors_, marker='o')
plt.scatter(scatter_x, scatter_y, c=colors_, marker='o')
plt.subplot(133)
plt.title('spectral cluster ')
plt.grid()
plt.scatter(scatter_x, scatter_y, c=colors, marker='o')
# plt.scatter(scatter_x, scatter_y, color='',edgecolors=colors, marker='o')
plt.show()
但是效果不是那麼好,哪位朋友能幫忙找下原因麼,sklearn有整合的SpectralClustering譜聚類也可以自行使用,調製相關引數即可得到,我的效果也不太好