EM算法最通俗理解

期望最大化算法(EM)是机器学习领域非常重要的算法之一,但作为一个工科生,每次看其推导过程,总会怀疑自己的智商是不是不够用,为什么每一步推导都能看懂,但放到一起就崩了呢?可能还是因为数学基础太差了,总不能真正理解,尤其是不理解为什么要这样,相信工科的同学都有这种疑问:到底是先有了实际意义再将其公式化,还是先有了公式再赋予其意义呢?前者应该是工科生的思维,而后者可能只有数学大牛才能搞定吧。

今天我们就以工科生的思维来理解一下EM算法,抛开数学公式推导,看能不能从实际意义上出发,最终得到类似的结果呢?从此刻开始,请忘记所有公式推导,忘记EM算法,回归问题本身。
让我们从经典的男女身高问题开始:这里有一笔学生身高统计数据(假设100个),但是统计的时候忘了统计性别,现在要分别估计男生和女生的身高分布。
你可能会说,这数据是男是女都不知道,根本没办法统计啊!但是现在告诉你,如果你做不出结果,老板就会把你开除,女朋友就要跟你分手。啥意思呢,就是无论如何你要做出一个结果!(言外之意,结果是否100%正确并不重要,统计本来就是一个概率的问题,只要你的结果"差不离儿"就可以了)
好了,为了不被开除/被分手,只能硬着头皮上了。这里先统一一下基本的常识,也就是根据经验来总结几条:
1) 男生身高一般来说是高于女生的
2) 从统计学来看,身高应该是服从正态分布的(也就是我们要估计的其实是4个数,女均值/女方差、男均值/男方差)
基于上面两条经验,我们可以得到一个最暴力的版本:
版本一:快刀斩乱麻
把所有身高从小到达排序一下,前50个作为女生身高,后50个作为男生身高,然后根据概率论里学到求均值和方差的公式,就可以求出男生和女生的分布了。
问题就这么简单地解决了,但这个做法显然过于暴力了,能不能做得细致一些呢?这种直接一刀切的方式,最大的问题是切的点可能不对,因为没有人说男生女生的数量是一样的。那怎么切能更准确一点儿呢?我们先来看一眼统计数据,假如一个身高是155,那你自己判断下它是属于男生还是女生呢?这还用说吗,这个八成是女生的啊。那你是基于什么判断的呢?显然这里有个经验问题,即女生的身高基本是160左右,男生基本是180左右(不接受任何反驳)。所以靠近160的统计数据,大概率是属于女生的,而靠近180的数据,大概率是属于男生的。有了这个经验我们就可以做出第二个版本了:
版本二:根据经验的一刀切
样本数据小于170((160+180)/2)的按照女生处理,大于170的按照男生处理。然后同样根据均值方差公式,得到男生女生的分布。
这个版本连先验知识(也就是没遇到这个问题之前你就知道的知识),感觉已经够极限了。但是还不够,老板跟女朋友还是逼问你:能不能做得更好呢?你可能有点儿发疯了,我这人生经验都用上了,这还能怎么搞啊?那我们换个问法:如果告诉你的结果不够准确,你觉得最有可能是哪里出了问题呢?显然,你就做了一个规定那就是按照170划分,那肯定就是划分错了呗,这里确实有点儿不太"优雅",因为169跟171其实就差了2厘米,却划分给了不同的组。甚至如果正好有个170的,该划分给男生还是划分给女生呢?你说那怎么办呢?难道还要把它劈开吗?哎,对了,为啥不能劈开呢?人当然是不能劈开的,数据是可以劈开的啊,也就是男女占比就按照(0.5/0.5),这样是不是更好呢?然后再看一下169的,前面也说了,它应该是属于女生的概率稍微大一些,那我们是不是可以认为它的男女占比是(0.4/0.6)。既然有了这样的思路,那190的其实也可以认为是男女占比是(0.9/0.1)嘛。
把一个样本按照概率分给男女两个分布去统计,这是个关键点。但前面也说了,这也是没办法的办法,可以说完全是基于直觉的。
于是我们就有了一个新的问题,那就是如何计算这个比例(为了避免混淆,后文以"分配比例"说明)。其实这个分配比例代表的是一个样本属于男还是属于女的概率的比。那我们就求出这两个概率不就可以了吗,用什么求概率呢,用概率密度公式啊,概率密度公式从哪儿来,从变量的分布来啊,那分布从哪儿来......哎,我们要求的不就是分布吗,怎么转了一圈又回到了原点?
回到了原点是不是说明无解了呢?稍等一下,谁说男女分布不知道呢?我们在版本一版本二中,不都得到了一个男女身高的分布吗?假如我们把这个分布拿过来不就算出了这个分配比例吗,那用分配比例又可以计算一个新的分布了.....事情有点儿变得有意思了,我们来捋一下:
我们拿一个预先估计的分布,计算出来一个样本的分配比例,然后用这个比例计算出一个新的分布。由于第一次预估的分布是强行划分得到的,第二次则用了一个分配比例,那第二次得到的分布直觉上应该更准确一些,更关键的是,我们得到了一个自循环,因为我们又可以用新的(应该是更准确的)分布去计算一个更准确的分配比例,这样迭代下去,问题就变成了估算分布->计算分配比例->计算分布->计算分配比例...
版本三:按比例划分样本
1)我们预先估计一个初始概率分布,可以用一些最简单的统计方式(比如方式一),甚至直接根据经验给出(比如前面说的男生均值就是180,女生就是160这样)
2)用估计的概率分布把样本按照比例划分,再根据新的比例去计算一个新分布
3)不断重复执行过程2
那问题来了,这个过程会一直进行下去吗?应该是不会,因为如果我们的估算越来越准确,那我们迟早会跟真实值非常接近,这个时候两次的计算结果应该就非常接近了。也就是这个循环肯定会有一个极限值存在的,不过极值一般是对一个函数而言的。哎对了,这个地方好像能隐约能感觉到我们是在求一个函数的极值有不有?虽然这个函数我们不知道是啥。如果你愿意,那你可以试着定义一个这样的函数,如果你定义了这样一个函数,那我愿意替你的函数起个名字:就叫似然函数吧。既然模糊感觉到的函数都有名字了,那我们用了半天的这个分配比例是不是也该有个名分呢?分配比例在概率论中的专业名词叫分布(注意不要跟我们估计的分布混了)。既然分布都有了,那总得定义一个变量吧,有变量才能有分布啊,那这个用来表示样本分配比例的变量叫啥呢?就叫它隐变量吧。

