譜聚類的R解釋

注,有疑問 加QQ群..[174225475].. 共同探討進步
有償求助請 出門左轉 door , 合作愉快

1. 相關概念科普

度矩陣

度矩陣為對角矩陣,對角線上的值表示 與該點 有來往的 其他點的個數 即度 為 與節點 相連的 個數

鄰接矩陣

鄰接矩陣 表示圖上 各點之間 是否有聯系或者聯系程度, 可以是 1/0 也可以是 具體權值


laplas1


laplas2

拉普拉斯矩陣

圖論中的的 拉普拉斯矩陣(也被稱為導納矩陣/吉爾霍夫矩陣/離散拉普拉斯)是圖的矩陣表示. 它是 度矩陣 和 鄰接矩陣 的差. 拉普拉斯矩陣 結合 吉爾霍夫理論 可以用來計算圖的最小生成樹的個數。
拉普拉斯矩陣還可用來尋找圖的其他屬性: 譜圖理論(spectral graph theory)
黎曼幾何的Cheeger不等式有涉及了拉普拉斯矩陣的離散模擬. 這或許是譜圖理論中最重要的定理也是在算法應用中最有用的facts.它通過拉普拉斯矩陣的第二特征值來近似圖的最小割
譜的定義 就是:
方陣作為線性算子,它的所有特征值的全體 統稱方陣的
方陣的譜半徑為最大的特征值;
矩陣A的譜半徑:(A^{T} \cdot A)的最大特征值。
其實,這里譜的本質是偽逆,是SVD中奇異值的平方

2. 譜聚類的基本思想

2.1 聚類與圖論

所謂聚類(Clustering), 就是要把一堆樣本合理地分成兩份或者K?份. 從圖論的角度來說,聚類的問題就相當于一個圖的分割問題. 即給定一個圖G = (V, E)?, 頂點集V?表示各個樣本,帶權的邊表示各個樣本之間的相似度,譜聚類的目的便是要找到一種合理的分割圖的方法,使得分割后形成若干個 子圖,連接不同 子圖 的邊的權重(相似度)盡可能低,同 子圖內 的邊的權重(相似度)盡可能高.被割掉各邊的權值和越小代表被它們連接的子圖之間的相似度越小,隔得越遠. 物以類聚,人以群分,相似的在一塊兒,不相似的彼此遠離
至于如何把圖的頂點集分割/切割為不相交的子圖有多種辦法,如

  • cut/Ratio Cut
  • Normalized Cut
  • 不基于圖,而是轉換成SVD能解的問題

2.2 最小割

在將數據從點集的結構轉換為了圖的結構后,我們可以引入更多圖論中的概念來幫助理解聚類的本質. 比如說最小割的概念(Minimum cut)
最小割是指去掉圖中的一些帶權邊,在使得圖從聯通圖變為不聯通圖的前提下,盡可能的讓去掉的邊權值之和盡可能小。對于數據的相似性圖來說,最小割就是要去除一些很弱的相似性,把數據點從一個互相連接的整體分為兩個或者多個獨立的部分,這其實就是一個聚類的過程。去除的權值就是聚類后不同組別間的相似程度,我們希望這個值盡可能的小,也就是希望不同組別之間的差距盡可能的大
不過,僅僅是用最小割來聚類存在著一些缺陷,因為我們只考慮了不同類的點之間相似度要小,而一個好的聚類還要具有同一類點相似度大的特征。比如下圖就是一個例子,一個好的聚類應該是在綠線處分割整個圖,但使用最小割卻會割在紅色的位置

specc3

如下圖所示,每個頂點是一個樣本,共有7個樣本(實際中一個樣本是特征向量). 邊的權值就是樣本之間的相似度. 然后我們需要分割,分割之后要使得連接不同組之間的邊的權重盡可能低(組間相似度小),組內部的邊的權重盡可能高(組內相似度高)


specc1

比如我們把中間的邊去掉,就滿足上面的簇間相似性最小,簇內相似性最大。如下圖


