標籤傳播演算法(Label Propagation)及 Python 實現

發表於2017-08-31

眾所周知,機器學習可以大體分為三大類:監督學習、非監督學習和半監督學習。監督學習可以認為是我們有非常多的labeled標註資料來train一個模型,期待這個模型能學習到資料的分佈,以期對未來沒有見到的樣本做預測。那這個效能的源頭–訓練資料,就顯得非常感覺。你必須有足夠的訓練資料,以覆蓋真正現實資料中的樣本分佈才可以,這樣學習到的模型才有意義。那非監督學習就是沒有任何的labeled資料,就是平時所說的聚類了,利用他們本身的資料分佈,給他們劃分類別。而半監督學習,顧名思義就是處於兩者之間的,只有少量的labeled資料,我們試圖從這少量的labeled資料和大量的unlabeled資料中學習到有用的資訊。

一、半監督學習

半監督學習(Semi-supervised learning)發揮作用的場合是:你的資料有一些有label,一些沒有。而且一般是絕大部分都沒有,只有少許幾個有label。半監督學習演算法會充分的利用unlabeled資料來捕捉我們整個資料的潛在分佈。它基於三大假設:

  1. Smoothness平滑假設:相似的資料具有相同的label。
  2. Cluster聚類假設:處於同一個聚類下的資料具有相同label。
  3. Manifold流形假設:處於同一流形結構下的資料具有相同label。

例如下圖,只有兩個labeled資料,如果直接用他們來訓練一個分類器,例如LR或者SVM,那麼學出來的分類面就是左圖那樣的。如果現實中,這個資料是右圖那邊分佈的話,豬都看得出來,左圖訓練的這個分類器爛的一塌糊塗、慘不忍睹。因為我們的labeled訓練資料太少了,都沒辦法覆蓋我們未來可能遇到的情況。但是,如果右圖那樣,把大量的unlabeled資料(黑色的)都考慮進來,有個全域性觀念,牛逼的演算法會發現,哎喲,原來是兩個圈圈(分別處於兩個圓形的流形之上)!那演算法就很聰明,把大圈的資料都歸類為紅色類別,把內圈的資料都歸類為藍色類別。因為,實踐中,labeled資料是昂貴,很難獲得的,但unlabeled資料就不是了,寫個指令碼在網上爬就可以了,因此如果能充分利用大量的unlabeled資料來輔助提升我們的模型學習,這個價值就非常大。

cpp_py_medium

半監督學習演算法有很多,下面我們介紹最簡單的標籤傳播演算法(label propagation),最喜歡簡單了,哈哈。

二、標籤傳播演算法

標籤傳播演算法(label propagation)的核心思想非常簡單:相似的資料應該具有相同的label。LP演算法包括兩大步驟:1)構造相似矩陣;2)勇敢的傳播吧。

2.1、相似矩陣構建

LP演算法是基於Graph的,因此我們需要先構建一個圖。我們為所有的資料構建一個圖,圖的節點就是一個資料點,包含labeled和unlabeled的資料。節點i和節點j的邊表示他們的相似度。這個圖的構建方法有很多,這裡我們假設這個圖是全連線的,節點i和節點j的邊權重為:

cpp_py_medium

這裡,α是超參。

還有個非常常用的圖構建方法是knn圖,也就是隻保留每個節點的k近鄰權重,其他的為0,也就是不存在邊,因此是稀疏的相似矩陣。

2.2、LP演算法

標籤傳播演算法非常簡單:通過節點之間的邊傳播label。邊的權重越大,表示兩個節點越相似,那麼label越容易傳播過去。我們定義一個NxN的概率轉移矩陣P:

cpp_py_medium

Pij表示從節點i轉移到節點j的概率。假設有C個類和L個labeled樣本,我們定義一個LxC的label矩陣YL,第i行表示第i個樣本的標籤指示向量,即如果第i個樣本的類別是j,那麼該行的第j個元素為1,其他為0。同樣,我們也給U個unlabeled樣本一個UxC的label矩陣YU。把他們合併,我們得到一個NxC的soft label矩陣F=[YL;YU]。soft label的意思是,我們保留樣本i屬於每個類別的概率,而不是互斥性的,這個樣本以概率1只屬於一個類。當然了,最後確定這個樣本i的類別的時候,是取max也就是概率最大的那個類作為它的類別的。那F裡面有個YU,它一開始是不知道的,那最開始的值是多少?無所謂,隨便設定一個值就可以了。

千呼萬喚始出來,簡單的LP演算法如下:

  1. 執行傳播:F=PF
  2. 重置F中labeled樣本的標籤:FL=YL
  3. 重複步驟1)和2)直到F收斂。

步驟1)就是將矩陣P和矩陣F相乘,這一步,每個節點都將自己的label以P確定的概率傳播給其他節點。如果兩個節點越相似(在歐式空間中距離越近),那麼對方的label就越容易被自己的label賦予,就是更容易拉幫結派。步驟2)非常關鍵,因為labeled資料的label是事先確定的,它不能被帶跑,所以每次傳播完,它都得迴歸它本來的label。隨著labeled資料不斷的將自己的label傳播出去,最後的類邊界會穿越高密度區域,而停留在低密度的間隔中。相當於每個不同類別的labeled樣本劃分了勢力範圍。