以上就是对男女身高问题的分析,既然有了分析,肯定要实验一下,用代码产生两组服从正态分布的数据,然后混合在一起,看用我们的方法能不能得到正确的结果。

N = 1000 #样本数量
# 模拟产生男女身高N个
garray = np.random.normal(loc = 165, scale = 5.0, size = N)
barray = np.random.normal(loc = 175, scale = 5.0, size = N)# 混合数据
merged_array = []
for i in range(len(male_array)):merged_array.append(male_array[i])merged_array.append(fmale_array[i])# 根据经验给出初始参数
gmu, gsigma = 160, 10 #女均值、标准差
bmu, bsigma = 180, 10 #男均值、标准差# 计算该参数下的权重分配
gweight = []
bweight = []
for h in height:gw = stats.norm.pdf(h, gmu, gsigma)bw = stats.norm.pdf(h, bmu, bsigma)gweight.append(gw / (gw + bw))bweight.append(bw / (gw + bw))# 用新权重更新参数(女生的)
wsum = 0.0
gmuSum = 0.0
for h,w in zip(height, gweight):gmuSum += h * wwsum += wgmu = gmuSum / wsum


这里要注意一下,有个比例归一的问题,假设没有比例分配问题,那女生的平均值就是gmuSum/N,但这里的gmuSum都乘了一个比例,假如所有比例都是(0.1/0.9),gmuSum实际是乘了个0.1的。所以,后面应该除上一个0.1。那如果比例不相等呢,那就除一个比例的平均值嘛。将所有比例求和再除N,即 wsum/N 然后用 gmuSum/N 除这个数,两个N消除了,就得到gmu = gmuSum / wsum

