统计学习方法中算法实现(基于Python) --- EM算法

1.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(θ)

2.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算法是收敛的,但不能保证收敛到全局最优。

3.EM算法应用极其广泛,主要应用于含有隐变量的概率模型的学习。高斯混合模型的参数估计是EM算法的一个重要应用,下一章将要介绍的隐马尔可夫模型的非监督学习也是EM算法的一个重要应用。

4.EM算法还可以解释为 F F F函数的极大-极大算法。EM算法有许多变形,如GEM算法。GEM算法的特点是每次迭代增加 F F F函数值(并不一定是极大化 F F F函数),从而增加似然函数值。

在统计学中,似然函数(likelihood function,通常简写为likelihood,似然)是一个非常重要的内容,在非正式场合似然和概率(Probability)几乎是一对同义词,但是在统计学中似然和概率却是两个不同的概念。概率是在特定环境下某件事情发生的可能性,也就是结果没有产生之前依据环境所对应的参数来预测某件事情发生的可能性,比如抛硬币,抛之前我们不知道最后是哪一面朝上,但是根据硬币的性质我们可以推测任何一面朝上的可能性均为50%,这个概率只有在抛硬币之前才是有意义的,抛完硬币后的结果便是确定的;而似然刚好相反,是在确定的结果下去推测产生这个结果的可能环境(参数),还是抛硬币的例子,假设我们随机抛掷一枚硬币1,000次,结果500次人头朝上,500次数字朝上(实际情况一般不会这么理想,这里只是举个例子),我们很容易判断这是一枚标准的硬币,两面朝上的概率均为50%,这个过程就是我们运用出现的结果来判断这个事情本身的性质(参数),也就是似然。

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

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

在这里插入图片描述

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
Baum-Welch算法是一种无监督学习算法,用于对隐马尔可夫模型进行参数估计。以下是Python实现Baum-Welch算法的基本步骤: 1.初始化隐马尔可夫模型参数,包括隐藏状态转移矩阵、观测状态概率矩阵和初始状态概率向量。 2.根据初始化的参数,使用前向-后向算法计算每个时刻的前向概率和后向概率。 3.根据计算得到的前向概率和后向概率,使用EM算法迭代更新模型参数。 4.重复步骤2和3,直到模型参数收敛或达到最大迭代次数。 下面是一个简单的Python实现Baum-Welch算法的代码示例: ```python import numpy as np def baum_welch(obs, states, n_iter=100): n_states = len(states) n_obs = len(obs) # 随机初始化模型参数 A = np.random.rand(n_states, n_states) B = np.random.rand(n_states, n_obs) pi = np.random.rand(n_states) # 归一化模型参数 A /= np.sum(A, axis=1, keepdims=True) B /= np.sum(B, axis=1, keepdims=True) pi /= np.sum(pi) # 迭代更新模型参数 for i in range(n_iter): alpha, beta, gamma, xi = calc_probs(obs, states, A, B, pi) # 更新参数 A_new = np.sum(xi, axis=0) / np.sum(gamma[:, :-1], axis=1, keepdims=True) B_new = np.sum(gamma[:, obs], axis=1) / np.sum(gamma, axis=1, keepdims=True) pi_new = gamma[:, 0] / np.sum(gamma[:, 0]) # 归一化参数 A_new /= np.sum(A_new, axis=1, keepdims=True) B_new /= np.sum(B_new, axis=1, keepdims=True) pi_new /= np.sum(pi_new) # 判断模型参数是否收敛 if np.allclose(A, A_new) and np.allclose(B, B_new) and np.allclose(pi, pi_new): break else: A, B, pi = A_new, B_new, pi_new return A, B, pi def calc_probs(obs, states, A, B, pi): n_states = len(states) n_obs = len(obs) alpha = np.zeros((n_states, n_obs)) beta = np.zeros((n_states, n_obs)) gamma = np.zeros((n_states, n_obs)) xi = np.zeros((n_states, n_states, n_obs-1)) # 计算前向概率和后向概率 for t in range(n_obs): if t == 0: alpha[:, t] = pi * B[:, obs[t]] beta[:, -1] = 1 else: alpha[:, t] = np.sum(alpha[:, t-1] * A.T, axis=1) * B[:, obs[t]] beta[:, -t-1] = np.sum(A * B[:, obs[-t:]] * beta[:, -t], axis=1) gamma[:, t] = alpha[:, t] * beta[:, t] / np.sum(alpha[:, t] * beta[:, t]) # 计算转移概率和发射概率 for t in range(n_obs-1): xi[:, :, t] = A * alpha[:, t].reshape(-1, 1) * B[:, obs[t+1]].reshape(1, -1) * beta[:, t+1].reshape(1, -1) xi[:, :, t] /= np.sum(xi[:, :, t]) return alpha, beta, gamma, xi ``` 这里的输入参数obs表示观测序列,states表示隐藏状态集合,n_iter表示最大迭代次数。输出参数A、B和pi分别表示隐马尔可夫模型的隐藏状态转移矩阵、观测状态概率矩阵和初始状态概率向量。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Systemd

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值