python em算法的实现


Posted in Python onOctober 03, 2020
'''
数据集:伪造数据集(两个高斯分布混合)
数据集长度:1000
------------------------------
运行结果:
----------------------------
the Parameters set is:
alpha0:0.3, mu0:0.7, sigmod0:-2.0, alpha1:0.5, mu1:0.5, sigmod1:1.0
----------------------------
the Parameters predict is:
alpha0:0.4, mu0:0.6, sigmod0:-1.7, alpha1:0.7, mu1:0.7, sigmod1:0.9
----------------------------
'''

import numpy as np
import random
import math
import time

def loadData(mu0, sigma0, mu1, sigma1, alpha0, alpha1):
  '''
  初始化数据集
  这里通过服从高斯分布的随机函数来伪造数据集
  :param mu0: 高斯0的均值
  :param sigma0: 高斯0的方差
  :param mu1: 高斯1的均值
  :param sigma1: 高斯1的方差
  :param alpha0: 高斯0的系数
  :param alpha1: 高斯1的系数
  :return: 混合了两个高斯分布的数据
  '''
  # 定义数据集长度为1000
  length = 1000

  # 初始化第一个高斯分布,生成数据,数据长度为length * alpha系数,以此来
  # 满足alpha的作用
  data0 = np.random.normal(mu0, sigma0, int(length * alpha0))
  # 第二个高斯分布的数据
  data1 = np.random.normal(mu1, sigma1, int(length * alpha1))

  # 初始化总数据集
  # 两个高斯分布的数据混合后会放在该数据集中返回
  dataSet = []
  # 将第一个数据集的内容添加进去
  dataSet.extend(data0)
  # 添加第二个数据集的数据
  dataSet.extend(data1)
  # 对总的数据集进行打乱(其实不打乱也没事,只不过打乱一下直观上让人感觉已经混合了
  # 读者可以将下面这句话屏蔽以后看看效果是否有差别)
  random.shuffle(dataSet)

  #返回伪造好的数据集
  return dataSet

def calcGauss(dataSetArr, mu, sigmod):
  '''
  根据高斯密度函数计算值
  依据:“9.3.1 高斯混合模型” 式9.25
  注:在公式中y是一个实数,但是在EM算法中(见算法9.2的E步),需要对每个j
  都求一次yjk,在本实例中有1000个可观测数据,因此需要计算1000次。考虑到
  在E步时进行1000次高斯计算,程序上比较不简洁,因此这里的y是向量,在numpy
  的exp中如果exp内部值为向量,则对向量中每个值进行exp,输出仍是向量的形式。
  所以使用向量的形式1次计算即可将所有计算结果得出,程序上较为简洁
  :param dataSetArr: 可观测数据集
  :param mu: 均值
  :param sigmod: 方差
  :return: 整个可观测数据集的高斯分布密度(向量形式)
  '''
  # 计算过程就是依据式9.25写的,没有别的花样
  result = (1 / (math.sqrt(2*math.pi)*sigmod**2)) * np.exp(-1 * (dataSetArr-mu) * (dataSetArr-mu) / (2*sigmod**2))
  # 返回结果
  return result


def E_step(dataSetArr, alpha0, mu0, sigmod0, alpha1, mu1, sigmod1):
  '''
  EM算法中的E步
  依据当前模型参数,计算分模型k对观数据y的响应度
  :param dataSetArr: 可观测数据y
  :param alpha0: 高斯模型0的系数
  :param mu0: 高斯模型0的均值
  :param sigmod0: 高斯模型0的方差
  :param alpha1: 高斯模型1的系数
  :param mu1: 高斯模型1的均值
  :param sigmod1: 高斯模型1的方差
  :return: 两个模型各自的响应度
  '''
  # 计算y0的响应度
  # 先计算模型0的响应度的分子
  gamma0 = alpha0 * calcGauss(dataSetArr, mu0, sigmod0)
  # 模型1响应度的分子
  gamma1 = alpha1 * calcGauss(dataSetArr, mu1, sigmod1)

  # 两者相加为E步中的分布
  sum = gamma0 + gamma1
  # 各自相除,得到两个模型的响应度
  gamma0 = gamma0 / sum
  gamma1 = gamma1 / sum

  # 返回两个模型响应度
  return gamma0, gamma1

