社群發現之譜聚類演算法的實現

2021-10-07 21:07:43 字數 4052 閱讀 6641

#譜聚類演算法實現

#1、計算距離矩陣(歐氏距離,作為相似度矩陣)

#2、利用knn計算鄰接矩陣a

#3、由鄰接矩陣計算都矩陣d和拉普拉斯矩陣l

#4、標準化拉普拉斯矩陣

#5、對拉普拉斯矩陣進行特徵值分解得到特徵向量

#6、對特徵向量進行k-means聚類

#7、得到分類結果

import numpy as np

#距離矩陣的計算

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是(500,2)的資料維度

x = np.array(x)

#初始化乙個相似度矩陣[len(x),len(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

#鄰接矩陣

#傳入的引數是相似度矩陣similarity和k

def myknn(s, k, sigma=1.0):

n = len(s)

a = np.zeros((n,n))

# print(s[0,:15])

for i in range(n):

#s[i]為相似都矩陣中的第i行的所有資料 s[i]長度為500

dist_with_index = zip(s[i], range(15))#每乙個值賦予乙個編號,然後打包,相當於給節點加上編號

#由小到大排序,按照x[0],也就是zip中的第乙個值,即相似度值(相似度值,編號)

dist_with_index = sorted(dist_with_index, key=lambda x:x[0])

#選出k個與節點i最相關的節點,相似度矩陣中值越小,表示兩點之間距離越近,相似度越大

#所以是由小到大排序,再選擇

#得到外迴圈節點i的鄰居節點集合

neighbours_id = [dist_with_index[m][1] for m in range(k+1)] # xi's k nearest neighbours

# print(neighbours_id)

# print(dist_with_index)

# print(len(dist_with_index))

# if i==0:

# break

#用高斯核函式計算鄰接矩陣的值

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

#資料載入

from sklearn import datasets

def gentwocircles(n_samples=1000):

#資料和標籤 (500,2)和500的維度

x, y = datasets.make_circles(n_samples, factor=0.5, noise=0.05)

return x, y

#拉普拉斯矩陣標準化

def callaplacianmatrix(adjacentmatrix):

# 計算鄰接矩陣的度

degreematrix = np.sum(adjacentmatrix, axis=1)#axis=1逐行相加 axis=0逐列相加

# 將鄰接矩陣轉化為對角矩陣,再減去鄰接矩陣就是拉普拉斯矩陣 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)

#畫圖from matplotlib import pyplot as plt

from itertools import cycle, islice

#引數data,y_sp為特徵向量聚類的標籤,y_km為原始資料聚類的標籤

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.show()

def main():

import sys

from sklearn.cluster import kmeans

np.random.seed(1)

#data維度是(500,2),500個樣本,本個樣本特徵維度是2

#label是(500),表示每乙個樣本的標籤

data, label = gentwocircles(n_samples=500)

#計算相似度矩陣 (500,500)的維度

similarity = caleucliddistancematrix(data)

#計算鄰接矩陣 k=10為每個節點擊擇最相似的10個鄰居

adjacent = myknn(similarity, k=10)#維度是(500,500)

#計算歸一化的拉普拉斯矩陣

laplacian = callaplacianmatrix(adjacent)

#計算拉普拉斯矩陣的特徵值和特徵向量 x:500 v(500,500)500個節點,每個節點特徵為500維

x, v = np.linalg.eig(laplacian)

#將特徵值由小到大排序 對應特徵向量

x = zip(x, range(len(x)))

x = sorted(x, key=lambda x: x[0])

#取出特徵向量來,因為特徵向量是按列排的,所以要轉置,用vstack推疊起來

h = np.vstack([v[:, i] for (v, i) in x[:500]]).t

#送入kmeans中聚類 傳入的是分解後的特徵向量

sp_kmeans = kmeans(n_clusters=2).fit(h)

#原始資料進行kmeans聚類

pure_kmeans = kmeans(n_clusters=2).fit(data)

#傳入plot函式作圖,原始資料,兩種聚類的標籤結果

plot(data, sp_kmeans.labels_, pure_kmeans.labels_)

if __name__ == '__main__':

main()

譜聚類演算法Matlab快速實現

ncut譜聚類完整函式定義 儲存為.m檔案 function c spectralclustering data,k,a data是資料點矩陣 k是聚類個數 a代表高斯核函式的引數 untitled summary of this function goes here detailed explan...

點雲學習 3 2 聚類演算法之譜聚類

譜聚類推導過程較為繁瑣,本文不作介紹,重點在於使用python語言實現演算法。譜聚類步驟 1.建無向圖,獲取鄰接矩陣w 對稱矩陣 2.計算拉普拉斯矩陣l l d w,其中d為對角陣,每個元素為w在該行求和 3.對l進行特徵分解,獲取最小的k個特徵值對應的特徵向量 4.將k個特徵向量構造成矩陣v 5....

譜聚類演算法原理介紹

給你上若干個部落格,讓你將它們分成k類,你會怎樣做?想必有很多方法,本文要介紹的是其中的一種 譜聚類。聚類的直觀解釋是根據樣本間相似度,將它們分成不同組。譜聚類的思想是將樣本看作頂點,樣本間的相似度看作帶權的邊,從而將聚類問題轉為圖分割問題 找到一種圖分割的方法使得連線不同組的邊的權重盡可能低 這意...