specc2

3. 算法步驟

譜聚類算法主要有下面幾部分:

3.1 未正則拉普拉斯矩陣 的譜聚類算法

3.1.1 計算得到圖的鄰接矩陣 W,以及拉普拉斯矩陣 L

給定樣本的原始特征,我們需要計算兩兩樣本之間的相似度值,才能構造出鄰接矩陣W . 我們一般使用高斯核函數來計算相似度。公式如下:

S(x,y)=e^{-\frac{||x-y||^{2}}{2\sigma^{2}}}

S(x,y)=e^{-{\frac{\sqrt{\sum_{i=1}^{k}\left(x_{i}-y_{i}\right)^{2}}}{2\sigma^2}}}

如果樣本x,y是對應數據集dt的第i,j行,則上述公式中的

\begin {aligned} \sqrt{\sum_{i=1}^{k}\left(x_{i}-y_{i}\right)^{2}}&= \sqrt{\sum_{i,j=1}^{n}(dt[x,]-dt[y,])^2} \\\ &= \sqrt{\sum_{i,j=1}^{n}(dt[i,]-dt[j,]) * t(dt[i,]-dt[j,])} \\\ &=dist(dt) \end {aligned}

高斯核相似度公式用 R 來表達:

S(dt) = exp(-(dist(dt)^2)/(2*sigma^2))

其中xy 是兩個樣本(行向量),x_{i} y_{i}是樣本x,y對應的第i個原始特征向量,我們可以計算出它們二者之間的相關性(高斯核). 注意,鄰接矩陣的對角線元素一致等于零. 這樣我們就得到了鄰接矩陣W

拉普拉斯矩陣 L = D - W, 其中D為上面圖的度矩陣,度是圖論中的概念,也就是矩陣E行或列的元素之和。后面我們就要基于矩陣L來進行研究

3.1.2 聚類劃分準則

關于劃分準則的問題是聚類技術中的核心。譜聚類被看作屬于圖論領域的問題,那個其劃分也會和邊的權重有關

準則1:最小化進行分割時去掉的邊的權重之和
cut (A_{1} \ldots A_{k}) = \frac {1}{2} \cdot \sum_{i=1}^{k} W (A_{i},\overline{A_{i})}
這個準則直觀地讓分割之后簇之間的相似度最小了。但是有個問題,就是這個準則沒有考慮到簇的大小,容易造成一個樣本就能分為一個簇。為了避免這個問題,有了下面的準則
準則2:考慮簇的大小
RationCut\left(A_{1},\ldots ,A_{k} \right)=\frac{1}{2} \cdot \sum_{i=1}^{k} \frac{W\left(A_{i},\overline{A_{i}}\right)} {||A_{i}||}

