簡介
文章將介紹譜聚類(spectral clustering)的基本算法,以及在matlab下的代碼實現。介紹內容將包括:
- 從圖分割角度直觀理解譜聚類
- 譜聚類算法步驟
- 數據以及實現代碼
本文將不會涉及細節化的證明和推導,如有興趣可參考july大神的文章從拉普拉斯矩陣說到譜聚類.
對譜聚類的理解
這一節將從圖分割聚類的角度直觀理解譜聚類。不過,因爲本人是從事社交媒體分析的,將從一種社會關係網絡的角度來介紹網絡圖分割成多個子圖的概念。
圖的分割
首先將社會關係網絡看成是一個整體,每一個個體(user)就是這個網絡中的各個節點(node),而連接個體的就是各個節點之間的邊(edge)。在不同性質的網絡中,邊的定義可能有所不同,這裏可以簡單的理解成個體之間關係的親密度。如圖(1)所示
每個個體與其他個體之間都有關係親密度(也叫做權重,設定範圍是[0,1]),可以看到user1,2,3之間關係緊密,user4,5,6關係緊密,而兩個小部分是靠着user2和user6來聯繫的。以現實生活爲例,123是A班級同學,456是B班級同學,2和6正好是認識的,關係一般,所以我們可以直觀的把2和6之間的邊給截斷(cut),從而形成兩個互不相關的子圖,這樣就完成了對這個網絡的分割。
圖的泛化意義
很多時候,並不是說一定要實際生活中是一個網絡(network)的事物,才能夠用圖(graph)模型來表示。圖模型只是解決問題的一個模型,可能一個對象既可以用圖模型,也可以用非圖模型來解決(拓撲,非拓撲)。舉個例子,在聚類,我們之前(K-means 聚類算法及其代碼實現)討論過如何將數據點看成是座標系下的一個個點,然後迭代找出中心點從而聚類。如果以另外一種視角,我們的座標系中的各個點看成是圖的節點,而點與點之間的相似性看成是邊的權重,我們同樣就構成了一個圖模型。所以圖與非圖是相對來看的,取決於哪個更好解決問題。
譜聚類的意義
譜聚類要做的事情就是完成對圖的分割,它想要找到最好的分割方式,來將圖分割開來。這種對圖的分割,取決於你如何定義這個圖。比如,圖中的點是什麼?圖中的邊又是怎麼確定的?最優分割的標準又是怎麼樣的?等等。對圖本身定義的不同,就會導致不同的分割結果,所以我們爲了明確這些東西,在這裏以一個實際的定義爲準,事先聲明,圖的定義也可以用其他方式,不過我這裏用的就是現在常用的相似度矩陣圖模型。
我們要解決的問題是:給定數據{
而我們將這些數據點都看成是數據的節點,它們之間的相似度定義爲邊的權重值,相似度矩陣爲
高斯相似度來計算的,其中
這樣計算。
因爲沒有給出關於截的概念,所以沒有辦法給出優化函數的形式,具體內容,還請參考從拉普拉斯矩陣說到譜聚類。
譜聚類算法步驟
這一小節將會給出譜聚類算法的步驟,整體來說,譜聚類算法要做的就是先求出相似性矩陣,然後對該矩陣歸一化運算,之後求前
實際上,譜聚類要做的事情其實就是將高維度的數據,以特徵向量的形式簡潔表達,屬於一種降維的過程。本來高維度用k-means不好分的點,在經過線性變換以及降維之後,十分容易求解。下面就給出步驟:
1. 按照式
2. 將
3. 按照式
4. 按照式
5. 計算L的特徵向量,將前
6. 歸一化X形成矩陣Y
7. 對矩陣Y按每行爲一個數據點,進行k-means聚類,第
至此就完成了譜聚類的全部過程。但是這裏面我們其實忽略了一個很重要的參數
譜聚類代碼分析
這一節介紹如何用matlab實現譜聚類的算法,數據以及代碼可以在我的github上下載。
代碼要解決的問題是如圖(2)所示的一個分類問題,
圖(2)
從圖片上面我們可以看到這個數據有兩個環,外面的環就是第一類,內部的環就是第二類,這個分類問題,是普通的k-means算法無法解決的。所以我們將使用代碼來實現上一節介紹的各個步驟。
首先,我們的數據存在
data
中,導入得到數據allpts
.
- 計算相似度矩陣
W ,其中向量化是運算可以用式(5) 來理解。
X = allpts;
N = size(X,1);
squared_X = sum(X.*X,2);
transi_X = X*X'; %x_j * x_i^T;
X_i = repmat(squared_X,1,N); % same value in row
X_j = repmat(squared_X',N,1); % same value in col
E = -(X_i + X_j - 2*transi_X );
W = exp(E/(2*sigsq));
2. 將對角線設爲零
W = W - diag(diag(W));
diag()既可以取出對角線的元素,也可以將一個向量生成一個對角矩陣。
3. 計算歸一化矩陣
D = diag(sum(W'));
.
4. 計算拉普拉斯矩陣
L =D^(-.5)*W*D^(-.5);
.
5. 找特徵值特徵向量並排序,找前K個
K = 2;
[X,di]=eig(L);
[Xsort,Dsort]=eigsort(X,di);
Xuse=Xsort(:,1:K);
因爲我這裏面只想分成兩類,所以K=2. 同時這裏的eigsort是另外定義1的函數,如下
% [Vsort,Dsort] = eigsort(V,D)
%
% Sorts a matrix eigenvectors and a matrix of eigenvalues in order
% of eigenvalue size, largest eigenvalue first and smallest eigenvalue
function [Vsort,Dsort] = eigsort(V,D);
eigvals = diag(D);
% Sort the eigenvalues from largest to smallest. Store the sorted
% eigenvalues in the column vector lambda.
[lohival,lohiindex] = sort(eigvals);
lambda = flipud(lohival);
index = flipud(lohiindex);
Dsort = diag(lambda);
% Sort eigenvectors to correspond to the ordered eigenvalues. Store sorted
% eigenvectors as columns of the matrix vsort.
M = length(lambda);
Vsort = zeros(M,M);
for i=1:M
Vsort(:,i) = V(:,index(i));
end;
其中一些不必要的註釋我就刪除了。
6. 歸一化X得到矩陣Y
Xsq = Xuse.*Xuse;
divmat=repmat(sqrt(sum(Xsq')'),1,2)
Y=Xuse./divmat
歸一化就是將特徵向量長度變成1
7. 進行k-means聚類算法
[c,Dsum,z] = kmeans(Y,2)
kk=c;
c1=find(kk==1);
c2=find(kk==2);
kmeans聚類後,找到類別標號,最後簡單畫一個圖(3)顯示我們的分類結果
圖(3)
這裏,我們用兩種顏色表示了兩種不同的類別,代碼中的
sigma
可能不同,會導致不同的結果,這個我沒有給出,各人根據問題各自設定0.1到10之類,具體可以去我的github上面下載完整代碼和數據。
總結
至此,完成了全部的譜聚類算法的理解,算法具體步驟,以及實際實現代碼。譜聚類能夠完成k-means不能完成的工作,其基本思想是一個線性空間變換,能夠提取出特徵向量降維表示原本複雜的數據,從來使用k-means進行一個簡單的聚類。涉及到特徵向量的算法,還有之後會繼續寫的PCA算法。
參考文獻
- Ng, A. Y., M. I. Jordan, and Y. Weiss (2001) “On Spectral Clustering:
- Shi, J., and J. Malik (1997) “Normalized Cuts and Image Segmentation”