# 再算下标准差(女生的)
gsigmaSum = 0.0
for h,w in zip(height, gweight):gsigmaSum += (h - gmu) * (h - gmu) * w
gsigma = gsigmaSum / wsum
gsigma = math.sqrt(gsigma)


同样的方式,计算男生的

wsum = 0.0
bmuSum = 0.0
for h,w in zip(height, bweight):bmuSum += h * wwsum += wbmu = bmuSum / wsumbsigmaSum = 0.0
for h,w in zip(height, bweight):bsigmaSum += (h - bmu) * (h - bmu) * w
bsigma = bsigmaSum / wsum
bsigma = math.sqrt(bsigma)

这样,一次运算就完成了,可以用新的参数去估算新的比例了,程序里加个循环就OK啦。后面会给出完整的程序代码,大家可以直接跑的,但在此之前,我们还有三个问题要考虑,这三个问题如果考虑明白了,那基本就算是理解了
1) 如果我们在一定范围内改变给定的初始值,结果会怎么样呢?
2) 假如我不小心把男女均值写反了,那结果会是怎么样的?
3) 假如我给定的男女均值是一样的(比如都是170),结果会是怎样呢?
你可以先考虑下这三个问题的结果,然后用下面的程序验证一下,或者也可以直接在程序上实验,先看结果再分析
....
PS:如果你看过别人或自己实现过EM算法,你会发现我的代码跟EM算法是完全一样的流程,说白了,这其实就是EM算法(为了回归主题,我们还是叫回它原来的名字吧)
假如你已经做完了实验,我们来尝试回答一下刚才的三个问题:
1) 如果我们在一定范围内改变给定的初始值,结果会怎么样呢?
如果你做了实验就会发现,在一定范围内改变初值,最后的结果是一样的。当然如果你改的太多了,比如改成了身高均值是10000,那可能会得到一些报错,这是因为程序的计算精度是有限的,如果中间的结果太小了,程序里就按照0处理了,所以可能除0异常。但在理论上,如果我们的计算精度是无限的,那无论初值是什么,我们最终都可以得到正确结果。
2) 假如我不小心把男女均值写反了,那结果会是怎么样的?
这是个有趣的问题,如果你把男女身高均值搞反了,那最终的结果也是反的,这里面好像有点儿说法,我们先看最后一个问题,再一起分析。
3) 假如我给定的男女均值是一样的(比如都是170),结果会是怎样呢?
不知道这个结果有没有让你很惊讶,如果我们给的初值一样,虽然它相当合理,相当接近真实值,但算法就是得不到正确结果。无论迭代多少次,男女的分布参数都是完全一样的。但只要我们稍微改变一点点,比如是170/170.1,那随着迭代进行,估计的均值和标准差都会慢慢的接近真实值,只是速度会很慢,可以预想到,如果迭代次数足够多,我们最终还是会得到正确结果。
如果你真的思考了,那你肯定已经有一些想法了,看看跟我们想的是不是一致呢?
EM算法其实是一种聚类的算法,它之所有能跑起来,并能得到一个不错的结果,主要依据是样本的“扎堆”性,因为样本分布其实是分了两堆的,我们可以把它想象成一排铁钉,然后我们选择的初始化的值就像两个磁铁一样,会被铁钉所吸引。然后磁铁就会向铁钉分布的中心移动,随着磁铁的移动,每个铁钉对它的引力也会产生变化,最终经过一段时间的移动,磁铁最终会到达铁钉堆的中心。而之所以两个磁铁会分开,就是因为它们的初始位置不一样,我们又强迫每个铁钉对磁铁的吸引力总和是一样的,这样就产生了蝴蝶效应,靠近下面的磁铁收到下面铁钉的引力就大于上面的铁钉,这样慢慢就将两个磁铁分开了。而磁铁本身是没有区分的,也就是两个磁铁换个位置,那结果就正好反过来了。
最后再提一个问题吧,如果我们统计的不是男生女生的身高分布,而是按照年龄段统计。比如年龄段在 5-10、10-15、15-20 的分别统计其分布,这时候该怎么处理呢?
给出一点提示:建立模型的时候,不是样本分了几堆,而是你认为它应该分几堆。借用投资大师芒格的一句话,“如果你有一把锤子,你看什么都像钉子”。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/web/18811.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

