谱聚类初探
1, 譜聚類(lèi)引入
對(duì)于這樣分布的樣本,我們?cè)趺催M(jìn)行聚類(lèi)呢?我們可以使用核函數(shù)+K-means來(lái)聚類(lèi),當(dāng)然也可以使用本節(jié)將要介紹的譜聚類(lèi)。
2,模型介紹
譜聚類(lèi)是一種基于圖模型的聚類(lèi)方法(一般圖是帶權(quán)重的無(wú)向圖)。比起傳統(tǒng)的K-Means算法,譜聚類(lèi)對(duì)數(shù)據(jù)分布的適應(yīng)性更強(qiáng),聚類(lèi)效果也很優(yōu)秀,同時(shí)聚類(lèi)的計(jì)算量也小很多。
譜聚類(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.1 幾個(gè)圖的概念
先定義幾個(gè)概念:
圖:G={V,E}
節(jié)點(diǎn)集合:V={1,2,……,N}
2.1.1 邊集合與鄰接矩陣
邊集合: E:W=[wij] 1≤i,j≤N? ,這里我們用一個(gè)相似度矩陣W來(lái)表達(dá)節(jié)點(diǎn)與節(jié)點(diǎn)之間,即邊的信息。其中相似度的定義有以下幾種:
1、?-鄰近法
從上式可見(jiàn),兩點(diǎn)的權(quán)重要不就是?, 要不就是0, 沒(méi)有其他信息了。距離遠(yuǎn)近度量很不精確,因此在實(shí)際應(yīng)用中,我們很少使用?-鄰近法。
2、K鄰近法
利用KNN算法遍歷所有的樣本點(diǎn),取每個(gè)樣本最近的k個(gè)點(diǎn)作為近鄰,只有和樣本距離最近的k個(gè)點(diǎn)之間的邊權(quán)重大于0。但是這種方法會(huì)造成重構(gòu)之后的鄰接矩陣W非對(duì)稱(chēng),我們后面的算法需要對(duì)稱(chēng)鄰接矩陣。為了解決這種問(wèn)題,一般采取下面兩種方法之一:
3、全連接法
相比前兩種方法,第三種方法所有的點(diǎn)之間的權(quán)重值都大于0,因此稱(chēng)之為全連接法。在實(shí)際的應(yīng)用中,使用第三種全連接法來(lái)建立鄰接矩陣是最普遍的。
可以選擇不同的核函數(shù)來(lái)定義邊權(quán)重,常用的有多項(xiàng)式核函數(shù),高斯核函數(shù)和Sigmoid核函數(shù)。最常用的是高斯核函數(shù)RBF。
2.1.2 度與度矩陣
度:度為該頂點(diǎn)與其他頂點(diǎn)連接權(quán)值之和。度矩陣是一個(gè)對(duì)角矩陣。
2.2 切割
2.2.1 兩類(lèi)的切割
我們先看切割成兩類(lèi)的情況
也就是兩個(gè)切割A(yù),B之間的度量是任意A中的點(diǎn)和任意B中的點(diǎn)之間的相似度。也就是“切口”兩側(cè)的點(diǎn)之間的相似度權(quán)重。
2.2.2 K類(lèi)的切割
然后我們推廣到K個(gè)類(lèi)別
那么這個(gè)K類(lèi)切割怎么度量呢?從在兩類(lèi)切割的情況我們知道,切割的度量只取決于“切口”兩側(cè)點(diǎn)之間的相似度權(quán)重。那么K類(lèi)切割也是同理,只不過(guò)原來(lái)是切一刀,現(xiàn)在是切K刀,每一刀切下Ai和其他部分。
于是我們就有:
那么我們可以通過(guò)調(diào)整Ai的分配,獲得最小的Cut。
2.3 Ncut
但是如果僅最優(yōu)化這邊的cut,會(huì)有一個(gè)不足。就是我們希望分割效果更好,希望每一個(gè)分割“緊湊”一點(diǎn)。也就是類(lèi)間的相似度低(w小),類(lèi)內(nèi)的相似度大(w大)。那么Cut的定義就無(wú)法滿足我們這個(gè)需求了。為了滿足這個(gè)“分割緊湊”的需求,我們對(duì)Cut進(jìn)行歸一化操作:
這里的Δ定義為某一類(lèi)內(nèi)點(diǎn)的度(雖然我覺(jué)得可能是類(lèi)內(nèi)點(diǎn)之間的度更合理一點(diǎn)?歡迎討論)
整合一下,Normalized Cut (NCut)的定義為
?
我們的目標(biāo)是
3, Ncut模型的矩陣表示
通過(guò)上一小節(jié),我們知道
為了更方便地求解這個(gè)優(yōu)化問(wèn)題,我們一般要將它轉(zhuǎn)化為矩陣形式
3.1 指示向量
我們先來(lái)看一下等號(hào)左邊,我們定義一個(gè)指示向量indicator vector,它類(lèi)似于one-hot向量
?
3.2 Ncut
接下來(lái)我們要對(duì)Ncut進(jìn)行矩陣表示
NCut是一個(gè)求和的數(shù)值,那么我們可以將其轉(zhuǎn)化為對(duì)角矩陣求跡(trace)
然后把分子分母分離(對(duì)角矩陣求逆相當(dāng)于對(duì)每一個(gè)對(duì)角線元素求逆):
整合一下,即:
但是,我們目前知道的是相似度矩陣W(N×N維)和指示向量Y(N×K維)【這里我們先給定一個(gè)特定的Y,然后將O,P用Y來(lái)表示。之后再用優(yōu)化問(wèn)題求解Y,所以此時(shí)Y暫定為已知的】
3.2.1 求P
我們先看一下?(K×K維):
?
?
對(duì)于每一個(gè),的結(jié)果是一個(gè)K×K的矩陣。如果中第j維是1(其他是0),那么中只有第(j,j)坐標(biāo)元素為1,其余為0。
那么這樣所有的求和的結(jié)果,元素值為1的部分全在對(duì)角線上.
對(duì)角線上的每個(gè)元素都是這一類(lèi)的元素個(gè)數(shù)。這個(gè)已經(jīng)和P(下圖)很像了,唯一的區(qū)別就是求和的內(nèi)容。
我們?cè)谇懊嬗钟?/p>
所以前面的P也可以寫(xiě)成
整合一下,有:
3.2.2. 求O
最后我們來(lái)看O
?
對(duì)于第一項(xiàng),也就是組別k內(nèi)所有點(diǎn)的度之和,即
而我們前面已經(jīng)求得了
而對(duì)于第二項(xiàng)
我們先猜測(cè)一下,因?yàn)槲覀儸F(xiàn)在就只知道W和Y,我們先試試行不行.
因?yàn)槲覀冎皇切枰筵E,而
是對(duì)角矩陣,所以這里我們也只需要驗(yàn)證的對(duì)角線部分即可。
我們?nèi)?什么時(shí)候元素會(huì)到對(duì)角線上呢?那就是yi和yj在一組里面(比如第k組)。此時(shí)第k行第k列的元素+
所以最后,只看對(duì)角線上的元素,那么這個(gè)矩陣就是
3.3 結(jié)論
所以
其中D-W我們稱(chēng)之為拉普拉斯矩陣
3.4 求最優(yōu)方案的方法
在之后會(huì)涉及的RatioCut中,我們?nèi)デ罄绽咕仃嘗的最小的前k個(gè)特征值,然后求出對(duì)應(yīng)的特征向量并標(biāo)準(zhǔn)化,然后對(duì)結(jié)果進(jìn)行一次傳統(tǒng)的聚類(lèi)。
Ncut和RatioCut唯一的區(qū)別就是分母的D,所以仿RatioCut方法,我們這里進(jìn)行特征分解的矩陣為標(biāo)準(zhǔn)化的拉普拉斯矩陣,即
4 拉普拉斯矩陣
拉普拉斯矩陣(Laplacian matrix)),也稱(chēng)為基爾霍夫矩陣, 是表示圖的一種矩陣。給定一個(gè)有n個(gè)頂點(diǎn)的圖,其拉普拉斯矩陣被定義為:L=D?W?其中D為圖的度矩陣,W為圖的鄰接矩陣。
?
4.1 拉普拉斯矩陣舉例
以下圖為例:
| 鄰接矩陣 | |
| 度矩陣 | |
| 拉普拉斯矩陣 |
?
?
?
?
?
?
?
?
?
?
?
?
4.2 拉普拉斯矩陣性質(zhì)
證明:
5 RatioCut切圖
大體思路和Ncut是一樣的,不過(guò)分母除的不是某個(gè)分割的度之和,而是某個(gè)分割中點(diǎn)的個(gè)數(shù)
和Ncut一樣,這邊的指示向量也表示了第i個(gè)元素(i∈[1,n])在第j個(gè)分割中(j∈[1,k])
那么我們對(duì)每一個(gè)分割A(yù)i有:
(展開(kāi)的時(shí)候,都屬于Ai的和都不屬于Ai的相減為0,所以不顯示出來(lái))
? ? ? ? ? ? ? ?
(Ai分割邊緣上所有點(diǎn)的權(quán)重之和就是cut(Ai,~Ai))
? ? ? ? ? ? ? ??
匯總到一塊,總的分割的RatioCut為
通過(guò)找到L的最小的k個(gè)特征值,可以得到對(duì)應(yīng)的k個(gè)特征向量,這k個(gè)特征向量組成一個(gè)nxk維度的矩陣,即為我們的H。
由于我們?cè)谑褂镁S度規(guī)約的時(shí)候損失了少量信息,導(dǎo)致得到的優(yōu)化后的指示向量h對(duì)應(yīng)的H現(xiàn)在不能完全指示各樣本的歸屬,因此一般在得到 n × k維度的矩陣H后還需要對(duì)每一行進(jìn)行一次傳統(tǒng)的聚類(lèi),比如使用K-Means聚類(lèi)。
6 譜聚類(lèi)算法流程匯總
以Ncut為例
輸入:樣本集D=(x1,x2,x3,......,xn)、相似矩陣的生成方式、 降維后的維度k1(需要分成幾個(gè)分割)、聚類(lèi)方法、聚類(lèi)后的維度k2
輸出: 簇劃分C=(c1,c2,.....ck2)?
流程:
1)根據(jù)輸入的相似矩陣的生成方式構(gòu)建樣本的相似矩陣S
2)根據(jù)相似矩陣S構(gòu)建鄰接矩陣W ,構(gòu)建度矩陣D
3)計(jì)算出拉普拉斯矩陣L
4)構(gòu)建標(biāo)準(zhǔn)化后的拉普拉斯矩陣
5)計(jì)算最小的k1個(gè)特征值所各自對(duì)應(yīng)的特征向量f
6) 將各自對(duì)應(yīng)的特征向量f組成的矩陣按行標(biāo)準(zhǔn)化,最終組成n × k1的特征矩陣F(第j個(gè)矩陣(j∈[1,n])屬于第i個(gè)分割(i∈[1,k1]))
7)對(duì)F中的每一行作為一個(gè)k1維的樣本,共n個(gè)樣本,用輸入的聚類(lèi)方法進(jìn)行聚類(lèi),聚類(lèi)維數(shù)為k2
8)得到簇劃分C=(c1,c2,.....ck2)?
7 譜聚類(lèi)python實(shí)現(xiàn)
為了方便記憶,我按照流程1~8依次實(shí)現(xiàn)
7-0-1 導(dǎo)入庫(kù)
import numpy as np from sklearn import datasets7-0-2 加載鳶尾花數(shù)據(jù)
#加載鳶尾花數(shù)據(jù) iris=datasets.load_iris() ''' print(iris['data'].shape) (150, 4) print(iris['data'][0]) array([5.1, 3.5, 1.4, 0.2]) '''m=iris['data'].shape[0] n=iris['data'].shape[1]7-1 構(gòu)建樣本的相似矩陣S
#相似矩陣 AMatrix=np.zeros((m,m))#求兩條記錄之間的距離(相似度),用高斯核函數(shù) def AffMatrix(arrA,arrB):sigma=0.5 diff=arrA-arrB #兩個(gè)ndarray逐元素相減diff=np.square(diff)#相減的結(jié)果逐元素平方a=np.sum(diff)#到這里就完成了||x-x'||^2這一部分了b=2*(np.square(sigma))#到這里完成了2*σ^2w=np.exp(-a/b) #高斯核函數(shù)#print(w)return w7-2?根據(jù)相似矩陣S構(gòu)建鄰接矩陣W ,構(gòu)建度矩陣D
7-2-1 鄰接矩陣
#計(jì)算鄰接矩陣 def M_Matrix(m,AMatrix):for i in range(m):for j in range(m):AMatrix[i][j]=AffMatrix(iris['data'][i],iris['data'][j])#計(jì)算兩兩的相似度AMatrix=AMatrix-np.identity(m)#我們認(rèn)為自己到自己是沒(méi)有邊相連的,所以需要讓對(duì)角線元素變?yōu)?#自己和自己的高斯核結(jié)果為0return AMatrixw=M_Matrix(m,AMatrix)''' w.shape (150, 150) '''7-2-2 度矩陣
D=np.diag(np.sum(w,axis=0))這里復(fù)習(xí)一個(gè)知識(shí),就是axis的事情
axis=0 第0個(gè)坐標(biāo)的元素疊加,其他坐標(biāo)的元素不變 sum([0,1,2,....,n][x][y])
axis=1 第1個(gè)坐標(biāo)的元素疊加,其他坐標(biāo)的元素不變 sum([x][0,1,2,....,n][y])
7.3?計(jì)算出拉普拉斯矩陣L=D?W?
L=D-w7.4?構(gòu)建標(biāo)準(zhǔn)化后的拉普拉斯矩陣
#np.power(np.sum(w,axis=0),-0.5) #D的對(duì)角線元素開(kāi)根號(hào) Dn=np.diag(np.power(np.sum(w,axis=0),-0.5)) #Dn=D^(-1/2) L=Dn.dot(L).dot(Dn)7.5?計(jì)算最小的k1個(gè)特征值所各自對(duì)應(yīng)的特征向量f
eigvals, eigvecs = np.linalg.eig(L) # 規(guī)范化后的拉普拉斯矩陣 特征分解k = 3 indices = eigvals.argsort()[:k] #最小的三個(gè)特征值k_max_eigvecs = eigvecs[:,indices] #最小的三個(gè)特征值對(duì)應(yīng)的特征向量 ''' k_max_eigvecs.shape (150,3) '''7.7?對(duì)F中的每一行作為一個(gè)k1維的樣本,共n個(gè)樣本,用輸入的聚類(lèi)方法進(jìn)行聚類(lèi),聚類(lèi)維數(shù)為k2
#KNN進(jìn)行聚類(lèi) from sklearn.cluster import KMeansres = KMeans(n_clusters=k).fit_predict(k_max_eigvecs)7.9?可視化
def draw():colorSet = ["black", "blue", "green", "yellow", "red", "purple", "orange", "brown"]for i in range(m):x = iris['data'][i][0]y = iris['data'][i][1]color = colorSet[res[i] % len(colorSet)]plt.scatter(x,y, marker="o", c=color, s=20)plt.xlabel("x")plt.ylabel("y")plt.show() draw()8 sklearn庫(kù)中的譜聚類(lèi)使用
在scikit-learn的類(lèi)庫(kù)中,sklearn.cluster.SpectralClustering實(shí)現(xiàn)了基于Ncut的譜聚類(lèi),沒(méi)有實(shí)現(xiàn)基于RatioCut的切圖聚類(lèi)。同時(shí),對(duì)于相似矩陣的建立,也只是實(shí)現(xiàn)了基于K鄰近法和全連接法的方式,沒(méi)有基于?-鄰近法的相似矩陣。
8.1?SpectralClustering中的參數(shù)
8.1.1?n_clusters
代表我們?cè)趯?duì)譜聚類(lèi)切圖時(shí)降維到的維數(shù),同時(shí)也是最后一步聚類(lèi)算法聚類(lèi)到的維數(shù)。
8.1.2 affinity:
我們的相似矩陣的建立方式。可以選擇的方式有三類(lèi),
第一類(lèi)是 **‘nearest_neighbors’**即K鄰近法。
第二類(lèi)是**‘precomputed’**即自定義相似矩陣。選擇自定義相似矩陣時(shí),需要自己調(diào)用set_params來(lái)自己設(shè)置相似矩陣。
第三類(lèi)是全連接法,可以使用各種核函數(shù)來(lái)定義相似矩陣,還可以自定義核函數(shù)。
最常用的是內(nèi)置高斯核函數(shù)’rbf’。其他比較流行的核函數(shù)有‘linear’即線性核函數(shù), ‘poly’即多項(xiàng)式核函數(shù), ‘sigmoid’即sigmoid核函數(shù)。
如果選擇了這些核函數(shù), 對(duì)應(yīng)的核函數(shù)參數(shù)在后面有單獨(dú)的參數(shù)需要設(shè)置。
affinity默認(rèn)是高斯核’rbf’。
8.1.3 核函數(shù)參數(shù)gamma:
如果我們?cè)赼ffinity參數(shù)使用了多項(xiàng)式核函數(shù) ‘poly’,高斯核函數(shù)‘rbf’, 或者’sigmoid’核函數(shù),那么我們就需要對(duì)這個(gè)參數(shù)進(jìn)行調(diào)參。
8.1.4 核函數(shù)參數(shù)degree
如果我們?cè)赼ffinity參數(shù)使用了多項(xiàng)式核函數(shù) ‘poly’,那么我們就需要對(duì)這個(gè)參數(shù)進(jìn)行調(diào)參。這個(gè)參數(shù)對(duì)應(yīng)中的d。默認(rèn)是3。
8.1.5?核函數(shù)參數(shù)coef0:
如果我們?cè)赼ffinity參數(shù)使用了多項(xiàng)式核函數(shù) ‘poly’,或者sigmoid核函數(shù),那么我們就需要對(duì)這個(gè)參數(shù)進(jìn)行調(diào)參。
8.1.6 kernel_params
如果affinity參數(shù)使用了自定義的核函數(shù),則需要通過(guò)這個(gè)參數(shù)傳入核函數(shù)的參數(shù)。
8.1.7 n_neighbors
?如果我們affinity參數(shù)指定為’nearest_neighbors’即K鄰近法,則我們可以通過(guò)這個(gè)參數(shù)指定KNN算法的K的個(gè)數(shù)。默認(rèn)是10
8.2 代碼
from sklearn.cluster import SpectralClustering from sklearn import metricsiris=datasets.load_iris() y_pred = SpectralClustering(gamma=0.1,n_clusters=3).fit_predict(iris['data'])8.3 可視化
可以看到結(jié)果和我們之前自己實(shí)現(xiàn)的是差不多的
def draw():colorSet = ["black", "blue", "green", "yellow", "red", "purple", "orange", "brown"]for i in range(m):x = iris['data'][i][0]y = iris['data'][i][1]color = colorSet[y_pred[i] % len(colorSet)]plt.scatter(x,y, marker="o", c=color, s=20)plt.xlabel("x")plt.ylabel("y")plt.show() draw() 《新程序員》:云原生和全面數(shù)字化實(shí)踐50位技術(shù)專(zhuān)家共同創(chuàng)作,文字、視頻、音頻交互閱讀總結(jié)
- 上一篇: python库整理:heapq 最小堆
- 下一篇: 数据库笔记-导论