def M_step(muo, mu1, gamma0, gamma1, dataSetArr):
  # 依据算法9.2计算各个值
  # 这里没什么花样,对照书本公式看看这里就好了
  mu0_new = np.dot(gamma0, dataSetArr) / np.sum(gamma0)
  mu1_new = np.dot(gamma1, dataSetArr) / np.sum(gamma1)

  sigmod0_new = math.sqrt(np.dot(gamma0, (dataSetArr - muo)**2) / np.sum(gamma0))
  sigmod1_new = math.sqrt(np.dot(gamma1, (dataSetArr - mu1)**2) / np.sum(gamma1))

  alpha0_new = np.sum(gamma0) / len(gamma0)
  alpha1_new = np.sum(gamma1) / len(gamma1)

  # 将更新的值返回
  return mu0_new, mu1_new, sigmod0_new, sigmod1_new, alpha0_new, alpha1_new


def EM_Train(dataSetList, iter=500):
  '''
  根据EM算法进行参数估计
  算法依据“9.3.2 高斯混合模型参数估计的EM算法” 算法9.2
  :param dataSetList:数据集(可观测数据)
  :param iter: 迭代次数
  :return: 估计的参数
  '''
  # 将可观测数据y转换为数组形式,主要是为了方便后续运算
  dataSetArr = np.array(dataSetList)

  # 步骤1:对参数取初值,开始迭代
  alpha0 = 0.5
  mu0 = 0
  sigmod0 = 1
  alpha1 = 0.5
  mu1 = 1
  sigmod1 = 1

  # 开始迭代
  step = 0
  while (step < iter):
    # 每次进入一次迭代后迭代次数加1
    step += 1
    # 步骤2:E步:依据当前模型参数,计算分模型k对观测数据y的响应度
    gamma0, gamma1 = E_step(dataSetArr, alpha0, mu0, sigmod0, alpha1, mu1, sigmod1)
    # 步骤3:M步
    mu0, mu1, sigmod0, sigmod1, alpha0, alpha1 = M_step(mu0, mu1, gamma0, gamma1, dataSetArr)

  # 迭代结束后将更新后的各参数返回
  return alpha0, mu0, sigmod0, alpha1, mu1, sigmod1


if __name__ == '__main__':
  start = time.time()

  # 设置两个高斯模型进行混合,这里是初始化两个模型各自的参数
  # 见“9.3 EM算法在高斯混合模型学习中的应用”
  # alpha是“9.3.1 高斯混合模型” 定义9.2中的系数α
  # mu0是均值μ
  # sigmod是方差σ
  # 在设置上两个alpha的和必须为1,其他没有什么具体要求,符合高斯定义就可以
  alpha0 = 0.3 # 系数α
  mu0 = -2 # 均值μ
  sigmod0 = 0.5 # 方差σ

  alpha1 = 0.7 # 系数α
  mu1 = 0.5 # 均值μ
  sigmod1 = 1 # 方差σ

  # 初始化数据集
  dataSetList = loadData(mu0, sigmod0, mu1, sigmod1, alpha0, alpha1)

  #打印设置的参数
  print('---------------------------')
  print('the Parameters set is:')
  print('alpha0:%.1f, mu0:%.1f, sigmod0:%.1f, alpha1:%.1f, mu1:%.1f, sigmod1:%.1f' % (
    alpha0, alpha1, mu0, mu1, sigmod0, sigmod1
  ))

  # 开始EM算法,进行参数估计
  alpha0, mu0, sigmod0, alpha1, mu1, sigmod1 = EM_Train(dataSetList)

  # 打印参数预测结果
  print('----------------------------')
  print('the Parameters predict is:')
  print('alpha0:%.1f, mu0:%.1f, sigmod0:%.1f, alpha1:%.1f, mu1:%.1f, sigmod1:%.1f' % (
    alpha0, alpha1, mu0, mu1, sigmod0, sigmod1
  ))

  # 打印时间
  print('----------------------------')
  print('time span:', time.time() - start)

以上就是python em算法的实现的详细内容,更多关于python em算法的资料请关注三水点靠木其它相关文章!