2.3、變身的LP演算法

我們知道,我們每次迭代都是計算一個soft label矩陣F=[YL;YU],但是YL是已知的,計算它沒有什麼用,在步驟2)的時候,還得把它弄回來。我們關心的只是YU,那我們能不能只計算YU呢?Yes。我們將矩陣P做以下劃分:

cpp_py_medium

這時候,我們的演算法就一個運算:

cpp_py_medium

迭代上面這個步驟直到收斂就ok了,是不是很cool。可以看到FU不但取決於labeled資料的標籤及其轉移概率,還取決了unlabeled資料的當前label和轉移概率。因此LP演算法能額外運用unlabeled資料的分佈特點。

這個演算法的收斂性也非常容易證明,具體見參考文獻[1]。實際上,它是可以收斂到一個凸解的:

cpp_py_medium

所以我們也可以直接這樣求解,以獲得最終的YU。但是在實際的應用過程中,由於矩陣求逆需要O(n3)的複雜度,所以如果unlabeled資料非常多,那麼I – PUU矩陣的求逆將會非常耗時,因此這時候一般選擇迭代演算法來實現。

三、LP演算法的Python實現

Python環境的搭建就不囉嗦了,可以參考前面的部落格。需要額外依賴的庫是經典的numpy和matplotlib。程式碼中包含了兩種圖的構建方法:RBF和KNN指定。同時,自己生成了兩個toy資料庫:兩條長形形狀和兩個圈圈的資料。第四部分我們用大點的資料庫來做實驗,先簡單的視覺化驗證程式碼的正確性,再前線。

演算法程式碼:

測試程式碼:

該註釋的,程式碼都註釋的,有看不明白的,歡迎交流。不同迭代次數時候的結果如下:

cpp_py_medium

是不是很漂亮的傳播過程?!在數值上也是可以看到隨著迭代的進行逐漸收斂的,迭代的數值變化過程如下:

四、LP演算法MPI並行實現

這裡,我們測試的是LP的變身版本。從公式,我們可以看到,第二項PULYL迭代過程並沒有發生變化,所以這部分實際上從迭代開始就可以計算好,從而避免重複計算。不過,不管怎樣,LP演算法都要計算一個UxU的矩陣PUU和一個UxC矩陣FU的乘積。當我們的unlabeled資料非常多,而且類別也很多的時候,計算是很慢的,同時佔用的記憶體量也非常大。另外,構造Graph需要計算兩兩的相似度,也是O(n2)的複雜度,當我們資料的特徵維度很大的時候,這個計算量也是非常客觀的。所以我們就得考慮並行處理了。而且最好是能放到叢集上並行。那如何並行呢?

對演算法的並行化,一般分為兩種:資料並行和模型並行。

資料並行很好理解,就是將資料劃分,每個節點只處理一部分資料,例如我們構造圖的時候,計算每個資料的k近鄰。例如我們有1000個樣本和20個CPU節點,那麼就平均分發,讓每個CPU節點計算50個樣本的k近鄰,然後最後再合併大家的結果。可見這個加速比也是非常可觀的。

模型並行一般發生在模型很大,無法放到單機的記憶體裡面的時候。例如龐大的深度神經網路訓練的時候,就需要把這個網路切開,然後分別求解梯度,最後有個leader的節點來收集大家的梯度,再反饋給大家去更新。當然了,其中存在更細緻和高效的工程處理方法。在我們的LP演算法中,也是可以做模型並行的。假如我們的類別數C很大,把類別數切開,讓不同的CPU節點處理,實際上就相當於模型並行了。

那為啥不切大矩陣PUU,而是切小點的矩陣FU,因為大矩陣PUU沒法獨立分塊,並行的一個原則是處理必須是獨立的。 矩陣FU依賴的是所有的U,而把PUU切開分發到其他節點的時候,每次FU的更新都需要和其他的節點通訊,這個通訊的代價是很大的(實際上,很多並行系統沒法達到線性的加速度的瓶頸是通訊!線性加速比是,我增加了n臺機器,速度就提升了n倍)。但是對類別C也就是矩陣FU切分,就不會有這個問題,因為他們的計算是獨立的。只是決定樣本的最終類別的時候,將所有的FU收集回來求max就可以了。

所以,在下面的程式碼中,是同時包含了資料並行和模型並行的雛形的。另外,還值得一提的是,我們是迭代演算法,那決定什麼時候迭代演算法停止?除了判斷收斂外,我們還可以讓每迭代幾步,就用測試label測試一次結果,看模型的整體訓練效能如何。特別是判斷訓練是否過擬合的時候非常有效。因此,程式碼中包含了這部分內容。

好了,程式碼終於來了。大家可以搞點大資料庫來測試,如果有MPI叢集條件的話就更好了。

下面的程式碼依賴numpy、scipy(用其稀疏矩陣加速計算)和mpi4py。其中mpi4py需要依賴openmpi和Cpython,可以參考我之前的部落格進行安裝。

五、參考資料

[1]Semi-SupervisedLearning with Graphs.pdf

相關文章