EM Algorithm

Expectation Maximization Algorithm

EM算法和之前學的都不太一樣,EM算法更多的是一種思想,所以後面用幾個例子講解,同時也會重點講解GMM高斯混合模型。

①極大似然估計

極大似然估計這裏面用的比較多。假設我們想要知道我們學生身高的分佈,首先先假設這些學生都是符合高斯分佈我們要做的就是要估計這兩個參數到底是多少。學生這麼多,挨個挨個來肯定是不切實際的,所以自然就是抽樣了。
爲了統計學生身高,我們抽樣200個人組成樣本
我們需要估計的參數首先估計一下抽到這兩百人的概率一共是多少,抽到男生A的概率抽到學生B的概率所以同時抽到這兩個學生的概率就是那麼同時抽到這200個學生的G概率
最後再取一個對數就好了:

notation和log

上面有一條公式裏面是同時存在了;和|,這兩個符號差別其實有點大的。|一般我們是用來表示條件概率,比如就是表示x在θ的條件下發生的概率。也是一個意思。
分號;表示的就是表示後面的是待估計的參數,也就是說P(x;θ)意思就是後面的θ是需要估計的參數而不是條件,所以|也有另一層意思,如果不是表示條件概率,那麼就是表示後面有待估計參數。
當然是在|不表示條件概率的情況下。

這兩種表示法是源於兩種學派的不同理解:
頻率派認爲參數爲固定的值,是指真實世界中,參數值就是某個定值。
貝葉斯派認爲參數是隨機變量,是指取這個值是有一定概率的。當然,無論是;還是|,他們都是表示條件概率的意思,只不過這兩個學派理解不一樣而已。
notation的問題解決了之後就是log的問題了,爲什麼需要log化,講道理,是不需要的。但是求log有這麼幾個好處:
1.計算簡單,累乘是很難計算的,log之後可以變換成累加。
2.概率累乘是會出現數字非常小的情況,log之後就可以避免這種情況。
3.log之後函數的梯度方向是沒有變化的,對於函數優化的方向影響很小。

似然函數的執行步驟:
1.得到似然函數
2.取對數整理
3.求導數,另導數爲零
4.解方程得到解

②Jensen不等式

首先引出凸函數的概念那麼就是凸函數,所以它的圖像就是一個勾形的,看起來是一個凹函數,實際上是凸函數。

10624272-b1efeb23d409f01d.png

凸函數的性質很顯而易見了

10624272-06507731dc83f7ca.png

其實很明顯的,看圖就知道了,E(x)其實就是a到b的平均值,上面的結論很容易證實。那麼如果想要取到等號,需要改變上面?取等號的意思就是相切,相切的意思就是a = b,既然a = b了,那麼x自然就是常數了,所以當且僅當
如果是凹函數,那麼就是方向相反了。

③EM算法的推導

正常來看先是要引入一個最大似然函數:但這樣其實是和難求的,P(x|θ)完全混在了一起,根本求不出來,所以我們要引入一個輔助變量z。

隱變量Z

隱變量是觀測不到的,比如做一個抽樣,從3個袋子裏面抽取小球。而抽取這些小球的過程是不可見的,抽取的過程其實就是隱變量,而這些隱變量,也就是過程可以告訴我們這個x是從哪個袋子來的,由此來區分。這個隱變量和HMM裏面的隱含序列不是一個東西,隱含序列是當前x的狀態,而不是抽取x的過程。所以在這裏,通俗點講,這個z就是用來找到x的組類的,也就是說z來告訴這個x你是屬於哪一組的。
另外需要注意的是,隱變量是不可以隨便添加的,添加隱變量之後不能影響邊緣概率。也就是說,原來是P(x),添加之後就是P(x,z),那麼必須有:

