关于EM算法原理的分析与理解(Python实现)

本文的计算公式出自《统计学习方法》,写这篇文章主要是想把自己对这个算法的思路理清,并把自己的理解记录下来,同时分享出来,希望能够帮助到打算入门机器学习的人。

定义:
概率模型有时既含有观测变量,又含有隐变量或潜在变量。如果概率模型的变量都是观测变量,那么给定数据,可以直接用极大似然估计法,或贝叶斯估计法估计模型参数,但是,当模型含有隐变量时,就不能简单地使用这些估计方法了。EM算法就是含有隐变量的概率模型参数的极大似然估计法,或极大后验概率估计法。

算法原理:
一般用Y表示观测随机变量的数据,Z表示隐随机变量的数据,theta是估计的模型参数。

EM算法通过迭代求
L_theta1.PNG

的极大似然估计,每次迭代包含两步:E步,求期望;M步,求极大化。
将极大似然函数展开得到:
9.PNG

该极大似然函数的展开式的意思是:在模型参数中隐变量Z的条件概率与在隐变量下观测变量的条件概率乘积是一次操作中观测变量的概率,而求和则是所有操作中观测变量的概率。
该极大似然函数是无法求解的,事实上EM算法是通过不断的迭代近似极大化极大似然函数的。
为了新模型参数估计值能使极大似然函数极大化,则考虑第i+1次迭代与第i次迭代的差,通过不断求解差值的极大化,从而求得第i+1次迭代的极大化。


6.PNG

7.PNG

8.PNG

看到这里就可以知道,通过取全数据对数似然的期望最大化,就可以最大化式子(9.12)

下面给出EM算法的一般步骤:


10.PNG

Python实现:
以《统计学习方法》书上的三硬币例子为例,过程就不描述了,自己参考书上。主要是通过这个例子讲解一下EM算法,一步一步的说明EM算法的过程。
三硬币模型极大似然函数:


11.PNG

12.PNG

13.PNG

(9.5)式子就是在第I次迭代中,根据每个观测变量分别求隐变量的条件概率(硬币A出现正面,选择硬币B得到观测数据的概率)。对应EM算法的第2步。


14.PNG

(9.6)~(9.7)是如何得到的?我会在下一篇《EM算法在高斯混合模型学习中的应用》详细推导是如何得来的。目前我们只需要理解这几个公式的意思即可。
(9.6)公式:对第i次迭代中求出的所有操作中硬币A出现正面的概率期望。
(9.7)公式:对第i次迭代中硬币A出现正面,然后选择硬币B得到正面占硬币B所有操作中的概率。
(9.8)公式:对第i次迭代中硬币A出现反面,然后选择硬币C得到正面占硬币C所有操作中的概率。
不断的迭代直到满足条件则停止迭代,算法结束。
需要注意的是,EM算法对初始值是敏感的,不同的初始值会得到的参数不同。

完整代码如下:

from numpy import *
import numpy as np
import matplotlib.pyplot as plt
import random

def create_sample_data(m, n):
    mat_y = mat(zeros((m, n)))

    for i in range(m):
        for j in range(n):
            #通过产生随机数,每一行表示一次实验结果
            mat_y[i, j] = random.randint(0, 1)
    return mat_t

#EM算法
def em(arr_y, theta, tol, iterator_num):
    PI = 0
    P = 0
    Q = 0
    m,n = shape(arr_y)
    mat_y = arr_y.getA()

    for i in range(iterator_num):
        miu = []
        PI = copy(theta[0])
        P = copy(theta[1])
        Q = copy(theta[2])
        for j in range(m):
            miu_value = (PI * (P**mat_y[j]) * ((1 - P)**(1 - mat_y[j]))) / \
                (PI * (P**mat_y[j]) * ((1 - P)**(1 - mat_y[j])) + (1 - PI) * (Q**mat_y[j]) * ((1 - Q)**(1 - mat_y[j])))
            miu.append(miu_value)
        
        sum1 = 0.0
        for j in range(m):
            sum1 += miu[j]
        theta[0] = sum1 / m

        sum1 = 0.0
        sum2 = 0.0
        for j in range(m):
            sum1 += miu[j] * mat_y[j]
            sum2 += miu[j]
        theta[1] = sum1 / sum2

        sum1 = 0.0
        sum2 = 0.0
        for j in range(m):
            sum1 += (1 - miu[j]) * mat_y[j]
            sum2 += (1 - miu[j])
        theta[2] = sum1 / sum2

        print("-------------------")
        print(theta)
        if(abs(theta[0] - PI) <= tol and abs(theta[1] - P) <= tol \
            and abs(theta[2] - Q) <= tol):
            print("break")
            break
    return PI,P,Q

def main():
    #mat_y = create_sample_data(100, 1)
    mat_y = mat(zeros((10, 1)))
    mat_y[0,0] = 1
    mat_y[1,0] = 1
    mat_y[2,0] = 0
    mat_y[3,0] = 1
    mat_y[4,0] = 0
    mat_y[5,0] = 0
    mat_y[6,0] = 1
    mat_y[7,0] = 0
    mat_y[8,0] = 1
    mat_y[9,0] = 1
    theta = [0.5, 0.6, 0.5]
    print(mat_y)
    PI,P,Q = em(mat_y, theta, 0.001, 100)
    print(PI, P, Q)

main()

输入数据(与《统计学习方法》的输入数据一样):

1
1
0
1
0
0
1
0
1
1

本文的输出结果:


15.PNG

《统计学习方法》上的输出结果:


16.PNG

两者对比结果是一样的。
可以改变模型参数再实验一下(依旧取书上的参数,看看是否输出依旧一样的)
def main():
    #mat_y = create_sample_data(100, 1)
    mat_y = mat(zeros((10, 1)))
    mat_y[0,0] = 1
    mat_y[1,0] = 1
    mat_y[2,0] = 0
    mat_y[3,0] = 1
    mat_y[4,0] = 0
    mat_y[5,0] = 0
    mat_y[6,0] = 1
    mat_y[7,0] = 0
    mat_y[8,0] = 1
    mat_y[9,0] = 1
    theta = [0.4, 0.6, 0.7]
    print(mat_y)
    PI,P,Q = em(mat_y, theta, 0.001, 100)
    print(PI, P, Q)

输出结果:


17.PNG

书上的输出结果:


18.PNG

经过对比还是完全一样的,算法正确。
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 194,457评论 5 459
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 81,837评论 2 371
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 141,696评论 0 319
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 52,183评论 1 263
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 61,057评论 4 355
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 46,105评论 1 272
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 36,520评论 3 381
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 35,211评论 0 253
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 39,482评论 1 290
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 34,574评论 2 309
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 36,353评论 1 326
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 32,213评论 3 312
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 37,576评论 3 298
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 28,897评论 0 17
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 30,174评论 1 250
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 41,489评论 2 341
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 40,683评论 2 335

推荐阅读更多精彩内容