EM 算法 实例

#coding:utf-8
import math
import copy
import numpy as np
import matplotlib.pyplot as plt

isdebug = True

#指定k个高斯分布参数,这里指定k=2。
#注意2个高斯分布具有相同方差Sigma,均值分别为Mu1,Mu2。
#共1000个数据

#生成训练样本,输入6,40,20,2  
#两类样本方差为6,
#一类均值为20,一类为40
#随机生成1000个数
def ini_data(Sigma,Mu1,Mu2,k,N): 
  #保存生成的随机样本
  global X 

  #求类别的均值
  global Mu 
  #保存样本属于某类的概率
  global Expectations 

  #1*N的矩阵,生成N个样本
  X = np.zeros((1,N)) 
  #任意给定两个初始值,任猜两类均值
  #赋值一次即可,最后要输出的量
  Mu = np.random.random(2) #0-1之间
  print Mu
  #给定1000*2的矩阵,保存样本属于某类的概率
  Expectations = np.zeros((N,k)) 

  #生成N个样本数据 
  for i in xrange(0,N): 
    #在大于0.5在第1个分布,小于0.5在第2个分布
    if np.random.random(1) > 0.5: 
      #均值40加上方差倍数,样本数据满足N(40,Sigma)正态分布
      X[0,i] = np.random.normal()*Sigma + Mu1 #
    else:
      #均值40加上方差倍数,样本数据满足N(20,Sigma)正态分布
      X[0,i] = np.random.normal()*Sigma + Mu2 

  if isdebug:
    print "***********"
    print u"初始观测数据X:"
    print X


#E步 计算每个样本属于男女各自的概率
#输入:方差Sigma,类别k,样本数N
def e_step(Sigma,k,N):
  #样本属于某类概率
  global Expectations
  #两类均值
  global Mu
  #样本
  global X

  #遍历所有样本点,计算属于每个类别的概率
  for i in xrange(0,N):
    #分母,用于归一化
    Denom = 0
    #遍历男女两类,计算各自归一化分母
    for j in xrange(0,k):
      #计算分母
      Denom += math.exp((-1/(2*(float(Sigma**2))))*(float(X[0,i]-Mu[j]))**2)

    #遍历男女两类,计算各自分子部分
    for j in xrange(0,k):
      #分子
      Numer = math.exp((-1/(2*(float(Sigma**2))))*(float(X[0,i]-Mu[j]))**2)
      #每个样本属于该类别的概率
      Expectations[i,j] = Numer/Denom

  if isdebug:
    print "***********"
    print u"隐藏变量E(Z):"
    print len(Expectations)
    #数据总个数
    print Expectations.size
    #矩阵数据
    print Expectations.shape
    #打印出隐藏变量的值
    print Expectations


#M步 期望最大化
def m_step(k,N):
  #样本属于某类概率P(k|xi)
  global Expectations
  #样本
  global X
  #计算两类的均值
  #遍历两类
  for j in xrange(0,k):
    Numer = 0
    Denom = 0
    #当前类别下,遍历所有样本
    #计算该类别下的均值和方差
    for i in xrange(0,N):
      #该类别样本分布P(k|xi)xi
      Numer += Expectations[i,j]*X[0,i]
      #该类别类样本总数Nk,Nk等于P(k|xi)求和
      Denom +=Expectations[i,j]
    #计算每个类别各自均值uk
    Mu[j] = Numer / Denom


#算法迭代iter_num次,或达到精度Epsilon停止迭代
#迭代次数1000次, 误差达到0.0001终止
#输入:两类相同方差Sigma,一类均值Mu1,一类均值Mu2
#类别数k,样本数N,迭代次数iter_num,可接受精度Epsilon
def run(Sigma,Mu1,Mu2,k,N,iter_num,Epsilon):
  #生成训练样本
  ini_data(Sigma,Mu1,Mu2,k,N)
  print u"初始<u1,u2>:", Mu

  #迭代1000次
  for i in range(iter_num):
    #保存上次两类均值
    Old_Mu = copy.deepcopy(Mu)
    #E步
    e_step(Sigma,k,N)
    #M步
    m_step(k,N)

    #输出当前迭代次数及当前估计的值
    print i,Mu

    #判断误差
    if sum(abs(Mu-Old_Mu)) < Epsilon:
      break

if __name__ == '__main__':

  #sigma,mu1,mu2,模型数,样本总数,迭代次数,迭代终止收敛精度
   run(6,40,20,2,1000,1000,0.0001)
   plt.hist(X[0,:],100) #柱状图的宽度
   plt.show()




  • 1
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
以下是一个简单的 EM 算法的 Python 代码实例,用于估计高斯混合模型的参数: ```python import numpy as np # 初始化高斯混合模型参数 def init_params(data, k): n = data.shape[0] d = data.shape[1] # 初始化权重 weights = np.ones(k) / k # 初始化均值 means = np.random.randn(k, d) # 初始化协方差矩阵 covs = np.zeros((k, d, d)) for i in range(k): covs[i] = np.eye(d) return weights, means, covs # E 步 def e_step(data, weights, means, covs): k = weights.shape[0] n = data.shape[0] # 初始化后验概率矩阵 gamma = np.zeros((n, k)) # 计算后验概率 for i in range(n): for j in range(k): gamma[i, j] = weights[j] * normal_pdf(data[i], means[j], covs[j]) gamma[i] /= np.sum(gamma[i]) return gamma # M 步 def m_step(data, gamma): k = gamma.shape[1] n = data.shape[0] d = data.shape[1] # 更新权重 weights = np.sum(gamma, axis=0) / n # 更新均值 means = np.zeros((k, d)) for j in range(k): for i in range(n): means[j] += gamma[i, j] * data[i] means[j] /= np.sum(gamma[:, j]) # 更新协方差矩阵 covs = np.zeros((k, d, d)) for j in range(k): for i in range(n): diff = data[i] - means[j] covs[j] += gamma[i, j] * np.outer(diff, diff) covs[j] /= np.sum(gamma[:, j]) return weights, means, covs # 计算多元高斯分布密度函数值 def normal_pdf(x, mean, cov): d = x.shape[0] coeff = 1.0 / np.sqrt((2*np.pi)**d * np.linalg.det(cov)) diff = x - mean exponent = -0.5 * np.dot(np.dot(diff.T, np.linalg.inv(cov)), diff) return coeff * np.exp(exponent) # EM 算法 def em_algorithm(data, k, max_iter): weights, means, covs = init_params(data, k) for i in range(max_iter): gamma = e_step(data, weights, means, covs) weights, means, covs = m_step(data, gamma) return weights, means, covs ``` 其中,`data` 是输入数据,`k` 是高斯混合模型的个数,`max_iter` 是最大迭代次数。在 `init_params` 函数中,我们通过随机初始化来初始化高斯混合模型的参数。在 `e_step` 函数中,我们计算后验概率矩阵。在 `m_step` 函数中,我们使用后验概率矩阵来更新高斯混合模型的参数。在 `normal_pdf` 函数中,我们计算多元高斯分布密度函数值。最后,在 `em_algorithm` 函数中,我们使用 EM 算法来估计高斯混合模型的参数。

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值