1. 求解抛硬币的参数
(1)首先给出样本数据及说明
  • 现在有A,B,C三个硬币,正面出现的概率分别为 python抛硬币100次输出概率_概率模型,python抛硬币100次输出概率_EM算法_02,python抛硬币100次输出概率_python抛硬币100次输出概率_03
  • 抛硬币的步骤:首先抛硬币A,硬币A正面朝上接下来抛硬币B,否则抛硬币C。
  • 现在得到的样本数据为: 1,1,0,1,0,0,1,0,1,1
(2)建立参数估计模型
  • 假定未知的模型参数 python抛硬币100次输出概率_EM算法_04,每次抛掷硬币A(隐变量)的数据结果为 python抛硬币100次输出概率_高斯混合模型_05,硬币B、C(观测变量)正反面的结果为 python抛硬币100次输出概率_概率模型_06
    python抛硬币100次输出概率_概率模型_07
  • 假定观测数据 python抛硬币100次输出概率_EM算法_08,观测次数为 python抛硬币100次输出概率_参数估计_09,则最大似然估计的公式为
    python抛硬币100次输出概率_高斯混合模型_10
    其中 python抛硬币100次输出概率_概率模型_11
(3)采用EM的步骤
  • 计算隐变量
    假定此时估计的 python抛硬币100次输出概率_EM算法_12
    观测数据来自B的概率为:
    python抛硬币100次输出概率_EM算法_13
    观测数据来自C的概率为:
    python抛硬币100次输出概率_参数估计_14
  • 此时对观测数据来自 B 的概率取平均值就可以得到参数 python抛硬币100次输出概率_高斯混合模型_15
    类似的可以得到
    python抛硬币100次输出概率_概率模型_16
  • 这里面仿真的是对于不同的初值最终 EM 算法会收敛到不同的概率预测值
sample = [1,1,0,1,0,0,1,0,1,1]
times = 20 #设定迭代参数为 20次
mu = []
def coin_EM(pi,p,q):
    pi_copy = pi
    q_copy = q
    p_copy = p
    for i in range(times):
        sum_p = 0
        sum_q = 0
        for flap in sample:
            if flap == 0:
                mu.append(pi*(1-p)/(pi*(1-p)+(1-pi)*(1-q)))
            else:
                mu.append(pi*p/(pi*p+(1-pi)*q))
                sum_p = sum_p + pi*p/(pi*p+(1-pi)*q)
                sum_q = sum_q + 1 - pi*p/(pi*p+(1-pi)*q)
        pi = sum(mu)/len(sample)
        p = sum_p/sum(mu)
        q = sum_q/(len(sample) - sum(mu))
        mu.clear()
    print("给定的初值分别为:")
    print("pi = {:.4f} , p = {:.4f} , q = {:.4f}".format(pi_copy,p_copy,q_copy))
    print("迭代得到的终值分别为:")
    print("pi = {:.4f} , p = {:.4f} , q = {:.4f}".format(pi,p,q))
    
    
def MLE(pi,p,q):
    index_one = 0
    index_zero = 0
    for clap in sample:
        if clap == 1:
            index_one = index_one + 1
    index_zero = len(sample) - index_one
    proability = pow(pi * p + (1-pi) * q,index_one) \
    * pow(pi * (1-p) + (1-pi) * (1-q),index_zero)
    print("对这一组的最大似然结果为:{:.5f}".format(proability))
    
print("第一组:")
coin_EM(0.46,0.55,0.67)
MLE(0.46,0.55,0.67)
print("###############################################")
print("第二组:")
coin_EM(0.5,0.5,0.5)
MLE(0.5,0.5,0.5)
print("###############################################")
print("第三组:")
coin_EM(0.4,0.6,0.7)
MLE(0.4,0.6,0.7)
#结果
第一组:
给定的初值分别为:
pi = 0.4600 , p = 0.5500 , q = 0.6700
迭代得到的终值分别为:
pi = 0.4619 , p = 0.5346 , q = 0.6561
对这一组的最大似然结果为:0.00119
###############################################
第二组:
给定的初值分别为:
pi = 0.5000 , p = 0.5000 , q = 0.5000
迭代得到的终值分别为:
pi = 0.5000 , p = 0.6000 , q = 0.6000
对这一组的最大似然结果为:0.00098
###############################################
第三组:
给定的初值分别为:
pi = 0.4000 , p = 0.6000 , q = 0.7000
迭代得到的终值分别为:
pi = 0.4064 , p = 0.5368 , q = 0.6432
对这一组的最大似然结果为:0.00110
2. 求解混合高斯分布的参数
(1)首先生成并展示出混合高斯分布的数据
  • 高斯混合模型的概率分布如下:
    python抛硬币100次输出概率_EM算法_17
    参数为 python抛硬币100次输出概率_概率模型_18,且其中 python抛硬币100次输出概率_概率模型_19 是系数(表示从各模型抽取的概率),python抛硬币100次输出概率_高斯混合模型_20 是高斯分布密度,python抛硬币100次输出概率_参数估计_21,第 python抛硬币100次输出概率_python抛硬币100次输出概率_22 个分模型的概率密度函数是
    python抛硬币100次输出概率_参数估计_23
  • 假定样本是从三个一维高斯分布中抽取出来的,抽取的概率分别为:
    python抛硬币100次输出概率_参数估计_24
  • 这三个高斯函数的参数分别为:(python抛硬币100次输出概率_EM算法_25) = (1,2) , (python抛硬币100次输出概率_EM算法_26) = (2,1),(python抛硬币100次输出概率_python抛硬币100次输出概率_27) = (4,8)