準則2相比于準則1的改進,類似于C4.5中的增益比率和ID3的信息增益的改進。在RatioCut中,如果某一組包含的頂點數越少,那么它的值就越大。在一個最小化問題中,這相當于是懲罰,也就是不鼓勵將組分得太小。現在只要將最小化RatioCut解出來,分割就完成了。不幸的是,這是個NP難問題。想要在多項式時間內解出來,就要對這個問題作一個轉化了。在轉化的過程中,就用到上面提到的L的那一組性質,經過若干推導,最后可以得到這樣的一個問題
\begin {aligned} \min_{H \in \mathbb{R}^{n \cdot k}} (Tr(H^{T}LH)) \\\ s.t. H^{T}H=I \end {aligned}
但到了這關鍵的最后一步,咱們卻遇到了一個比較棘手的問題,即由之前得到的拉普拉斯矩陣的性質L最小特征值為0,對應的特征值為1.其不滿足f1正交的條件,那該怎么辦呢?根據論文“A Tutorial on Spectral Clustering”中所說的Rayleigh-Ritz 理論,我們可以取第2小的特征值,以及對應的特征向量v
更進一步,由于實際中,特征向量v里的元素是連續的任意實數,所以可以根據v是大于0,還是小于0對應到離散情況下的f=(f_{1},\ldots ,f_{n}) \prime \in \mathbb{R}^{n\cdot k},決定f是取\sqrt{\frac{|A|} {|\overline{A}|}}還是取 -\sqrt{\frac{|A|} {|\overline{A}|}} .而如果能取v的前k個特征向量,進行Kmeans聚類,得到K個簇,便從二聚類擴展到了K聚類的問題 ( \overline{A}表示A的補集)
而所要求的這前K個特征向量就是拉普拉斯矩陣的特征向量(計算拉普拉斯矩陣的特征值,特征值按照從小到大順序排序,特征值對應的特征向量也按照特征值遞增的順序排列,取前K個特征向量,便是我們所要求的前K個特征向量)!
所以,問題就轉換成了:求拉普拉斯矩陣的前K個特征值,再對前K個特征值對應的特征向量進行 Kmeans聚類。而兩類的問題也很容易推廣到K類的問題,即求特征值并取前K個最小的,將對應的特征向量排列起來,再進行Kmeans聚類. 兩類分類和多類分類的問題,如出一轍
RatioCut巧妙地把一個NP難度的問題轉換成拉普拉斯矩陣特征值(向量)的問題,將離散的聚類問題松弛為連續的特征向量,最小的系列特征向量對應著圖最優的系列劃分方法。剩下的僅是將松弛化的問題再離散化,即將特征向量再劃分開,便可以得到相應的類別。不能不說妙哉!

3.1.3 求出L的前k個特征值及對應的特征向量

在本文中,除非特殊說明,否則“前k個”指按照特征值的大小從小到大的順序)以及對應的特征向量
PS: L=D-W是計算前 k小的特征向量,如果是L=W-D則是計算前 k

3.1.4 根據新生成的特征矩陣進行kmeans聚類

把這k個特征(列)向量排列在一起組成一個n \cdot k的矩陣,將其中每一行看作k維空間中的一個向量,并使用Kmeans算法進行聚類. 聚類的結果中每一行所屬的類別就是原來 Graph 中的節點亦即最初的n個數據點分別所屬的類別

3.1.5 總結一下完整的譜聚類算法的流程

  • 確認輸入參數:一個描述數據相似性圖的鄰接矩陣W,和聚類的目標類數目k
  • 計算度矩陣 D和 拉普拉斯矩陣 L
  • 計算特征值方程L\cdot y = \lambda \cdot D \cdot y的前k個特征向量,記為y_{1} \ldots y_{k}
  • 通過 y_{1} \ldots y_{k}按列排成矩陣 Y \in \mathbb{R}^{n \cdot k}
  • Y 的第 i行的行向量記為 x_{i} \prime (i \leq n)
  • x_{i} \prime 進行 kmeans 聚類
  • x_{i} \prime 的類別分配給 x_{i}, 即 class(x_{i})=class(x_{i} \prime)
  • 輸出聚類結果
    整個過程都只用到了包括求解特征值等基本線性代數運算,因此譜聚類是一種推導有些繁雜,但是實現很簡單的聚類算法

3.2 正則的拉普拉斯矩陣 的譜聚類算法

3.2.1 對稱拉普拉斯矩陣的譜聚類算法

  • 將 為正則拉普拉斯中的 L = D -W 替換成 L=D^{-\frac{1}{2}}\cdot(D-W)\cdot D^{\frac{1}{2}}
  • 同時在完成k維特征向量提取之后,進行kmeans聚類之前,添加一步:
    k維 特征向量對應的 各樣本 進行單位化使得|y_{i}|=1
    mx[i,]=\frac{mx[i,]} {\sqrt{\sum_{i=1}^{k}mx[i,]^2}}
mx2 <- mx1/sqrt(rowSums(mx1^2))
  • 然后在此基礎上繼續 kmeans 聚類

下面是在參加某賽事時正則化譜聚類實現步驟