Python 相关文章推荐
python中PIL安装简单教程
Apr 21 Python
python处理csv中的空值方法
Jun 22 Python
pycharm debug功能实现跳到循环末尾的方法
Nov 29 Python
python列表使用实现名字管理系统
Jan 30 Python
Python3.4解释器用法简单示例
Mar 22 Python
wxpython绘制圆角窗体
Nov 18 Python
python 循环数据赋值实例
Dec 02 Python
Python 利用OpenCV给照片换底色的示例代码
Aug 03 Python
利用Python将图片中扭曲矩形的复原
Sep 07 Python
matplotlib绘制鼠标的十字光标的实现(内置方式)
Jan 06 Python
pytorch model.cuda()花费时间很长的解决
Jun 01 Python
对象析构函数__del__在Python中何时使用
Mar 22 Python
浅析Python中字符串的intern机制
Oct 03 #Python
Python实现AES加密,解密的两种方法
Oct 03 #Python
python实现AdaBoost算法的示例
Oct 03 #Python
Django创建一个后台的基本步骤记录
Oct 02 #Python
Python中qutip用法示例详解
Oct 02 #Python
如何利用Python给自己的头像加一个小国旗(小月饼)
Oct 02 #Python
Python通过fnmatch模块实现文件名匹配
Sep 30 #Python
You might like
PHP令牌 Token改进版
2008/07/18 PHP
2014最热门的24个php类库汇总
2014/12/18 PHP
PHP函数import_request_variables()用法分析
2016/04/02 PHP
php app支付宝回调(异步通知)详解
2018/07/25 PHP
解决FLASH需要点击激活的代码
2006/12/20 Javascript
经典的解除许多网站无法复制文字的绝招
2006/12/31 Javascript
Extjs学习笔记之六 面版
2010/01/08 Javascript
javascript高级程序设计第二版第十二章事件要点总结(常用的跨浏览器检测方法)
2012/08/22 Javascript
jquery实现select选中行、列合计示例
2014/04/25 Javascript
js获取窗口相对于屏幕左边和上边的位置坐标
2014/05/15 Javascript
jsMind通过鼠标拖拽的方式调整节点位置
2015/04/13 Javascript
jquery滚动特效集锦
2015/06/03 Javascript
Js类的静态方法与实例方法区分及jQuery拓展的两种方法
2016/06/03 Javascript
AngularJS实现根据变量改变动态加载模板的方法
2016/11/04 Javascript
requirejs按需加载angularjs文件实例
2017/06/08 Javascript
利用JS如何计算字符串所占字节数示例代码
2017/09/13 Javascript
vue2.0 兄弟组件(平级)通讯的实现代码
2018/01/15 Javascript
vue 根据数组中某一项的值进行排序的方法
2018/08/30 Javascript
js事件on动态绑定数据,绑定多个事件的方法
2018/09/15 Javascript
基于axios 解决跨域cookie丢失的问题
2018/09/26 Javascript
原生JavaScript写出Tabs标签页的实例代码
2020/07/20 Javascript
下载糗事百科的内容_python版
2008/12/07 Python
收藏整理的一些Python常用方法和技巧
2015/05/18 Python
Django模板导入母版继承和自定义返回Html片段过程解析
2019/09/18 Python
通过字符串导入 Python 模块的方法详解
2019/10/27 Python
pytorch实现CNN卷积神经网络
2020/02/19 Python
一文弄懂Pytorch的DataLoader, DataSet, Sampler之间的关系
2020/07/03 Python
利用python对mysql表做全局模糊搜索并分页实例
2020/07/12 Python
python爬取音频下载的示例代码
2020/10/19 Python
澳大利亚小众服装品牌:Maurie & Eve
2018/03/27 全球购物
Fenty Beauty官网:蕾哈娜创立的美妆品牌
2021/01/07 全球购物
.net工程师笔试题
2012/06/09 面试题
创业计划书六个要素
2013/12/26 职场文书
《鱼游到了纸上》教学反思
2014/02/20 职场文书
幼儿园见习报告范文
2014/10/30 职场文书
新娘婚礼致辞
2015/07/27 职场文书