%matplotlib inline
import numpy as np
import matplotlib.pyplot as plt
#下面完成50000次取样
times = 50000
choice = np.random.choice([1,2,3],size = (1,times),p = [1/2,1/3,1/6]).tolist()
sample_list = []
for i in choice[0]:
    if i == 1:
        sample_list.append(np.random.normal(1,2,1).item())
    elif i == 2:
        sample_list.append(np.random.normal(2,1,1).item())
    else:
        sample_list.append(np.random.normal(4,8,1).item())

sample_list = np.array(sample_list)

bins = np.arange(-5,10,0.1)

plt.hist(sample_list,bins)
plt.show()




python抛硬币100次输出概率_python抛硬币100次输出概率_28


(2)EM的理论算法流程
  • 明确隐变量,写出完全数据的对数似然函数
    观测数据 python抛硬币100次输出概率_概率模型_29,反映观测数据 python抛硬币100次输出概率_EM算法_30 来自第 python抛硬币100次输出概率_python抛硬币100次输出概率_22 个分模型的隐变量 python抛硬币100次输出概率_python抛硬币100次输出概率_32
    python抛硬币100次输出概率_python抛硬币100次输出概率_33
    综合观测数据和未观测数据可以得到完全数据是 python抛硬币100次输出概率_概率模型_34
    写出完全数据的似然函数
    python抛硬币100次输出概率_python抛硬币100次输出概率_35
    其中 python抛硬币100次输出概率_参数估计_36python抛硬币100次输出概率_python抛硬币100次输出概率_37
    变成对数形式 python抛硬币100次输出概率_概率模型_38
  • E步:确定 Q 函数
    python抛硬币100次输出概率_参数估计_39
    其中 python抛硬币100次输出概率_python抛硬币100次输出概率_40
  • M步:确定 python抛硬币100次输出概率_python抛硬币100次输出概率_41
    python抛硬币100次输出概率_概率模型_42
    通过求偏导可得
    python抛硬币100次输出概率_EM算法_43
(3)EM的编程算法流程
  • EM 的步骤:
    输入:观测数据 python抛硬币100次输出概率_概率模型_29,高斯混合模型;
    输出:高斯混合模型参数
  • 取参数的初始值并开始迭代。
  • E步:依据当前模型参数,计算分模型python抛硬币100次输出概率_python抛硬币100次输出概率_22对观测数据python抛硬币100次输出概率_概率模型_46的响应度

python抛硬币100次输出概率_python抛硬币100次输出概率_47

  • M步:计算新一轮的迭代参数

python抛硬币100次输出概率_参数估计_48

(3)在这个例子中的EM
  • 在这里总共有50000个样本,因此python抛硬币100次输出概率_高斯混合模型_49。总共有3个高斯分布,因此python抛硬币100次输出概率_python抛硬币100次输出概率_50
  • 给出初始迭代值
    python抛硬币100次输出概率_参数估计_51
    (python抛硬币100次输出概率_概率模型_52) = (1,1) , (python抛硬币100次输出概率_参数估计_53) = (2,2), (python抛硬币100次输出概率_参数估计_54) = (3,3)
  • 得到的迭代收敛值
    得到的概率值为:python抛硬币100次输出概率_EM算法_55
    得到的分布为:(python抛硬币100次输出概率_概率模型_52) = (1,1) , (python抛硬币100次输出概率_参数估计_53) = (1,1), (python抛硬币100次输出概率_参数估计_54) = (2,5)
import scipy.stats
gamma = np.empty([times,3])
p = np.array([1 / 4, 1 / 2, 1 / 4])
mu = np.array([1, 2, 3])
std = np.array([1, 2, 3])
#这里设定迭代次数为1000次
iteration = 1000

# 这里进行 E-step的操作
def E_step():
    calculate_temp = np.empty((times,3))
    for k in range(3):
        calculate_temp[:, k] = p[k] * scipy.stats.norm(mu[k], std[k]).pdf(sample_list)
    divide_temp = np.sum(calculate_temp, axis=1).reshape(times, )
    for k in range(3):
        gamma[:, k] = calculate_temp[:, k] / divide_temp

#这里进行M-step的操作
def M_step():
    for k in range(3):
        # 这里更新mu的值
        mu[k] = np.divide(np.sum(gamma[:,k] * sample_list) ,np.sum(gamma[:,k]))
        # 这里更新std的值
        std[k] = np.sqrt(np.sum(gamma[:,k] * np.square(sample_list - mu[k]))/np.sum(gamma[:,k]))
        # 这里更新p的值
        p[k] = np.sum(gamma[:,k]) / times

        
for cnt in  np.arange(iteration):   
    E_step()
    M_step()
print("得到的概率值为:p1 = {:.2f},p2 = {:.2f},p3 = {:.2f}".format(p[0],p[1],p[2]))
print("得到的分布为:(mu1,std1) = ({},{}) (mu2,std2) = ({},{}) (mu3,std3) = ({},{})".format(mu[0],std[0],mu[1],std[1],mu[2],std[2]))
(4)画出EM计算出的结果
import math
EM_lis = np.arange(-5,10,0.1)
EM_draw = np.zeros(EM_lis.shape)

for j in range(3):
    EM_draw = EM_draw + scipy.stats.norm(mu[j],std[j]).pdf(EM_lis)* p[j]
#下面乘以4500只是做一个scale,并没有其他的含义
plt.plot(EM_lis,EM_draw*4500)
plt.hist(sample_list,bins)
plt.show()



python抛硬币100次输出概率_EM算法_59