EM算法系列-三硬幣問題

來自https://www.jianshu.com/p/f4ff48025c52
https://blog.csdn.net/wendaomudong_l2d4/article/details/79005461

1、引言

概率模型有時既含有觀測變量,又含有隱變量或潛在變量,如果概率模型的變量都是觀測變量,那麼給定數據,可以直接用極大似然估計法,或貝葉斯估計法估計模型參數,但是,當模型中含有隱變量時,就不能簡單的使用這些方法。EM算法就是含有隱變量的概率模型參數的極大似然估計法,或極大後驗概率估計法。

EM算法流程

E步:對完全數據的對數似然函數$\log(P(Y,Z|\theta)$求關於$P(Z|Y,\theta^{(i)})$的數學期望,
EZY,θ(i)[log(P(Y,Zθ))]\quad E_{Z|Y,\theta^{(i)}}[log(P(Y,Z|\theta))]
其中$\theta^{(i)}$是第i次迭代時,$θ\theta`的估計值

M步:對E步的結果求極值

EM算法步驟

一般的,用Y表示觀測隨機變量的數據,Z表示隱隨機變量的數據,Y和Z連在一起稱爲完全數據,只有觀測數據Y稱爲不完全數據,假設給定觀測數據Y,其概率分佈爲P(Y|θ),那麼不完全數據的似然函數就是P(Y|θ),對數似然函數是L(θ) = log(P(Y|θ)),假設Y和Z的聯合概率分佈是P(Y,Z|θ),那麼完全數據的對數似然函數是logP(Y,Z|θ)。
EM算法通過迭代求L(θ) = log(P(Y|θ))的極大似然估計,每次迭代包括兩步:E步,求期望,M步,求最大化,下面介紹EM算法的步驟:

KaTeX parse error: Can't use function '$' in math mode at position 6: \quad$̲`輸入:觀測變量數據Y,隱變量…,條件分佈`P(ZY,θ)P(Z|Y,\theta)$;

$\quad輸出:模型參數θ\theta`.

KaTeX parse error: Can't use function '$' in math mode at position 10: \quad (1)$̲`選擇參數的初值`$\thet…,開始迭代;

$(2)\quad (2)E步:記θ(i)\theta^{(i)}爲第i次迭代參數θ\theta`的估計值,在第i+1次迭代的E步,計算

Q(θ,θ(i))=EY,θ(i)[log(P(Y,Zθ))]\qquad\qquad Q(\theta,\theta^{(i)})=E_{Y,\theta^{(i)}}[\log( P(Y,Z|\theta))]

 =Zlog(P(Y,Zθ)P(ZY,θ(i)))\qquad\qquad\qquad\quad\ =\sum\limits_Z log(P(Y,Z|\theta)P(Z|Y,\theta^{(i)}))

這裏,$P(Z|Y,\theta^{(i)})$是在給定觀測數據Y和當前的參數估計$\theta^{(i)}$下隱變量數據Z的條件概率分佈;

KaTeX parse error: Can't use function '$' in math mode at position 6: \quad$̲`(3) M步: 求使`$Q(…

θ(i+1)=argmaxθQ(θ,θ(i))\qquad\qquad\qquad \theta^{(i+1)}=\arg\underset{\theta}{\max}Q(\theta,\theta^{(i)})

$\quad`(4) 重複第(2)步和第(3)步,直到收斂.

2、三硬幣模型描述

三硬幣問題是這樣的:
假設有三枚硬幣,分別記爲A、B、C。這些硬幣正面的概率分別爲π,p,q,進行如下的拋硬幣實驗:先擲硬幣A,根據其結果選出硬幣B或者硬幣C,正面選硬幣B,反面選硬幣C,然後擲選出的硬幣,擲硬幣的記錄,出現正面記作1,出現反面記作0,獨立地重複n次實驗(這裏n=10),然後觀測結果如下:

1,1,0,1,0,0,1,0,1,1

假設只能觀測到擲硬幣的結果,不能觀測擲硬幣的過程,問如何估計三硬幣正面出現的概率,即三硬幣模型的參數π,p,q。

3、三硬幣問題表示

符號標記:

KaTeX parse error: Can't use function '$' in math mode at position 10: \quad y_j$̲`爲第j次實驗的觀測 \quad Z$爲隱變量,表示擲硬幣A出現的結果.該變量只有兩個取值0,1 $$\quad z_j$爲第j次實驗時,擲硬幣A出現的結果,$z_j=1$表示硬幣A擲出正面,$z_j=0$表示硬幣A擲出反面
KaTeX parse error: Can't use function '$' in math mode at position 12: \quad\theta$̲`表示參數集合`$\pi,p,…\quad\theta^{(i)}i,`爲第i次迭代時,π,p,q\pi,p,q`的估計值

4、EM算法求解三硬幣模型

假設當前模型的參數爲π,p,q時,隱含變量來自於硬幣A的後驗概率,
對數似然函數爲:

log(P(Y,Zθ))=log(j=1np(yj,zjθ))=j=1nlog(p(yj,zjθ))\log(P(Y,Z|\theta))=\log(\prod\limits_{j=1}^n p(y_j,z_j|\theta))=\sum\limits_{j=1}^n \log(p(y_j,z_j|\theta))

期望爲:

`EZY,θ(i)[log(P(Y,Zθ))]E_{Z|Y,\theta^{(i)}}[\log(P(Y,Z|\theta))]$

=j=1nzj[p(zjyj,θ(i))log(p(yj,zjθ))]=\sum\limits_{j=1}^n\sum\limits_{z_j}[p(z_j|y_j,\theta^{(i)})\log(p(y_j,z_j|\theta))]

=j=1n(p(zj=1yj,θ(i))log(p(yj,zj=1θ))+p(zj=0yj,θ(i))log(p(yj,zj=0θ)))=\sum\limits_{j=1}^n(p(z_j=1|y_j,\theta^{(i)})\log(p(y_j,z_j=1|\theta))+p(z_j=0|y_j,\theta^{(i)})\log(p(y_j,z_j=0|\theta)))

對於概率`p(zj,yjθ)p(z_j,y_j|\theta)$:
p(yj,zj=1θ)=p(yjzj=1,θ)p(zj=1θ)=πpyj(1p)1yj\quad p(y_j,z_j=1|\theta)=p(y_j|z_j=1,\theta)p(z_j=1|\theta)=\pi p^{y_j}(1-p)^{1-y_j},

p(yj,zj=0θ)=p(yjzj=0,θ)p(zj=0θ)=(1π)qyj(1q)1yj\quad p(y_j,z_j=0|\theta)=p(y_j|z_j=0,\theta)p(z_j=0|\theta)=(1-\pi) q^{y_j}(1-q)^{1-y_j}

所以最終結果:

Q(θ,θ(i))=EZY,θ(i)[log(P(Y,Zθ))]\qquad Q(\theta,\theta^{(i)})=E_{Z|Y,\theta^{(i)}}[\log(P(Y,Z|\theta))]

=j=1n(μj(i)log(πpyj(1p)1yj)+(1μj(i))log((1π)qyj(1q)1yj))\qquad\qquad = \sum\limits_{j=1}^n(\mu_j^{(i)} * \log(\pi p^{y_j}(1-p)^{1-y_j})+(1-\mu_j^{(i)})\star \log((1-\pi)q^{y_j}(1-q)^{1-y_j}))

上式中`μj(i)=p(zj=1yj;θ(i))\mu_j^{(i)}=p(z_j=1|y_j;\theta^{(i)})$.

EM算法的具體實現

E-Step:

μj(i)=πpyj(1p)1yjπpyj(1p)1yj+(1π)qyj(1q)1yj\qquad \mu_j^{(i)}=\frac{\pi p^{y_j}(1-p)^{1-y_j}}{\pi p^{y_j}(1-p)^{1-y_j}+(1-\pi)q^{y_j}(1-q)^{1-y_j}},

那麼隱含變量來自於硬幣C的後驗概率自然爲`1μj(i)1-\mu_j^{(i)}$.

def cal_u(phi, p, q, yj):
    return phi * math.pow(p, yj) * math.pow(1 - p, 1 - yj) / \
           float(phi * math.pow(p, yj) * math.pow(1 - p, 1 - yj) +
                 (1 - phi) * math.pow(q, yj) * math.pow(1 - q, 1 - yj))

def e_step(phi,p,q,y):
    """
        e步計算
    :param phi: 下一次迭代開始的 pi
    :param p:  下一次迭代開始的 p
    :param q:  下一次迭代開始的 q
    :param y: 觀察數據
    :return:
    """
    return [cal_u(phi,p,q,yj) for yj in y]

M-Step:

下面分別對$\pi,p,q$求偏導:

(1) 估計參數$\pi$

$$\qquad `對`\pi$`求偏導:

\begin{array}{lll}
\frac{\partial Q}{\partial \pi}&=&\sum\limits_{j=1}^n(\mu_j^{(i)}* \frac{1}{\pi}-(1-\mu_j^{(i)})* \frac{1}{1-\pi})\\
&=&\sum\limits_{j=1}^n(\frac{\pi-\mu_j^{(i)}}{\pi(1-\pi)})\\
&=&\frac{n\pi-\sum\limits_{j=1}^n\mu_j^{(i)}}{\pi(1-\pi)}=0
\end{array}

所以π的估計爲:

π=1nj=1nμj(i)\qquad\qquad \pi=\frac{1}{n}\sum\limits_{j=1}^n \mu_j^{(i)}

(2) 估計參數p

對p求偏導:

\begin{array}{lll}
\frac{\partial Q}{\partial p}&=&\sum\limits_{j=1}^n\mu_j^{(i)}*\frac{\pi(y_j p^{y_j-1}(1-p)^{1-y_j}+p^{y_j}(-(1-y_j)(1-p)^{-y_j})}{\pi p^{y_j}(1-p)^{1-y_j}}\\
&=&\sum\limits_{j=1}^n \mu_j^{(i)}* \frac{y_j p^{y_j-1}(1-p)^{-y_j}(1-p)+p^{y_j-1}*p(y_j-1)(1-p)^{-y_j}}{p^{y_j}(1-p)^{1-y_j}}\\
&=&\sum\limits_{j=1}^n\mu_j^{(i)}*\frac{y_j(1-p)+p*(y_j-1)}{p(1-p)}\\
&=&\sum\limits_{j=1}^n\mu_j^{(i)}*\frac{y_j-p}{p(1-p)}=0
\end{array}

p的估計爲:

p=j=1nμj(i)yjj=1nμj(i)\qquad p=\frac{\sum\limits_{j=1}^n\mu_j^{(i)}y_j}{\sum\limits_{j=1}^n\mu_j^{(i)}}

(3) 估計參數q

對q求偏導:

\begin{array}{lll}
\frac{\partial Q}{\partial q}&=&\sum\limits_{j=1}^n(1-\mu_j^{(i)})*\frac{(1-\pi)(y_j q^{y_j-1}(1-q)^{1-y_j}+q_{y_j}(-(1-y_j)(1-q){-y_j}))}{(1-\pi)q^{y_j}(1-q)^{1-y_j}}\\
&=&\sum\limits_{j=1}^n(1-\mu_j^{(i)})*\frac{y_j q^{y_j-1}(1-q)^{-y_j}*(1-q)+q^{y_j-1}*q(y_j-1)(1-q)^{-y_j}}{q^{y_j}(1-q)^{1-y_j}}\\
&=&\sum\limits_{j=1}^n(1-\mu_j^{(i)})*\frac{y_j(1-q)+q*(y_j-1)}{q(1-q)}\\
&=&\sum\limits_{j=1}^n(1-\mu_j^{(i)})*\frac{y_j-q}{p(1-q)}=0
\end{array}

q的估計爲:

 p=j=1n(1μj(i))yjj=1n(1μj(i))\qquad\ p=\frac{\sum\limits_{j=1}^n(1-\mu_j^{(i)})y_j}{\sum\limits_{j=1}^n(1-\mu_j^{(i)})}

更新$\pi,p,q$的代碼如下:

def m_step(u,y):
    phi1=sum(u)/len(u)
    p1=sum([u[i]*y[i] for i in range(len(u))]) / sum(u)
    q1=sum([(1-u[i])*y[i] for i in range(len(u))]) / sum([1-u[i] for i in range(len(u))])
    return [phi1,p1,q1]

算法首先選取參數初始值θ(0)=π(0),p(0),q(0) ,然後迭代到收斂爲止.

完整的python代碼如下:

# -*- coding: utf-8 -*-
import math

def cal_u(phi, p, q, yj):
    """
      u值計算
    :param phi: 下一次迭代開始的 pi
    :param p:  下一次迭代開始的 p
    :param q:  下一次迭代開始的 q
    :param yj: 觀察數據第j個值,從0開始
    :return: 
    """
    return phi * math.pow(p, yj) * math.pow(1 - p, 1 - yj) / \
           float(phi * math.pow(p, yj) * math.pow(1 - p, 1 - yj) +
                 (1 - phi) * math.pow(q, yj) * math.pow(1 - q, 1 - yj))

def e_step(phi,p,q,y):
    """
        e步計算
    :param phi: 下一次迭代開始的 pi
    :param p:  下一次迭代開始的 p
    :param q:  下一次迭代開始的 q
    :param y: 觀察數據
    :return:
    """
    return [cal_u(phi,p,q,yj) for yj in y]

def m_step(u,y):
    """
     m步計算
    :param u:  m步計算的u
    :param y:  觀察數據
    :return:
    """
    phi1=sum(u)/len(u)
    p1=sum([u[i]*y[i] for i in range(len(u))]) / sum(u)
    q1=sum([(1-u[i])*y[i] for i in range(len(u))]) / sum([1-u[i] for i in range(len(u))])
    return [phi1,p1,q1]

def run(observed_y, start_phi, start_p, start_q, iter_num):
    """

    :param observed_y:  觀察數據
    :param start_phi:  下一次迭代開始的pi $\pi$
    :param start_p:  下一次迭代開始的p
    :param start_q:  下一次迭代開始的q
    :param iter_num:  迭代次數
    :return:
    """
    for i in range(iter_num):
        u=e_step(start_phi, start_p, start_q, observed_y)
        print (i,[start_phi,start_p,start_q])
        if [start_phi,start_p,start_q]==m_step(u, observed_y):
            break
        else:
            [start_phi,start_p,start_q]=m_step(u, observed_y)
if __name__ =="__main__":
    # 觀察數據
    y = [1, 1, 0, 1, 0, 0, 1, 0, 1, 1]
    # 初始化 pi,p q
    [phi, p, q] = [0.4, 0.6, 0.7]
    # 迭代計算
    run(y,phi,p,q,100)

結果如下:

0 [0.4, 0.6, 0.7]
1 [0.40641711229946526, 0.5368421052631579, 0.6432432432432431]
2 [0.40641711229946537, 0.5368421052631579, 0.6432432432432431]
3 [0.40641711229946537, 0.536842105263158, 0.6432432432432431]
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章