幾年前我寫過一個Service Ticket自動歸類程序。根據現成的指導寫一個程序容易,而搞明白其背後的算法原理,用了好久。算法
不過想明白以後發現,不只對這一個模型,並且對於Machine Learning的通常方法的理解,都有了提高。數據庫
在工做中學習Machine Learning,這種問題->模型->算法->數學原理(公式)的認知過程至關高效。微信
需求
當時的任務很簡單:把內容相近的Service Ticket放到一塊兒(造成一個「簇」),每簇中的元素數量最好不要超過某個預約義的閾值。
ide
沒有事先定義「簇」的類型,可見這是一個典型的聚類的問題。函數
說到聚類,最多見的模型固然是KMeans。學習
不過若是使用KMeans的話,須要指定K的值,也就是要在訓練前指定最後的結果被分爲幾「簇」。而同時KMeans的結果並不能保證每簇中的個體數量低於某個量值。spa
所以,KMeans並不符合這個任務的要求。.net
那應該用什麼模型呢?通過一通Google,以及請教公司內部的數據科學家,肯定了使用:基於圖切割的譜聚類(Spectral Clustering)。3d
算法實現
肯定了模型就好辦,根據《A Tutorial on Spectral Clustering》和專家意見,按照如下步驟實現了這個程序:orm
【步驟1】 將每一個Service Ticket轉化爲一個詞袋,並通過normalization和去停用詞操做。
【步驟2】生成一張圖G = <V,E>,每一個詞袋是其中一個頂點(vertex),每兩個頂點之間的邊則是這兩個詞袋之間的Jaccard距離:
Jaccard_Distance = 1 – (|A ∩ B|/ |A U B|)
這樣一張圖用矩陣 C = (cij) 存儲; 其中:
cij =Jaccard_Distance(wordbag_i, wordbag_j)
【步驟3】肯定距離閾值threshold_C, 將全部cij > threshold_C的兩個頂點 i 和 j 視爲斷開。據此將完整的G分割爲若干連通圖{G1, G2, … , Gn}。
計算每個子圖的radius (最遠邊緣節點到中心節點的距離) 和size(包含頂點數)。
若是(cluster_radius<= threshold_radius) && (cluster_size <= threshold_size), 則該連通圖自己就是一個獨立的簇,不然,對該簇進行下一個步驟。
【步驟4】圖切割:
4.1 將待切割圖G切割爲2個子圖Gs1 和Gs2, 達到Gs1和Gs2之間距離儘可能大而兩個子圖內部個節點間距離儘可能小的目的。具體切割過程以下:
4.1.1 構造一個和C同等大小的矩陣W = (wij)
wij = exp(-||xi - xj||2/σ2) ; 這裏用到了高斯類似度函數(Gaussian similarity function),其中σ 是一個用來控制變換速度的參數。
具體到本例子, ||xi-xj||就用wordbag_i和wordbag_j的Jaccard_distance來計算便可。也就是說||xi-xj|| = cij。
4.1.2 構造一個對角矩陣D:
對角項 di = Σj wij
4.1.3 令 L = D - W,構造等式:
Lv = (D-W)v = λv,其中λ爲常數,v爲向量。
4.1.4 計算上述等式的倒數第二小的特徵值所對應特徵向量f。
設被分割圖 G一共包含n個頂點,則其由一個nxn矩陣表達,所以得出的特徵向量f也是n維向量。f中的每一維表明一個頂點(即一個service ticket)。
f = (f1, f2, …, fn);
IF fi >= 0 THEN vertex_i 屬於 Gs1
IF fi < 0 THEN vetex_i 屬於 Gs2
這樣就把G分紅了兩部分:Gs1和Gs2。
4.2 計算Gs1和Gs2的大小和半徑,而後
IF ((cluster_radius > threshold_radius) && (cluster_size > threshold_size))
THEN
重複 4.1,直到全部被分割的結果知足上述條件爲止。
【步驟5】將【步驟4】運用到全部【步驟3】中全部連通圖{G1, G2, … , Gn}上。
運行結果
當時這個程序是用內嵌R的PostgreSQL編寫的,由於全部Training Data都存儲在數據庫裏,因此要用一種可以方便操做數據庫的語言。
並且總共只有40多萬條(平均每條不超過1K),用SQL+R也並非很慢。
R的矩陣運算功能使得整個程序編寫至關容易,將threshold_size設爲2000,threshold_radius設爲50以後,總體運行結果還不錯。最後獲得了17個簇,人工看結果也比較reasonable。
被質疑的算法
不過在團隊內部分享算法實現的時候,有同事說:這不就是算詞頻嘛。態度頗爲不屑。
當時的感受是有些無言以對。
詞袋模型(用詞袋來表示Service Ticket)自己確實是沒有考慮單詞出現順序對文檔含義的影響,並且採用Jaccard Distance計算的是兩個詞袋之間單詞交集和並集的比例,也確實和詞語出現的次數相關。
可是若是說譜聚類就是算詞頻,則相差太遠了。
但是具體差在哪裏呢?好像又有點說不清楚。只是朦朧的以爲,若是不是採用了類似度矩陣,若是不是進行了矩陣運算,則根本得不出「簇」的結果——
要算單個文檔(service ticket)的詞頻或者整體詞頻都很容易。可是若是不是矩陣運算,又怎麼可能把這些文檔歸爲若干簇,使得每個簇內文檔相互之間的距離儘可能小,而簇之間的距離儘可能大呢?
模模糊糊有如上這樣的想法。可是,其實本身並不明白,即便採用了譜聚類,又是怎麼能作到不一樣的簇高內聚低耦合的。
還有,爲何要作那麼一大堆奇怪的矩陣變換?爲何要把一個好好的類似度矩陣扭曲成很奇怪的樣子?這樣作究竟是爲何呢?
算法原理
回頭從理論層面看譜聚類的數學原理,纔對上述的疑問有了一點點感悟。
【基本原理】
譜聚類的目的就是要找到一種合理的分割,使得分割後造成若干子圖,鏈接不一樣的子圖的邊的權重儘量低,即「截」最小,同一子圖內的邊的權重儘量高。
【構造矩陣】
步驟 4.1.1 中根據對稱陣C構造的矩陣W,也是一個對稱陣。它描述了G中各節點間的類似度。
NOTE 1: 在步驟 2中構造的矩陣 C = (cij) 中,cij表示點 i 到點 j 的距離,cij值越大說明距離越遠。可是到了矩陣W中的節點:wij = exp(-(cij)2/σ2)。cij 越大,則wij越小。也就是說W中的節點wij 的數值越小,它所表示的對應的兩個點之間的距離也就越大。
步驟 4.1.2 則是構造了W的對角矩陣D。
步驟 4.1.3 中,由類似度矩陣W和其對角矩陣D,咱們構造了一個新的矩陣:
L= D-W
L是一個拉普拉斯(Laplacian)矩陣,稱做非規範化的拉普拉斯矩陣(Unnormalized Laplacian Matrix)。
【拉普拉斯矩陣性質】
因拉普拉斯矩陣性質得知:
(i) L是對稱半正定矩陣;
(ii) Laplacian矩陣L的最小特徵值是0,相應的特徵向量是I;
(iii) Laplacian矩陣L有n個非負實特徵值:0 = λ1 <= λ2 <= … <= λn
又由於L = D - W,對於任一實向量f,均可以作以下計算:
所以,對於任一實向量f都有下面的式子成立:
【圖分割和矩陣運算的關係】
如今咱們回過頭來,看圖切割這件事情。
假設咱們把L所對應的原圖進行圖切割,成兩個新的圖:A和。
也就是說,以前n x n矩陣L所對應的n個頂點被分爲了兩部分,一部分屬於A,另外一部分屬於它的補。
到底哪些點被分給了A,哪些店被分給了它的補呢?咱們能夠用一個向量來表示。
假設存在一個向量f = (f1, f2, ..., fn)', 其中不一樣維度的值能夠指示該維度對應的頂點屬於新分出來的哪一個子圖。具體以下:
將f帶入到上面(iii)中的公式:,又由於當i,j同屬於A或者
時,fi – fj 爲0。
所以,f'Lf 就能夠被轉化爲以下形式:
<式子1>
取出上面<式子1>中的後一部分:
其中:k表示不一樣類別的個數,這裏k=2。表示子圖A和
之間連通邊的權重。
這裏的定義的Cut函數,又能夠被稱爲「截函數」。
當一個圖被劃分紅爲兩個子圖時,「截」即指子圖間的鏈接密度。即被切割後的子圖之間,本來是連通狀態(但在切割時被截斷)的邊的值加權和。
咱們要找到一種分割,使得分割後,鏈接被分割出來的兩個子圖的邊的權重儘量低,即「截」最小。
所以,Cut函數就是咱們求取圖切割方法的目標函數。
由於在這個例子裏面,Cut函數中的值是就是wij (頂點i 位於A, 頂點 j 位於)。根據前面的NOTE 1可知wij 越小,則對應的兩點間的距離越大。
咱們既然要讓切割出來的結果是兩個子圖之間的加權距離儘可能大,那麼天然,咱們就要讓的值儘可能小。
由此可知,咱們要作的就是最小化Cut函數。
咱們再將Cut函數帶回到<式子1>中,獲得結果以下:
其中|V|表示的是頂點的數目,對於肯定的圖來講是個常數。
由上述的推導可知,由f’Lf推導出了RatioCut函數。到此,咱們得出了:
由於Cut函數和RatioCut函數相差的是一個常數,所以求Cut的最小值就是求RatioCut的最小值。
又由於|V|是常數,所以咱們求RatioCut函數的最小值就是求f’Lf的最小值。
到此時,圖切割問題,就變成了求f’Lf的最小值的問題。
【經過求f’Lf的最小值來切割圖】
假設λ是Laplacian矩陣L的特徵值,f是特徵值λ對應的特徵向量,則有:Lf = λf
在上式的兩端同時左乘f’,獲得:
f’Lf = λf’f
已知 ||f|| = n1/2 則 f’f = n,上式能夠轉化爲:f’Lf = λn
既然咱們的目標是求 ,那麼咱們只需求得最小特徵值λ。
由Laplacian矩陣的性質可知,Laplacian矩陣的最小特徵值爲0,相應的特徵向量是I。
向量I中全部維度 都爲1,沒法將對應頂點分爲兩份。所以咱們用L第二小的特徵值(也就是最小的非零特徵值)來近似取RatioCut的最小值。(本天然段描述純爲筆者的理解,此處背後實際的理論依據是Rayleigh-Ritz理論。)
咱們先求出L第二小的特徵矩陣f,再經過以下變換,將f轉化爲一個離散的指示向量:
對於求解出來的特徵向量f = (f1,f2,…, fn)’ 中的每個份量fi,根據每一個份量的值來判斷對應的點所屬的類別:
這也就是步驟4.1.4中描述的內容。
【從切割成2份到切割成k份的推演】
若是不是要一次將圖切成2份,而是要切成k份,那麼就要先求L的前k小個特徵向量。
若前k個特徵向量爲,這樣便由特徵向量構成以下的特徵向量矩陣:
將特徵向量矩陣中的每一行做爲一個樣本,利用K-Means聚類方法對其進行聚類。
即對n個k維向量進行聚類,將其聚爲k個簇。聚類完成以後,若是特徵矩陣中的第i個k維向量被彙集到了第j個簇中,則本來圖中的第i個點就被彙集到了第j個簇中。
以上,就是根據非規範化拉普拉矩陣進行基於圖切割的譜聚類的算法原理。
【規範化拉普拉斯矩陣】
L 也能夠被規範化,D-1/2L D-1/2 就是L的規範化形式。
L' = D-1/2L D-1/2 又稱爲規範化的拉普拉斯矩陣(Normalized Laplacian Matrix)。
對於規範化的拉普拉斯矩陣,不能直接求其特徵值和特徵向量來作圖切割。不過大致過程和思路與非規範化拉普拉斯矩陣一致,在此不贅述。
本文分享自微信公衆號 - 悅思悅讀(yuesiyuedu)。
若有侵權,請聯繫 support@oschina.cn 刪除。
本文參與「OSC源創計劃」,歡迎正在閱讀的你也加入,一塊兒分享。