IA9b - K-means分群與EM算法: 實作

這一篇文章延續了上一篇IA9a的內容,但側重在python的實作,所以所有的節數、圖案以及公式編號都會依照IA9a的編號接序下來,所以重複的內容就直接引用,不在這裡重新贅述。

四、實作EM

4.1 高斯混合分佈

讓我們從1.1節的協方差矩陣開始,生成的圖形就如圖4 (腳本內加了seed random方便我們每次追蹤),另外也看到了執行5次K-means算法後 (再多次也不會變了) 得到的分群結果如圖5,這顯然與我們的預期有極大的落差!
 但我們將按照3.3結給出EM算法的偽代碼,假設資料群是高斯混合分佈的形式,重新執行一遍分群,我們將看到EM算法能很好的分出我們預期的兩群的結果。我們預計會有兩群,所以k=1,2,且第一步需要初始化參數組θ={μk,Σk,πk}。初始化的過程是給定一個起始點,原則上隨機選擇的方式是合理的,不過為了計算上方便,可以讓初始的協方差矩陣都為單位矩陣,πk則為每個群均分 (這裡就是每個都是0.5),如下代碼
# Initializing parameters
sigma1,sigma2 = np.eye(2),np.eye(2)
pi1 = 0.5
pi2 = 1-pi1
N = len(cluster)
完成初始的參數選擇後,我們用偽代碼的第二步,也就是E-step計算置信度γ(znk)。這裡我將Eq. (10)列出來方便解說 γ(znk)=πkN(x|μk,Σk)2k=1πkN(x|μk,Σk). 因為我們是假設兩群都是高斯分佈,所以對第一個群而言的分子就是
# Starting E-step: Calculating responsibilities
# Numerator for k=1
k1 = pi1*multivariate_normal.pdf(cluster,p1,sigma1)
直接透過python腳本我們很容易理解了分子的意義便是計算每個資料點分別對應到{μ1,Σ1}的高斯分佈的機率密度,所以愈靠近k=1群的點,它分子的值就愈大。接著計算對k=2以及分母並完整的寫下Eq. (10)的結果
k2 = pi2*multivariate_normal.pdf(cluster,p2,sigma2)
gamma1 = k1/(k1+k2)
gamma2 = k2/(k1+k2)
不難理解Eq. (10)的分母就是將兩個分子結果相加即可,最後的gamma1gamma2分別表示γ(zn1)γ(zn2)。所以我們可以看下圖7,它是透過初始值所計算出的置信度。顏色代表它們有大於0.5的置信度是屬於同一群。

圖7. 初始條件下所計算的置信度,實線圓圈代表confidence level,內圈是1σ而外圈是2σ

 既然我們已經分出兩群了,我們變透過這兩群的點來計算M-step所需要的值,基本上在M-step裡就是要透過置信度來更新參數組θ,計算所需的公式是Eqs. (12-15),實現的代碼如下
# Starting M-step: Re-estimate parameters that maximizes expectation
# Re-evaluating N_k, Eq. (13) 
N1,N2 = np.sum(gamma1),np.sum(gamma2)

# Re-evaluating mean mu_k, Eq. (12)
p1 = np.sum(((cluster.T)*gamma1).T,axis=0)/N1
p2 = np.sum(((cluster.T)*gamma2).T,axis=0)/N2

# Re-evaluating pi_k, Eq. (15)
pi1 = N1/N
pi2 = N2/N
上面的部份更新了{μk,πk},因這兩個計算比較簡單。而協方差矩陣的計算按照Eq. (14)是 Σk=1NkNn=1γ(znk)(xnμk)(xnμk). 假使我要計算新的Σ1,那麼它必須逐一計算x內每個資料點對μ1的差外積後乘上該點對應的γ(zn1),當計算完x內所有的點後,我們會得到N2×2的矩陣 (因為我們考慮的是2維的資料),將這N個矩陣加總並除以N1即得Σ1,對Σ2的情形一樣,代碼如下
# Re-evaluating covariance matrix
sigma1,sigma2 = [],[]
for i in range(N):
    sigma1.append(gamma1[i]*np.outer((cluster[i]-p1),(cluster[i]-p1)))
    sigma2.append(gamma2[i]*np.outer((cluster[i]-p2),(cluster[i]-p2)))
sigma1 = np.sum(sigma1,axis=0)/N1
sigma2 = np.sum(sigma2,axis=0)/N2
OK, very well! 從代碼註解# Starting E-step...開始一路到上面結束我們變完成一次迭代啦,結果如下圖8。

圖8. EM算法經過一次迭代後的結果,為了排版乾淨我們只秀出兩個群對應到1σ所包含的區域

 不難發現我們的μk已經透過E-step的置信度分群之後更新位置了,但距離正確的分群還有一段距離,所以我們可以加上for迴圈來重複迭帶個幾次,如下
for iters in range(max_iters):
    ...
其中...就是上面E/M-steps交互計算的代碼部份,最大迭代次數由max_iters決定,當然在本文提供的腳本裏面,你會注意到我還提供了一個停止條件,若當μk和上一次迭代的距離變化小於0.01時,不管有沒有達到max_iters的次數都會結束計算,這裡不贅述。而這份代碼經過23次迭帶後會碰到停止條件,我們把部份的結果羅列如下圖9。

圖9. 部份迭代後的結果,實線圓圈的區域表1σ CL

 在圖9裡秀出了每一次迭代過程中μk走過的軌跡,以及該次迭代後修正的Σk對應到1σ CL區間,不像K-means (圖5和6) 最終錯誤的分群,EM很正確的分出來我們預期的結果。

4.2 Beyond Gaussians

在上一節中我們用高斯混合為例,發現了EM算法比傳統的K-means更正確的分出了結果,而事實上數學可以證明K-means就是將EM中置信度全取為1的特例,這種我們叫作hard K-means,而EM又叫作soft K-means (McKay 2003),不過這只是歷史名詞,我們不必太拘泥。
 事實上,分佈p(x|θ)不一定要是高斯,同理p(z|x)也不一定要是Eq. (6)的形式,在這種情況下我們就必須假定一個分佈p(x,z)並採用第三節的方案,而代碼也不能直接照抄4.1節的結果 (It's Gaussian mixtures ad hoc!),腳本是死的,方法是活的,了解後便可以理出正確的思路,高斯以外的討論可以見Bishop 2008和Murphy 2012。

五、小結

在IA9裡我們看出EM算法將機率分佈的概念引入分群的方法中,使得它較hard K-means更有彈性,雖然它必須花費較多的計算效能,但卻能得到更接近我們預期的結果,並且這個算法在computer vision裡用來分割圖像或分離前後景也有著重要的應用 (Prince 2012)。但即使這裡引入了機率 (主要是每個資料點對應的pdf) 的計算,我們仍然離真正的隨機性算法八字沒一撇,EM仍是所謂的決定性算法,與IA8用Gibbs採樣去噪本質仍是不一樣的,我會在之後的文章繼續討論這個議題。啊對了,雖然在IA9a的引文裡提到要證明如何從高斯混合EM到K-means,不過就和費馬 (Pierre de Fermat) 說的一樣:空間不夠,而目前我是時間不夠😜,所以只能留待之後再補遺啦!


Source on githubIA9_EM.ipynb

留言

這個網誌中的熱門文章

PS2 — 因果本無心,天機皆可洩: 統計!

物理雜記3 - Ising模型與模擬退火