所以我們引入隱變量的原因是爲了轉化成和這幾個高斯模型相關的式子,否則無從下手。化簡一下上式子:既然z可以指定x,那麼我們只需要求解出z就好了。
注意上面凸函數所提到的一個期望性質,這裏就可以使用了。因爲雖然優化了上面的式子,還是不能求出來,因爲z變量實在是太抽象了,找不到一個合適的公式來表示它。EM的一個方法就是用優化下界函數的方法來達到優化目標函數的目的。
既然z很抽象,那麼我們就需要一個轉變一下。對於每一個樣例x都會對應一個z,那麼假設一個分佈Q(z)是滿足了z的分佈的,而Q(z)滿足的條件是Qi意味着每一個x對應的z都會對應着一個Q了,這裏有點複雜,再詳細解釋一下。一個x對應一組z,z是一個向量,但是每一個z又會分別對應一個一個分佈Q。以爲最後得到的z不會是一個數字,而是一個概率,也就是說Q(z)得到的是這個x樣例屬於這個類別的概率是多少。而z的數量,一個是當前有多少個分佈混合在一起的數量。
再梳理一下:現在的樣本是xi,那麼每一個xi將會對應着一組的z,每一個xi同時也會對應着一個分佈Qi,z其實就是反應了這個樣本是來自於哪個分佈的。比如這個x是A1分佈做了3,A2分佈做了5,那麼z可能就是={3,5}。所以Qi(z)得到的是這個x屬於這些個分佈的概率,也就是說這些分佈對x做了多少百分比的功,自然就是要等於1了。
還要注意的是,上面的這個並不能得到Qi(z)就是分佈對x做了多少功的結論,得到這個結論是後面下界函數與目標函數相等得到的。這裏只是知道了總和等於1,因爲是分佈的總和嘛。
現在就到了公式的化簡:
仔細看一下這個式子這個式子其實就是求的期望,假設,那麼可以利用上面。於是化簡:
這個時候就得到了下界函數,上面也講過了,想要相等,自然就是x要是常數,所以既然,而且z也是一樣的,因爲一個樣本嘛。所以上下加和(如果是離散的,那就sum一下,連續的那就積分,這裏是離散的,所以就是sum一下)。於是有
於是有:

10624272-ccb80da25300ab61.png

所以Q(z)計算的是後驗概率。計算在當前參數θ和已經抽樣到x的條件下,這個x是從z來的概率。其實就是z對x做了多少貢獻。
所以整個EM算法步驟就很清晰了:

EM算法計算步驟:

E-step:
對於每一個,求
M-step:

這時候就可以使用求導迭代的方法求解了。

這就是整一個EM算法的框架了,可以看到其實沒有比較具體的算法,大致上就是一個框架。那麼問題來了,怎麼樣證明這東西是一個收斂的??

證明EM算法的收斂性

既然是極大似然估計,那麼需要證明的自然就是,也就是說極大似然估計要單調遞增。因爲每一次都是極大,那麼隨着時間增加,自然就是要增大的了。
當給定一個的時候,相當於t時間的EM算法進行了E步了,所以有:
然後就走M步,M步之前還沒有求最大,所以:這一步有點複雜,這裏是M-step了,是L(θ)求極大值得到的,而最重要的是L和後面下界函數的關係。這兩個東西是不相等的,下界函數等於目標函數的條件是x爲constant,x == constant意味着Q得求出來,這裏看這個Q貌似是出來了,但是這個Q是,是上一個時刻的,而不是這個時刻的,所以t+1時刻Q還沒有被固定住,也就是沒有滿足x == constant的條件,所以下界函數小於等於目標函數。接下來就簡單了,直接把換成就好了。

10624272-e4c4d749e2aa0ded.png

這樣就證明了收斂性。

EM algorithm的優化方法:

之前討論過,這種方法是迭代,使用極大似然估計和迭代的方法來進行優化,但實際上這更像是一種座標上升的方法:

10624272-544bd237ec99baf9.png

一次固定一個變量,對另外的求極值,最後逐步逼近極值。對應到EM上,E步:固定 θ,優化Q;M步:固定 Q,優化 θ;交替將極值推向極大。Kmeans也是這樣更新的,固定中心點,優化Ein;優化完成,更新中心點。SMO也是,固定更新α1和α2。

④GMM的推導

可以直接把高斯混合模型代入EM框架裏面。
存在多個高斯分佈混合生成了一堆數據X,取各個高斯分佈的概率是,第i個高斯分佈的均值是,方差是,求法φ,μ,σ。
按照套路,第一個E-step求出Q,於是有:
意思就是求出第i個樣本屬於第j個分佈的概率是多少。之後就是M-step了,就是化簡了:

這裏可能需要解釋一下,根據至於條件,因爲很明顯,z是隱變量,只是指明瞭x是屬於哪個類別,和μ,Σ沒有什麼關係,所以直接忽略那兩個參數了,所以P(z)是沒有那兩個參數的,z是代表了分佈,所以每一個分佈的概率肯定是包括了,所以就只有一個概率的參數。P(x|z)是本身的概率,就是已經知道分佈是那個了,求屬於這個分佈的概率是多少,既然已經選定了分佈那麼自然就不需要再看φ了,因爲φ是各個分佈的概率。