【NumPy】权威指南:使用NumPy的percentile函数进行百分位数计算

🧑 博主简介:阿里巴巴嵌入式技术专家,深耕嵌入式人工智能领域,具备多年的嵌入式硬件产品研发管理经验。 📒 博客介绍:分享嵌入式开发领域的相关知识、经验、思考和感悟,欢迎关注。提供嵌入式方向…

python爬虫之JS逆向——爬虫基础

目录 一、http协议 二、前端三剑客 1 HTML 标签 标签举例 2 CSS CSS的引入方式 选择器 属性操作 3 JS基础 JS的引入方式 JS的基本语法 变量赋值 数据类型 运算符 分支语句 循环语句 函数 JS的内置方法 字符串的内置方法 数组的内置方法 内置高阶方法 4 …

研学活动报名二维码怎么制作?

在组织研学活动时,老师们经常面临报名流程繁琐、信息收集不全面、统计工作耗时等问题?如何高效地管理学生的报名信息,确保活动顺利进行呢? 现在我们有了更多的选择。老师们可以快速制作出研学活动的研学活动报名二维码怎么制作&am…

【网络协议Http】Http中get,post,put,delete区别

Http协议 超文本传输协议(Hypertext Transfer Protocol,HTTP)是一个简单的请求-响应协议,它通常运行在TCP之上。 【参考】 GET && POST 对比 关于tcp数据包:对于GET方式的请求,浏览器会把http hea…

Android 11 AudioPolicyService 启动流程

AudioPolicyService在init进程中启动,源码路径:frameworks/av/media/audioserver/audioserver.rc service audioserver /system/bin/audioserverclass coreuser audioserver# media gid needed for /dev/fm (radio) and for /data/misc/media (tee)grou…

DETR整体模型结构解析

DETR流程 Backbone用卷积神经网络抽特征。最后通过一层1*1卷积转化到d_model维度fm(B,d_model,HW)。 position embedding建立跟fm维度相同的位置编码(B,d_model,HW)。 Transformer Encoder,V为fm,K,Q为fm…

非量表题如何进行信效度分析

效度是指设计的题确实在测量某个东西,一般问卷中使用到。如果是量表类的数据,其一般是用因子分析这种方法去验证效度水平,其可通过因子分析探究各测量量表的内部结构情况,分析因子分析得到的内部结构与自己预期的内部结构进行对比…

自学之路Flutter使用Provider进行状态管理

使用前的准备 首先在pubspec.yaml中配置,然后pub get,等待安装完成 我们首先创建两个比较简单的控制器,测试页面跳转之间的数据传递。 import package:flutter/material.dart;void main() {runApp(const MyApp()); }class MyApp extends StatelessWid…

python接口自动化之会话保持

🍦 会话保持-token 有的网站登录需要token鉴权,是啥意思呢,现在有两个接口,一个接口是登录,一个接口是提交订单,那你怎么保证,提交登录这个用户是登录状态呢。登录成功的接接口会在response里面…

大模型预训练结果到底是什么?

近日参加一个线下 AI 交流会议,会上有个非本行业的老师提问:“大家说的训练好的大模型到底是什么?是像 Word 软件一样可以直接使用的程序吗?” 这个问题看似简单,却一下把我问住了。的确,我们这些身处 AI 领…

Kafka原生API使用Java代码-生产者-发送消息

