Spectral?clustering譜聚類(lèi)算法的實(shí)現(xiàn)代碼
1.作者介紹
劉然,女,西安工程大學(xué)電子信息學(xué)院,2021級(jí)研究生
研究方向:圖像處理
電子郵件:1654790996@qq.com
劉帥波,男,西安工程大學(xué)電子信息學(xué)院,2021級(jí)研究生,張宏偉人工智能課題組
研究方向:機(jī)器視覺(jué)與人工智能
電子郵件:1461004501@qq.com
2.關(guān)于譜聚類(lèi)的介紹
2.1 譜聚類(lèi)概述
譜聚類(lèi)是從圖論中演化出來(lái)的算法,它的主要思想是把所有的數(shù)據(jù)看做空間中的點(diǎn),這些點(diǎn)之間可以用邊連接起來(lái)。距離較遠(yuǎn)的兩個(gè)點(diǎn)之間的邊權(quán)重值較低,而距離較近的兩個(gè)點(diǎn)之間的邊權(quán)重值較高,通過(guò)對(duì)所有數(shù)據(jù)點(diǎn)組成的圖進(jìn)行切圖,讓切圖后不同的子圖間邊權(quán)重和盡可能的低,而子圖內(nèi)的邊權(quán)重和盡可能的高,從而達(dá)到聚類(lèi)的目的。
2.2 無(wú)向權(quán)重圖
對(duì)于一個(gè)圖G,我們一般用點(diǎn)的集合V和邊的集合E來(lái)描述。即為G(V,E)。其中V即為我們數(shù)據(jù)集里面所有的點(diǎn)(v1,v2,…vn)。對(duì)于V中的任意兩個(gè)點(diǎn),點(diǎn)vi和點(diǎn)vj,我們定義權(quán)重wij為二者之間的權(quán)重。由于是無(wú)向圖,所以wij=wji。
2.3 鄰接矩陣
鄰接矩陣(Adjacency Matrix):是表示頂點(diǎn)之間相鄰關(guān)系的矩陣。在如圖2-1所示的權(quán)重圖當(dāng)中(假設(shè)各權(quán)重為1),其鄰接矩陣可表示為圖2-2所示。


2.4 相似矩陣
在譜聚類(lèi)中,我們只有數(shù)據(jù)點(diǎn)的定義,并沒(méi)有直接給出這個(gè)鄰接矩陣,所以我們可以通過(guò)樣本點(diǎn)距離度量的相似矩陣S來(lái)獲得鄰接矩陣W。
2.5 度矩陣
度矩陣是對(duì)角陣,對(duì)角上的元素為各個(gè)頂點(diǎn)的度。圖2-1的度矩陣為圖2-3所示。

2.6 拉普拉斯矩陣
拉普拉斯矩陣L=D-W,其中D為度矩陣,W為鄰接矩陣。圖2-1的拉普拉斯矩陣為圖2-4所示。

用拉普拉斯矩陣求解特征值,通過(guò)確定特征值(特征值要遵循從小到大的排列方式)的個(gè)數(shù)來(lái)確定對(duì)應(yīng)特征向量的個(gè)數(shù),從而實(shí)現(xiàn)降維,然后再用kmeans將特征向量進(jìn)行聚類(lèi)。
2.7 K-Means
K-Means是聚類(lèi)算法中的最常用的一種,算法最大的特點(diǎn)是簡(jiǎn)單,好理解,運(yùn)算速度快,但是只能應(yīng)用于連續(xù)型的數(shù)據(jù),并且一定要在聚類(lèi)前需要手工指定要分成幾類(lèi)。
下面,我們描述一下K-means算法的過(guò)程,為了盡量不用數(shù)學(xué)符號(hào),所以描述的不是很?chē)?yán)謹(jǐn),大概就是這個(gè)意思,“物以類(lèi)聚、人以群分”:
1.首先輸入k的值,即我們希望將數(shù)據(jù)集經(jīng)過(guò)聚類(lèi)得到k個(gè)分組。
2.從數(shù)據(jù)集中隨機(jī)選擇k個(gè)數(shù)據(jù)點(diǎn)作為初始大哥(質(zhì)心,Centroid)
3.對(duì)集合中每一個(gè)小弟,計(jì)算與每一個(gè)大哥的距離(距離的含義后面會(huì)講),離哪個(gè)大哥距離近,就跟定哪個(gè)大哥。
4.這時(shí)每一個(gè)大哥手下都聚集了一票小弟,這時(shí)候召開(kāi)人民代表大會(huì),每一群選出新的大哥(其實(shí)是通過(guò)算法選出新的質(zhì)心)。
5.如果新大哥和老大哥之間的距離小于某一個(gè)設(shè)置的閾值(表示重新計(jì)算的質(zhì)心的位置變化不大,趨于穩(wěn)定,或者說(shuō)收斂),可以認(rèn)為我們進(jìn)行的聚類(lèi)已經(jīng)達(dá)到期望的結(jié)果,算法終止。
6.如果新大哥和老大哥距離變化很大,需要迭代3~5步驟。
3.Spectral clustering(譜聚類(lèi))算法實(shí)現(xiàn)
3.1 數(shù)據(jù)集
本實(shí)驗(yàn)中使用到的數(shù)據(jù)集均由sklearn.datasets中提供的方法生成,本實(shí)驗(yàn)中用到了make_circles,make_moons,make_blobs等函數(shù)。make_circles生成數(shù)據(jù)集,形成一個(gè)二維的大圓,包含一個(gè)小圓,如圖3-1所示;make_moons生成數(shù)據(jù)集,形成兩個(gè)彎月,如圖3-2所示;make_blobs為聚類(lèi)生成符合正態(tài)分布的數(shù)據(jù)集,如圖3-3所示。



