1. 程式人生 > 其它 >譜聚類和Kmeans聚類演算法實現(python的sklearn)

譜聚類和Kmeans聚類演算法實現(python的sklearn)

Kmeans演算法大家都基本耳熟能詳了,而譜聚類演算法的過程如下

 

 

  1. 構建樣本相似度矩陣S
  2. 根據S構建度矩陣H
  3. 計算拉普拉斯矩陣L=H-S 
  4. 構建標準化拉普拉斯矩陣 H(-1/2)LH(-1/2)
  5. 計算 L  的最小的K個特徵值對應的特徵向量(K為cluster數量)
  6. 將向量按照行進行標準化(每個元素除以本行所有元素的平方和在開根號)得到N*K的矩陣F,N為樣本點數
  7. F中每一行作為一個樣本,共N個樣本,對其進行聚類
  8. 得到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譜聚類也可以自行使用,調製相關引數即可得到,我的效果也不太好