EM算法的简介
EM算法由两步组成:E步和M步,是最常用的迭代算法。

本文主要参考了李航博士的《统计学习方法》
在此基础上主要依据EM算法原理补充了三硬币模型的推导。

1.EM算法的原理
1.1从一个例子开始

三硬币模型
假设有3枚硬币,分别记作A,B和C。 这些硬币正面向上的概率分别是 python应用EMD方法 python em算法_nlppython应用EMD方法 python em算法_nlp_02 。进行如下抛硬币试验:
1、先抛硬币A, 根据其结果选出硬币B或者硬币C,正面选硬币B,反面选硬币C;
2、然后掷选出的硬币,抛硬币的结果,出现正面记作1,出现反面记作0;
3、独立重复python应用EMD方法 python em算法_nlp_03次试验(这里,n=10),观测结果如下:
python应用EMD方法 python em算法_机器学习_04
假设只能观测到掷硬币的结果,不能观测掷硬币的过程。问如何估计三硬币正面出现的概率,即三硬币模型参数。

对于单次观测结果,三硬币模型可以写作:
python应用EMD方法 python em算法_机器学习_05

其中,python应用EMD方法 python em算法_python应用EMD方法_06是第python应用EMD方法 python em算法_机器学习_07个观测结果1或0;随机变量python应用EMD方法 python em算法_python应用EMD方法_08是隐变量,表示未观测到的掷硬币A的结果;python应用EMD方法 python em算法_机器学习_09是模型参数。
方便起见,观测数据可以表示为python应用EMD方法 python em算法_python应用EMD方法_10,隐变量数据可以表示为python应用EMD方法 python em算法_机器学习_11。观测数据的似然函数可以表示为:
python应用EMD方法 python em算法_机器学习_12

即:

python应用EMD方法 python em算法_python应用EMD方法_13

这个问题没有办法直接解析,只能用迭代的方法解决。下面我们先看看EM算法的推导,之后重新再对这个问题进行推导。

1.2 EM算法推导
1.2.1 Jensen 不等式说明

首先说明一下什么是凸函数:
粗糙一点理解,如果函数的二阶导数为正数,那么这个函数就是凸函数:比如开口向上的二次函数就是典型的凸函数。

若有凸函数python应用EMD方法 python em算法_nlp_14,且在函数中取自变量点集python应用EMD方法 python em算法_人工智能_15,且取对应python应用EMD方法 python em算法_机器学习_16,满足python应用EMD方法 python em算法_python应用EMD方法_17,
则有:

python应用EMD方法 python em算法_python_18

python应用EMD方法 python em算法_人工智能_19时,python应用EMD方法 python em算法_nlp_20的二阶导数python应用EMD方法 python em算法_机器学习_21,故可对python应用EMD方法 python em算法_机器学习_22运用Jessen不等式。
如果是对于python应用EMD方法 python em算法_人工智能_23运用Jessen不等式,不等式方向要变号。

1.2.2 EM算法推导

求解型入(1)式的问题,我们取对数似然函数,也就是对对数似然函数求取极大值:
python应用EMD方法 python em算法_python_24

运用迭代的思想解决这个问题,假设在第python应用EMD方法 python em算法_人工智能_25次迭代后python应用EMD方法 python em算法_人工智能_26的估计值是python应用EMD方法 python em算法_人工智能_27。因为想要求取最大对数似然,所以我们希望python应用EMD方法 python em算法_nlp_28,并逐步达到极大值,也就是它们的差值达到最大值:

python应用EMD方法 python em算法_python_29

利用Jensen不等式,得到其下界:

python应用EMD方法 python em算法_nlp_30

python应用EMD方法 python em算法_python_31,则求取的是:

python应用EMD方法 python em算法_人工智能_32

python应用EMD方法 python em算法_python应用EMD方法_33

因为后一项中无python应用EMD方法 python em算法_人工智能_26项,故:

python应用EMD方法 python em算法_python_35

因为:

python应用EMD方法 python em算法_python应用EMD方法_36

设:

python应用EMD方法 python em算法_nlp_37

则:

python应用EMD方法 python em算法_python_38

EM算法的总结:
E步(求隐变量python应用EMD方法 python em算法_python应用EMD方法_39):给定观测数据python应用EMD方法 python em算法_python_40和当前的参数估计python应用EMD方法 python em算法_python_41,求取隐变量python应用EMD方法 python em算法_nlp_42的条件概率分布;
M步:将隐变量当做已知量,求python应用EMD方法 python em算法_人工智能_43的极大化的python应用EMD方法 python em算法_python应用EMD方法_44
E步和M步重复执行,直到收敛。

1.3 三硬币模型继续推导
1.3.1 三硬币模型的隐变量以及完全数据的对数似然函数

我们已知:

python应用EMD方法 python em算法_人工智能_45

python应用EMD方法 python em算法_python应用EMD方法_46来自掷硬币B的概率为python应用EMD方法 python em算法_nlp_47, 则来自C的概率为python应用EMD方法 python em算法_机器学习_48,且python应用EMD方法 python em算法_python_49。即参数python应用EMD方法 python em算法_机器学习_50为模型的隐变量。

于是完全数据的似然函数可以表示为:

python应用EMD方法 python em算法_python_51

相应的对数似然函数为:

python应用EMD方法 python em算法_机器学习_52

1.3.2 E步:确定python应用EMD方法 python em算法_python应用EMD方法_53函数

因为EM算法是迭代算法,设第python应用EMD方法 python em算法_人工智能_25次迭代的参数估计值为python应用EMD方法 python em算法_python_55,又因为隐变量python应用EMD方法 python em算法_机器学习_50代表观测数据来自B的概率,所以第python应用EMD方法 python em算法_人工智能_57次隐变量:

python应用EMD方法 python em算法_python_58

求取python应用EMD方法 python em算法_python应用EMD方法_53:

python应用EMD方法 python em算法_python应用EMD方法_60

python应用EMD方法 python em算法_nlp_61带入则可以得到:

python应用EMD方法 python em算法_python应用EMD方法_62

1.3.2 M步

得到了python应用EMD方法 python em算法_python应用EMD方法_53函数,接下来就是极大化参数:

python应用EMD方法 python em算法_python_64

1.求解python应用EMD方法 python em算法_python_65:

python应用EMD方法 python em算法_python_66

求取极值,令等式右边为0:

python应用EMD方法 python em算法_python_67

左右两边同时乘python应用EMD方法 python em算法_机器学习_68得到:

python应用EMD方法 python em算法_python应用EMD方法_69

python应用EMD方法 python em算法_python_70

python应用EMD方法 python em算法_python应用EMD方法_71

则:
python应用EMD方法 python em算法_nlp_72

2.接下来求解python应用EMD方法 python em算法_python_73:

python应用EMD方法 python em算法_python应用EMD方法_74

求取极值,令等式右边为0:

python应用EMD方法 python em算法_nlp_75

左右两边同时乘python应用EMD方法 python em算法_python_76得到:

python应用EMD方法 python em算法_人工智能_77

python应用EMD方法 python em算法_python_78

则:

python应用EMD方法 python em算法_机器学习_79

3.最后用同样的方法得到python应用EMD方法 python em算法_机器学习_80:

python应用EMD方法 python em算法_nlp_81

1.3.2 参数空间

1.模型参数
python应用EMD方法 python em算法_python_65: 硬币A正面的概率,在此模型中是一个float类型的数值
python应用EMD方法 python em算法_python_73: 硬币B正面的概率,在此模型中是一个float类型的数值
python应用EMD方法 python em算法_机器学习_80:硬币C正面的概率,在此模型中是一个float类型的数值
2.隐变量
python应用EMD方法 python em算法_机器学习_50: 最后观测值到底来源于B还是C,是一个一维向量
python应用EMD方法 python em算法_人工智能_86,其中python应用EMD方法 python em算法_nlp_47代表第python应用EMD方法 python em算法_机器学习_07次抛硬币B的概率。

1.4 EM算法的收敛性

证明EM算法的收敛,只需要证明python应用EMD方法 python em算法_人工智能_89是单调递增的即可:

python应用EMD方法 python em算法_python应用EMD方法_90

证明:
由于:

python应用EMD方法 python em算法_python应用EMD方法_91

取对数化简得:

python应用EMD方法 python em算法_机器学习_92

前两项有python应用EMD方法 python em算法_人工智能_93,对后两项进行计算:

python应用EMD方法 python em算法_人工智能_94

也即后面两项小于等于0,所以python应用EMD方法 python em算法_python应用EMD方法_95
得证。

2 三银币模型的Python实现
2.1 模型实现
import numpy as np
np.random.seed(0)


class ThreeCoinsMode(object):
    def __init__(self, n_epoch=5):
        """
        运用EM算法求解三银币模型
        :param n_epoch: 迭代次数
        """
        self.n_epoch = n_epoch
        self.params = {'pi': None, 'p': None, 'q': None, 'mu': None}

    def __init_params(self, n):
        """
        对参数初始化操作
        :param n: 观测样本个数
        :return: 
        """
        self.params = {'pi': np.random.rand(1),
                       'p': np.random.rand(1),
                       'q': np.random.rand(1),
                       'mu': np.random.rand(n)}
        # self.params = {'pi': [0.5],
        #                'p': [0.5],
        #                'q': [0.5],
        #                'mu': np.random.rand(n)}

    def E_step(self, y, n):
        """
        E步:跟新隐变量mu
        :param y: 观测样本
        :param n: 观测样本个数
        :return: 
        """
        pi = self.params['pi'][0]
        p = self.params['p'][0]
        q = self.params['q'][0]
        for i in range(n):
            self.params['mu'][i] = (pi * pow(p, y[i]) * pow(1-p, 1-y[i])) / (pi * pow(p, y[i]) * pow(1-p, 1-y[i]) + (1-pi) * pow(q, y[i]) * pow(1-q, 1-y[i]))

    def M_step(self, y, n):
        """
        M步:跟新模型参数
        :param y: 观测样本
        :param n: 观测样本个数
        :return: 
        """
        mu = self.params['mu']
        self.params['pi'][0] = sum(mu) / n
        self.params['p'][0] = sum([mu[i] * y[i] for i in range(n)]) / sum(mu)
        self.params['q'][0] = sum([(1-mu[i]) * y[i] for i in range(n)]) / sum([1-mu_i for mu_i in mu])

    def fit(self, y):
        """
        模型入口
        :param y: 观测样本
        :return: 
        """
        n = len(y)
        self.__init_params(n)
        print(0, self.params['pi'], self.params['p'], self.params['q'])
        for i in range(self.n_epoch):
            self.E_step(y, n)
            self.M_step(y, n)
            print(i+1, self.params['pi'], self.params['p'], self.params['q'])
2.2 模型测试结果
def run_three_coins_model():
    y = [1, 1, 0, 1, 0, 0, 1, 0, 1, 1]
    tcm = ThreeCoinsMode()
    tcm.fit(y)

运行结果:

0 [0.5488135] [0.71518937] [0.60276338]
1 [0.54076424] [0.65541668] [0.53474516]
2 [0.54076424] [0.65541668] [0.53474516]
3 [0.54076424] [0.65541668] [0.53474516]
4 [0.54076424] [0.65541668] [0.53474516]
5 [0.54076424] [0.65541668] [0.53474516]

参考文献:
《统计学习方法》 李航著