3.2 導(dǎo)入所需要的包
#導(dǎo)入需要的包 import numpy as np from sklearn.cluster import KMeans from sklearn.datasets import make_moons#生成數(shù)據(jù)集,形成兩個(gè)彎月。 from sklearn.datasets import make_circles#生成數(shù)據(jù)集,形成一個(gè)二維的大圓,包含一個(gè)小圓 from sklearn.datasets import make_blobs#為聚類(lèi)生成符合正態(tài)分布的數(shù)據(jù)集,產(chǎn)生一個(gè)數(shù)據(jù)集和相應(yīng)的標(biāo)簽 import matplotlib.pyplot as plt
3.3 獲取特征值和特征向量
def get_eigen(L, num_clusters):#獲取特征
eigenvalues, eigenvectors = np.linalg.eigh(L)#獲取特征值 特征向量
best_eigenvalues = np.argsort(eigenvalues)[0:num_clusters]#argsort函數(shù)返回的是數(shù)組值從小到大的索引值
U = np.zeros((L.shape[0], num_clusters))
U = eigenvectors[:, best_eigenvalues]#將這些特征取出 構(gòu)成新矩陣
return U
3.4 利用K-Means聚類(lèi)
#K-Means聚類(lèi)
def cluster(data, num_clusters):
data = np.array(data)
W = affinity_matrix(data)
D = getD(W)
L = getL(D, W)
eigenvectors = get_eigen(L, num_clusters)
clf = KMeans(n_clusters=num_clusters)
s = clf.fit(eigenvectors) # 聚類(lèi)
label = s.labels_
return label
3.5 完整代碼
#導(dǎo)入需要的包
import numpy as np
from sklearn.cluster import KMeans
from sklearn.datasets import make_moons#生成數(shù)據(jù)集,形成兩個(gè)彎月。
from sklearn.datasets import make_circles#生成數(shù)據(jù)集,形成一個(gè)二維的大圓,包含一個(gè)小圓
from sklearn.datasets import make_blobs#為聚類(lèi)生成符合正態(tài)分布的數(shù)據(jù)集,產(chǎn)生一個(gè)數(shù)據(jù)集和相應(yīng)的標(biāo)簽
import matplotlib.pyplot as plt
#定義高斯核函數(shù)
def kernel(x1, x2, sigma_sq=0.05):
return np.exp(-(np.linalg.norm(x1 - x2) ** 2) / (2 * sigma_sq ** 2))
#定義相似度矩陣
def affinity_matrix(X):
A = np.zeros((len(X), len(X)))#零矩陣
for i in range(len(X) - 1):#長(zhǎng)度為len(x) 但是從0開(kāi)始
for j in range(i + 1, len(X)):#從1開(kāi)始,到len(x) 是方陣 為啥下角標(biāo)取值的初始值不同???
A[i, j] = A[j, i] = kernel(X[i], X[j])
return A#通過(guò)高斯核的計(jì)算 給矩陣賦予新值 10*10
# 計(jì)算度矩陣
def getD(A):
D = np.zeros(A.shape)
for i in range(A.shape[0]):
D[i, i] = np.sum(A[i, :])
return D
#計(jì)算拉普拉斯矩陣
def getL(D, A):
L = D - A
return L
def get_eigen(L, num_clusters):#獲取特征
eigenvalues, eigenvectors = np.linalg.eigh(L)#獲取特征值 特征向量
best_eigenvalues = np.argsort(eigenvalues)[0:num_clusters]#argsort函數(shù)返回的是數(shù)組值從小到大的索引值
U = np.zeros((L.shape[0], num_clusters))
U = eigenvectors[:, best_eigenvalues]#將這些特征取出 構(gòu)成新矩陣
return U
#K-Means聚類(lèi)
def cluster(data, num_clusters):
data = np.array(data)
W = affinity_matrix(data)
D = getD(W)
L = getL(D, W)
eigenvectors = get_eigen(L, num_clusters)
clf = KMeans(n_clusters=num_clusters)
s = clf.fit(eigenvectors) # 聚類(lèi)
label = s.labels_
return label
def plotRes(data, clusterResult, clusterNum):
"""
結(jié)果可似化
: data: 樣本集
: clusterResult: 聚類(lèi)結(jié)果
: clusterNum: 聚類(lèi)個(gè)數(shù)
:return:
n = len(data)
scatterColors = ['black', 'blue', 'red', 'yellow', 'green', 'purple', 'orange']
for i in range(clusterNum):
color = scatterColors[i % len(scatterColors)]
x1 = []
y1 = []
for j in range(n):
if clusterResult[j] == i:
x1.append(data[j, 0])
y1.append(data[j, 1])
plt.scatter(x1, y1, c=color, marker='+')
if __name__ == '__main__':
# # #月牙形數(shù)據(jù)集,sigma=0.1
# # # cluster_num = 2
# # # data, target = make_moons()
# # # label = cluster(data, cluster_num)
# # # print(label)
# # # plotRes(data, label, cluster_num)
# #
# # 圓形數(shù)據(jù)集,sigma=0.05
cluster_num = 2
data, target = make_circles(n_samples=1000, shuffle=True, noise=0.05, factor=0.5)
label = cluster(data, cluster_num)
print(label)
plotRes(data, label, cluster_num)
# # # # 正態(tài)數(shù)據(jù)集
# # # # n_samples是待生成的樣本的總數(shù)。
# # # # n_features是每個(gè)樣本的特征數(shù)。
# # # # centers表示類(lèi)別數(shù)。
# # # # cluster_std表示每個(gè)類(lèi)別的方差,例如我們希望生成2類(lèi)數(shù)據(jù),其中一類(lèi)比另一類(lèi)具有更大的方差,可以將cluster_std設(shè)置為[1.0, 3.0]。
# # # cluster_num = 2
# # # data, target = make_blobs(n_samples=1500, n_features=2, centers=4, random_state=24)
# # # label = cluster(data, cluster_num)
# # # print(label)
# # # plt.subplot(121)
# # # plotRes(data, target, cluster_num)
# # # plt.subplot(122)
# # # plotRes(data, label, cluster_num)
plt.show()
4.參考
1.<譜聚類(lèi)(spectral clustering)原理總結(jié) - 劉建平Pinard - 博客園
2.參考博客1
3.參考博客2
4.參考博客3
到此這篇關(guān)于Spectral clustering譜聚類(lèi)算法的實(shí)現(xiàn)的文章就介紹到這了,更多相關(guān)Spectral clustering譜聚類(lèi)算法內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
python提取具有某種特定字符串的行數(shù)據(jù)方法
今天小編就為大家分享一篇python提取具有某種特定字符串的行數(shù)據(jù)方法,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。一起跟隨小編過(guò)來(lái)看看吧2018-12-12
Python光學(xué)仿真教程實(shí)現(xiàn)光線追蹤
傳統(tǒng)的高斯光學(xué)是建立在傍軸近似基礎(chǔ)之上的理想成像理論,這種處理以物像關(guān)系為核心,通過(guò)基點(diǎn)對(duì)光路的成像特性進(jìn)行描述。然而,傍軸近似在一定程度上犧牲了精確性,從而使得需要一套像差理論作為補(bǔ)充2021-10-10
Sublime?Text?配置?Python?環(huán)境的問(wèn)題及解決方案
這篇文章主要介紹了Sublime?Text?配置?Python?環(huán)境的問(wèn)題,文中介紹了python自定義的構(gòu)建系統(tǒng)的完整代碼,代碼簡(jiǎn)單易懂,對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下2022-01-01
python根據(jù)txt文本批量創(chuàng)建文件夾
這篇文章主要為大家詳細(xì)介紹了python根據(jù)txt文本批量創(chuàng)建文件夾,文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2019-03-03
python實(shí)現(xiàn)QQ郵箱群發(fā)郵件實(shí)例
大家好,本篇文章主要講的是python實(shí)現(xiàn)QQ郵箱群發(fā)郵件實(shí)例,感興趣的同學(xué)趕快來(lái)看一看吧,對(duì)你有幫助的話記得收藏一下2022-01-01
Python通過(guò)遞歸獲取目錄下指定文件代碼實(shí)例
這篇文章主要介紹了python通過(guò)遞歸獲取目錄下指定文件代碼實(shí)例,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友可以參考下2019-11-11