文章目录 1、生产者发送消息1.1、使用EFAK创建主题my_topic31.2、根据kafka官网文档写代码1.3、pom.xml1.4、KafkaProducer1.java1.5、使用EFAK查看主题1.6、再次运行KafkaProducer1.java1.7、再次使用EFAK查看主题 1、生产者发送消息 1.1、使用EFAK创建主题my_topic3 1.2、根…

STM32 OTA需要注意问题

一、OTA设计思路(问题) 1、根据stm32f405 flash分布,最初将flash划分为四个区域,分别是Bootloader、APP1、APP2、参数区,设备上电后,进入Bootloader程序,判断OTA参数,根据参数来确定…

APP逆向之调试的开启

很基础的一个功能设置,大佬轻喷。 背景 在开始进行对APP逆向分析的时候,需要对APP打开调试模式。 打开调试的模式有多种方式可以通过直接改包方式也可以通过借助第三方工具进行打开调试模式。 下面就整理下这个打开调试模式的一些方式。 改包修改模…

Java面试题分享-敏感词替换 java 版本

入职啦最近更新了一些后端笔试、面试题目,大家看看能快速实现吗? 关注 入职啦 微信公众号,每日更新有用的知识,Python,Java,Golang,Rust,javascript 等语言都有 不要再用replaceAll做…

npm获取yarn在安装依赖时 git://github.com/user/xx.git 无法访问解决方法 -- 使用 insteadOf设置git命令别名

今天在使用一个node项目时突然遇到 一个github的拉取异常&#xff0c;一看协议居然是git://xxx 貌似github早就不用这种格式了&#xff0c; 而是使用的gitgithub.com:xxx 这种或者https协议&#xff0c;解决方法&#xff1a; 使用insteadof设置git别名 url.<base>.inste…

DNF手游攻略:开荒必备攻略!

DNF手游马上就要开服了&#xff0c;今天给大家带来最完整的DNF手游入门教程。这篇攻略主要讲述了 DNF手游开服第一天要注意的事项&#xff0c;这是一个新手必备的技能书&#xff0c;可以让你在开服的时候&#xff0c;少走一些弯路&#xff0c;让你更快完成任务&#xff01;废话…

蓝牙Mesh模块多跳大数据量高带宽传输数据方法

随着物联网技术的飞速发展&#xff0c;越来越多的设备需要实现互联互通。蓝牙Mesh网络作为一种低功耗、高覆盖、易于部署的无线通信技术&#xff0c;已经成为物联网领域中的关键技术之一。在蓝牙Mesh网络中&#xff0c;节点之间可以通过多个跳数进行通信&#xff0c;从而实现大…

mysql-日志管理-error.log

日志管理 默认的数据库日志 vim /etc/my.cnf //错误日志 log-error/usr/local/mysql/mysql.log查看数据库日志 tail -f /usr/local/mysql/mysql.log1 错误日志 &#xff1a;启动&#xff0c;停止&#xff0c;关闭失败报错。rpm安装日志位置 /var/log/mysqld.log #默认开启 2 …

【OrangePi AIpro】香橙派 AIpro 为AI而生

产品简介 OrangePi AIpro(8T)&#xff1a;定义边缘智能新纪元的全能开发板 在当今人工智能与物联网技术融合发展的浪潮中&#xff0c;OrangePi AIpro(8T)凭借其强大的硬件配置与全面的接口设计&#xff0c;正逐步成为开发者手中的创新利器。这款开发板不仅代表了香橙派与华为…

最新淘宝死店全自动采集私信筛选脚本,号称日赚500+【采集软件+使用教程】

原理&#xff1a; 利用脚本自动采集长时间未登录店铺&#xff0c;然后脚本自动私信对应的店铺&#xff0c;看看商家是不是不回消息来判断是否是死店&#xff0c;再下单购买死店的产品&#xff0c;超过48小时不发货就可以联系客服获得赔付&#xff0c;一单利润百分之5%-30%&…