• 《统计学习方法》 第九章 EM算法(原理+代码)


    EM算法

    EM算法是含有隐变量的概率模型极大似然估计或极大后验概率估计的迭代算法

    含有隐变量的概率模型的数据表示为 θ \theta θ

    这里, Y Y Y是观测变量的数据, Z Z Z是隐变量的数据, θ \theta θ 是模型参数

    EM算法通过迭代求解观测数据的对数似然函数

    L ( θ ) = log ⁡ P ( Y ∣ θ ) {L}(\theta)=\log {P}(\mathrm{Y} | \theta) L(θ)=logP(Yθ)的极大化,实现极大似然估计


    每次迭代包括两步

    E E E步,求期望

    即求 l o g P ( Z ∣ Y , θ ) logP\left(Z | Y, \theta\right) logP(ZY,θ) )关于 P ( Z ∣ Y , θ ( i ) ) P\left(Z | Y, \theta^{(i)}\right) P(ZY,θ(i)))的期望:

    Q ( θ , θ ( i ) ) = ∑ Z log ⁡ P ( Y , Z ∣ θ ) P ( Z ∣ Y , θ ( i ) ) Q\left(\theta, \theta^{(i)}\right)=\sum_{Z} \log P(Y, Z | \theta) P\left(Z | Y, \theta^{(i)}\right) Q(θ,θ(i))=ZlogP(Y,Zθ)P(ZY,θ(i))

    称为 Q Q Q函数

    这里 θ ( i ) \theta^{(i)} θ(i)是参数的现估计值

    M M M步,求极大

    即极大化 Q Q Q函数得到参数的新估计值

    θ ( i + 1 ) = arg ⁡ max ⁡ θ Q ( θ , θ ( i ) ) \theta^{(i+1)}=\arg \max _{\theta} Q\left(\theta, \theta^{(i)}\right) θ(i+1)=argθmaxQ(θ,θ(i))

    在构建具体的EM算法时,重要的是定义 Q Q Q函数

    每次迭代中,EM算法通过极大化 Q Q Q函数来增大对数似然函数 L ( θ ) {L}(\theta) L(θ)


    E M EM EM算法在每次迭代后均提高观测数据的似然函数值,即

    P ( Y ∣ θ ( i + 1 ) ) ⩾ P ( Y ∣ θ ( i ) ) P\left(Y | \theta^{(i+1)}\right) \geqslant P\left(Y | \theta^{(i)}\right) P(Yθ(i+1))P(Yθ(i))

    在一般条件下EM算法是收敛的,但不能保证收敛到全局最优。


    E M EM EM算法应用极其广泛

    主要应用于含有隐变量的概率模型的学习

    高斯混合模型的参数估计是EM算法的一个重要应用

    隐马尔可夫模型的非监督学习也是EM算法的一个重要应用


    E M EM EM算法还可以解释为 F F F函数的极大-极大算法

    E M EM EM算法有许多变形,如GEM算法

    G E M GEM GEM算法的特点是每次迭代增加 F F F函数值(并不一定是极大化 F F F函数),从而增加似然函数值

    P ( Y ∣ θ ) = ∏ [ π p y i ( 1 − p ) 1 − y i + ( 1 − π ) q y i ( 1 − q ) 1 − y i ] P(Y|\theta) = \prod[\pi p^{y_i}(1-p)^{1-y_i}+(1-\pi) q^{y_i}(1-q)^{1-y_i}] P(Yθ)=[πpyi(1p)1yi+(1π)qyi(1q)1yi]


    代码实现

    E step:

    μ i + 1 = π ( p i ) y i ( 1 − ( p i ) ) 1 − y i π ( p i ) y i ( 1 − ( p i ) ) 1 − y i + ( 1 − π ) ( q i ) y i ( 1 − ( q i ) ) 1 − y i \mu^{i+1}=\frac{\pi (p^i)^{y_i}(1-(p^i))^{1-y_i}}{\pi (p^i)^{y_i}(1-(p^i))^{1-y_i}+(1-\pi) (q^i)^{y_i}(1-(q^i))^{1-y_i}} μi+1=π(pi)yi(1(pi))1yi+(1π)(qi)yi(1(qi))1yiπ(pi)yi(1(pi))1yi

    def pmf(i, pro_A, pro_B, por_C):
        pro_1 = pro_A * math.pow(pro_B, data[i]) * math.pow(
            (1 - pro_B), 1 - data[i])
        pro_2 = pro_A * math.pow(pro_C, data[i]) * math.pow(
            (1 - pro_C), 1 - data[i])
        return pro_1 / (pro_1 + pro_2)
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6

    M step:

    π i + 1 = 1 n ∑ j = 1 n μ j i + 1 \pi^{i+1}=\frac{1}{n}\sum_{j=1}^n\mu^{i+1}_j πi+1=n1j=1nμji+1

    p i + 1 = ∑ j = 1 n μ j i + 1 y i ∑ j = 1 n μ j i + 1 p^{i+1}=\frac{\sum_{j=1}^n\mu^{i+1}_jy_i}{\sum_{j=1}^n\mu^{i+1}_j} pi+1=j=1nμji+1j=1nμji+1yi

    q i + 1 = ∑ j = 1 n ( 1 − μ j i + 1 y i ) ∑ j = 1 n ( 1 − μ j i + 1 ) q^{i+1}=\frac{\sum_{j=1}^n(1-\mu^{i+1}_jy_i)}{\sum_{j=1}^n(1-\mu^{i+1}_j)} qi+1=j=1n(1μji+1)j=1n(1μji+1yi)

    class EM:
        def __init__(self, prob):
            self.pro_A, self.pro_B, self.pro_C = prob
    
        # e_step
        def pmf(self, i):
            pro_1 = self.pro_A * math.pow(self.pro_B, data[i]) * math.pow(
                (1 - self.pro_B), 1 - data[i])
            pro_2 = (1 - self.pro_A) * math.pow(self.pro_C, data[i]) * math.pow(
                (1 - self.pro_C), 1 - data[i])
            return pro_1 / (pro_1 + pro_2)
    
        # m_step
        def fit(self, data):
            count = len(data)
            print('init prob:{}, {}, {}'.format(self.pro_A, self.pro_B,
                                                self.pro_C))
            for d in range(count):
                _ = yield
                _pmf = [self.pmf(k) for k in range(count)]
                pro_A = 1 / count * sum(_pmf)
                pro_B = sum([_pmf[k] * data[k] for k in range(count)]) / sum(
                    [_pmf[k] for k in range(count)])
                pro_C = sum([(1 - _pmf[k]) * data[k]
                             for k in range(count)]) / sum([(1 - _pmf[k])
                                                            for k in range(count)])
                print('{}/{}  pro_a:{:.3f}, pro_b:{:.3f}, pro_c:{:.3f}'.format(
                    d + 1, count, pro_A, pro_B, pro_C))
                self.pro_A = pro_A
                self.pro_B = pro_B
                self.pro_C = pro_C
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
  • 相关阅读:
    Redis03-过期策略和淘汰策略
    Ajax--form表单与模板引擎--模板引擎的基本概念 - art-template模板引擎
    uni-app 封装api请求
    Spring复习之——IoC和AOP
    【编译原理】-- 递归下降语法分析设计原理与实现(C语言实现)
    vscode快捷键设置
    webpack插件开发必会Tapable
    【技术积累】Linux中的命令行【理论篇】【八】
    vuex的模块化和namespaced
    ECMAScript 6(es6)
  • 原文地址:https://blog.csdn.net/qq_38973721/article/details/128067368