library(data.table)
library(dplyr)
library(ggplot2)
library(geosphere)
setwd('xxx/spec')
train1 <- fread('train.csv',header = FALSE,encoding = 'UTF-8')
test1 <- fread('test.csv',header = FALSE,encoding = 'UTF-8')
dt_all <- rbind(train1,test1)

dist2 = distm(dt_all[,c('longitude','latitude')])/1000
lamb1 <- sqrt(ncol(dt_all[,c('longitude','latitude')]))/sqrt(2)
W1 <- exp(-dist2^2/(2*lamb1^2))
rm(dist2)
W1[W1<1e-15]=0
W2 <- as(W1,'sparseMatrix')
diag1 <- rowSums(W1)
rm(W1)
D1 <- Matrix::sparseMatrix(i=seq(1,length(diag1)),
                           j=seq(1,length(diag1)),
                           x=diag1) # 度矩陣
D2 <- Matrix::sparseMatrix(i=seq(1,length(diag1)),
                           j=seq(1,length(diag1)),
                           x=diag1^(-1/2))
D3 <- Matrix::sparseMatrix(i=seq(1,length(diag1)),
                           j=seq(1,length(diag1)),
                           x=diag1^(1/2))
L1 <- D1-W2
L2 <- D2%*%L1%*%D3 #拉普拉斯矩陣
rm(L1,D1,D2,D3)
eig1 <- eigen(L2)
mx1 <- eig1$vectors[,-c(1:(ncol(eig1$vectors)-k))]
mx2 <- mx2/sqrt(rowSums(mx1^2))
# find best k value for kmeans
library(factoextra)
fviz_nbclust(area1, kmeans, method = "silhouette",k.max = 50)
# the larger the better for result value(this formu is friendly for bigdata)
kmean1 <- kmean(mx2,49)
# plot
ggplot()+
  geom_point(data=dt_all,aes(x=longitude,y=latitude,color=as.factor(kmean1$cluster)))+
  geom_text(data=NULL,aes(x=kmean1$centers[,1],
                          y=kmean1$centers[,2],
                          label=row.names(kmean1$centers)))+
  theme(legend.position = 'none')

由于樣本huge,eigen時cost too much, so kmeans替代,以上代碼作為R實現步驟留念,指不定哪天R真正解決了分布式問題,譜聚類就能跟kmeans一樣高效了
Kernlab包中有specc函數可實現此功能,但礙于樣本量巨大,2個小時沒出結果也只能作罷

3.2.2 隨機游走拉普拉斯矩陣 的譜聚類算法

它的變化就是將 L 矩陣的L=D-W計算方式改為L=D^{-1}(D-W),其他步驟與 未正則拉普拉斯矩陣 的譜聚類算法相同

4. 參考文獻與推薦閱讀

最后編輯于
?著作權歸作者所有,轉載或內容合作請聯系作者
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發布,文章內容僅代表作者本人觀點,簡書系信息發布平臺,僅提供信息存儲服務。

推薦閱讀更多精彩內容

  • 寫在之前 因簡書導入公式很麻煩,如果想獲得更好的觀看體驗請移步https://www.zybuluo.com/ha...
    hainingwyx閱讀 6,929評論 2 13
  • 考試說明 注重基礎知識和概念的理解,因此解題中的計算過程不會很復雜,但是會有推公式的過程。本課程的重點知識包括:貝...
    藝術叔閱讀 2,912評論 0 3
  • k均值聚類 算法邏輯 先進行初始化中心點和每個點的歸屬類 根據每個點與原中心點的距離找到最近的中心點作為歸屬類 根...
    在河之簡閱讀 2,659評論 0 1
  • 數學是計算機技術的基礎,線性代數是機器學習和深度學習的基礎,了解數據知識最好的方法我覺得是理解概念,數學不只是上學...
    闖王來了要納糧閱讀 22,848評論 2 48
  • 逝去的靈魂,假如你還活著,請愿諒我,我不是故意要這樣做,只是生活的無奈迫使我這樣的過,失去了你,我不知道我的明天會...
    三小姐的悲哀閱讀 308評論 1 5