10624272-97f310b5bd8c11ae.png

之後就是求導數了:
10624272-38609e624cdf4c52.png

導數等於0,於是有:
μ就出來了。
對於φ,那就簡單了,實際上需要優化的式子:
求導等於0。
要注意的是φ還有一個條件:
。有條件,那麼問題來了,不能直接求導,所以只能用拉格朗日乘子法求解,於是構造式子:

接着求導
。於是得到
,再改變一下,兩邊加和,得到
,這個就簡單了,
,所以-β = m。那麼:
10624272-e76886d2bd920041.png

Σ也是一樣:
10624272-735036c5f3e898e1.png

這樣整個推導就算結束了。

⑤硬幣模型

現在有兩個硬幣AB,進行5次試驗每一次投10次,並不知道是哪個硬幣投的,求兩種硬幣的正面的概率。
首先E-step:
首先先初始化一下,
第一個試驗選中A的概率:
同樣求得
計算機出每一個試驗的概率然後相加求均值。
之後就是M-step了:

10624272-2d21573def70f1f6.png

表示選擇了A的概率,
表示選擇了B的概率。之後就是求導更新了。

⑥代碼實現

方差的求解就不玩了,主要就是迭代求解μ和φ的值了。
首先是生成數據,4個高斯分佈,每一個高斯分佈的sigma都是一樣的,不一樣的只有μ和α,也就是φ,習慣上把前面的一個參數叫做權值,所以用α來表示。

def generate_data(sigma, N, mu1, mu2, mu3, mu4, alpha):
    global X
    X = np.zeros((N, 2))
    X = np.matrix(X)
    global mu
    mu = np.random.random((4, 2))
    mu = np.matrix(mu)
    global expect
    expect = np.zeros((N, 4))
    global alphas
    alphas = [0.25, 0.25, 0.25, 0.25]
    for i in range(N):
        if np.random.random(1) < 0.1:
            X[i, :] = np.random.multivariate_normal(mu1, sigma, 1)
        elif 0.1 <= np.random.random(1) < 0.3:
            X[i, :] = np.random.multivariate_normal(mu2, sigma, 1)
        elif 0.3 <= np.random.random(1) < 0.6:
            X[i, :] = np.random.multivariate_normal(mu3, sigma, 1)
        else:
            X[i, :] = np.random.multivariate_normal(mu4, sigma, 1)
    plt.title('Generator')
    plt.scatter(X[:, 0].tolist(), X[:, 1].tolist(), c = 'b')
    plt.xlabel('X')
    plt.ylabel('Y')
    plt.show()

這四個模型的比例分別是1:2:3:4,使用EM來找到他們屬於的類別。


10624272-ed6bdb6587db87d9.png

其實如果用kmeans聚類的話更加快速,但是這裏還是用EM。
E-step:

def e_step(sigma, k, N):
    global X
    global mu
    global expect
    global alphas
    for i in range(N):
        W = 0
        for j in range(k):
            W += alphas[j] * math.exp(-(X[i, :] - mu[j, :]) * sigma.I * np.transpose(X[i, :] - mu[j, :])) / np.sqrt(np.linalg.det(sigma))
        for j in range(k):
            w = math.exp(-(X[i, :] - mu[j, :]) * sigma.I * np.transpose(X[i, :] - mu[j, :])) / np.sqrt(np.linalg.det(sigma))
            expect[i, j] = alphas[j]*w/W
            pass

就是按照公式來求解w即可,求解每一個分佈對樣本點做了多少的功,之後求單個樣本點求比例。
M-step:

def m_step(k, N):
    global expect
    global X
    global alphas
    for j in range(k):
        mathor = 0
        son = 0
        for i in range(N):
            son += expect[i, j]*X[i, :]
            mathor += expect[i, j]
        mu[j, :] = son / mathor
        alphas[j] = mathor / N

直接按照公式優化即可。

if __name__ == '__main__':
    iterNum = 1000
    N = 500
    k = 4
    probility = np.zeros(N)
    mu1 = [5, 35]
    mu2 = [30, 40]
    mu3 = [20, 20]
    mu4 = [45, 15]
    sigma = np.matrix([[30, 0], [0, 30]])
    alpha = [0.1, 0.2, 0.3, 0.4]
    generate_data(sigma, N, mu1, mu2, mu3, mu4, alpha)
    for i in range(iterNum):
        print('iterNum : ', i)
        err = 0
        err_alpha = 0
        Old_mu = copy.deepcopy(mu)
        Old_alpha = copy.deepcopy(alphas)
        e_step(sigma, k, N)
        m_step(k, N)
        for z in range(k):
            err += (abs(Old_mu[z, 0] - mu[z, 0]) + abs(Old_mu[z, 1] - mu[z, 1]))
            err_alpha += abs(Old_alpha[z] - alphas[z])
        if (err <= 0.001) and (err_alpha < 0.001):
            print(err, err_alpha)
            break
    color = ['blue', 'red', 'yellow', 'green']
    markers  = ['<', 'x', 'o', '>']
    order = np.zeros(N)
    for i in range(N):
        for j in range(k):
            if expect[i, j] == max(expect[i, ]):
                order[i] = j
        plt.scatter(X[i, 0], X[i, 1], c = color[int(order[i])], alpha=0.5, marker=markers[int(order[i])])
    plt.show()
    print('standedμ:',mu4, mu3, mu2, mu1)
    print('standedα:',alpha)
    print('new μ:', mu)
    print('new α:',alphas)

運行函數。看看結果:


10624272-a85506d016bce0bd.png

10624272-5cf9e38f6ac2a4e6.png

結果其實還是相差不大。達到預期。

⑦EM的另一種理解方法

上面所講的其實只是一種理解方法,在李航老師的統計學習方法裏面是另一種比較厲害的解法:
1.E-step:求出Q函數。
2.M-step:利用Q函數求極大值。

其實這兩種方法是完全一樣的,Q函數就是下界函數,

10624272-1c18b5cacb8882f9.png
這個公式和上面的:
10624272-94b9cd251a48dcf1.png
是一樣的,至於爲什麼有下面這個
10624272-3c3ac6b0ff7f9663.png
這是李航老師書上的,既然θ是已經知道了,那麼自然就可以去掉,因爲在log下面做分母就相當於是常數了,拆開可以變減號嘛,在前面的就不可以。回來看看我們剛剛推導的,其實是一樣的,下面的那個Q確實可以去掉,因爲是事先知道的了。在使用Jensen不等式的時候,需要假設隱變量服從某種形式的概率分佈,纔可以將推導過程的一部分看成是期望的表達形式從而應用Jensen不等式。然而這個分佈不是隨便指定的。我們令Jensen不等式取等號的時候,可以計算出這個分佈其實就是:已知觀測數據的隱變量的後驗概率分佈。由於求Q函數需要先求出隱變量的後驗概率的期望,因此,這就可以解釋爲什麼EM算法的“通俗”理解角度的E步驟是求隱變量的期望了。有時候在用EM算法解決某個具體問題的時候,會發現M步驟極大化的居然是完全數據的對數似然函數。這是因爲,Q函數雖然是完全數據的對數似然函數的某種期望,但是求這個期望的過程有時其實就是將隱變量的後驗概率的期望代入就可以了。因此,本質上我們其實還是在求Q函數的極大。
事實上,李航老師的Estep求出Q函數,其實就是通俗理解裏面的求出Q(z)並代入下界函數的過程。因爲求出Q(z)就相當於這個Q(z)被固定了,可以去掉了,於是就和李航老師的式子一樣了。有機會再補一些李航老師的推導,勃大精深。

⑧總結

EM和Kmeans算法其實很類似,事實上步驟基本可以用EM框架來替換,但是Kmeans算法是硬分類,說一不二,但是EM算法不太一樣,是軟分類,百分之幾是那個,百分之幾是這個。

缺點也還是有的:初值敏感,局部最優。因爲存在了隱變量,所以導致了直接對x做極大似然是不可行的,log已經在sum的外面了。所以EM算法就轉向了下界函數,而這種方法本來就不保證找到局部最優解。

如果將樣本看作觀察值,潛在類別看作是隱藏變量,那麼聚類問題也就是參數估計問題。如果一個目標函數存在多個變量,那麼梯度下降牛頓法這些逼近方法就用不了了。但我們可以使用座標上升方法,固定一個變量,對另外一個求導數,然後替換最後逐步逼近極值點。對應到EM算法也是一樣,E步求隱含的z變量,Mstep求解其他參數。

最後符上GitHub代碼:

https://github.com/GreenArrow2017/MachineLearning/tree/master/MachineLearning/ExpectationMaximization

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章