漫谈 Clustering (番外篇): Expectation Maximization
Expectation Maximization (EM) 是一种以迭代的方式来解决一类特殊最大似然 (Maximum Likelihood) 问题的方法,这类问题通常是无法直接求得最优解,但是如果引入隐含变量,在已知隐含变量的值的情况下,就可以转化为简单的情况,直接求得最大似然解。
我们会看到,上一次说到的 Gaussian Mixture Model 的迭代求解方法可以算是 EM 算法最典型的应用,而最开始说的 K-means 其实也可以看作是 Gaussian Mixture Model 的一个变种(固定所有的 ,并令 即可)。然而 EM 实际上是一种通用的算法(或者说是框架),可以用来解决很多类似的问题,我们最后将以一个中文分词的例子来说明这一点。
为了避免问题变得太抽象,我们还是先从上一次的 Gaussian Mixture Model 说起吧。回顾一下我们之前要解决的问题:求以下 Log-likelihood function 的最大值:
但是由于在 函数里面又有加和,没法直接求。考虑一下 GMM 生成 sample 的过程:先选一个 Component ,然后再从这个 Component 所对应的那个普通的 Gaussian Distribution 里进行 sample 。我们可以很自然地引入一个隐含变量 ,这是一个 维向量,如果第 个 Component 被选中了,那么我们讲其第 个元素置为 1 ,其余的全为 0 。那么,再来看看,如果除了之前的 sample 的值之外,我们同时还知道了每个 所对应的隐含变量 的值,情况又会变成怎么样呢?
因为我们同时观察到了 和 ,所以我们现在要最大化的似然函数也变为 。注意到 可以表示为:
而 的概率,当 的第 个元素为 1 的时候,亦即第 个 Component 被选中的时候,这个概率为 ,统一地写出来就是:
带入上面个式子,我们得到 的概率是一个大的乘积式(对比之前 是一个和式)。再替换到最开始的那个 Log-likelihood function 中,得到新的同时关于 sample 和隐含变量 的 Log-likelihood:
情况瞬间逆转,现在 和求和符号换了个位置,直接作用在普通的高斯分布上了,一下子就变成了可以直接求解的问题。不过,事情之所以能发展得如此顺利,完全依赖于一个我们伪造的假设:隐含变量的值已知。然而实际上我们并不知道这个值。问题的结症在这里了,如果我们有了这个值,所有的问题都迎刃而解了。回想一下,在类似的地方,我们是如何处理这样的情况的呢?一个很类似的地方就是(比如,在数据挖掘中)处理缺失数据的情况,一般有几种办法:
- 用取值范围类的随机值代替。
- 用平均值代替。
- 填 0 或者其他特殊值。
这里我们采取一种类似于平均值的办法:取期望。因为这里我们至少有 sample 的值,因此我们可以把这个信息利用起来,针对后验概率 来取期望。前面说过, 的每一个元素只有 0 和 1 两种取值,因此按照期望的公式写出来就是:
中间用贝叶斯定理变了一下形,最后得到的式子正是我们在漫谈 GMM 中定义的 。因此,对于上面那个可以直接求解的 Log-likelihood function 中的 ,我们只要用其期望 亦即 代替即可。
到这里为止,看起来是一个非常完美的方法,不过仔细一看,发现还有一个漏洞:之前的 Log-likelihood function 可以直接求最大值是建立在 是已知情况下,现在虽然我们用 来代替了 ,但是实际上 是一个反过来以非常复杂的关系依赖所要求参数的一个式子,而不是一个“已知的数值”。解决这个问题的办法就是迭代。
到此为止,我们就勾勒出了整个 EM 算法的结构,同时也把上一次所讲的求解 GMM 的方法又推导了一遍。EM 名字也来源于此:
- Expectation 一步对应于求关于后验概率的期望亦即 ;
- Maximization 一步则对应于接下来的正常的最大似然的方法估计相关的参数亦即 、 和 。
如果你还没有厌烦这些公式的话,让我们不妨再稍微花一点时间,从偏理论一点的角度来简略地证明一下 EM 这个迭代的过程每一步都会对结果有所改进,除非已经达到了一个(至少是局部的)最优解。
现在我们的讨论将不局限于 GMM ,并使用一些稍微紧凑一点的符号。用 表示所有的 sample ,同时用 表示所有对应的隐含变量。我们的问题是要通过最大似然的方法估计出 中的参数 。在这里我们假设这个问题很困难,但是要优化 却很容易。这就是 EM 算法能够解决的那一类问题。
现在我们引入一个关于隐含变量的分布 。注意到对于任意的 ,我们都可以对 Log-likelihood Function 作如下分解:
其中 是分布 和 之间的 Kullback-Leibler divergence 。由于 Kullback-Leibler divergence 是非负的,并且只有当两个分布完全相同的时候才会取到 0 。因此我们可以得到关系 ,亦即 是 的一个下界。
现在考虑 EM 的迭代过程,记上一次迭代得出的参数为 ,现在我们要选取 以令 最大,由于 并不依赖于 ,因此 的上限(在 固定的时候)是一个定值,它取到这个最大值的条件就是 Kullback-Leibler divergence 为零,亦即 等于后验概率 。把它带入到 的表达式中可以得到
其中 const
是常量,而 则正是我们之前所得到的“同时包含了 sample 和隐含变量的 Log-likelihood function 关于后验概率的期望”,因此这个对应到 EM 中的“E”一步。
在接下来的“M”一步中,我们讲固定住分布 ,再选取合适的 以将 最大化,这次其上界 也依赖于变量 ,并会随着 的增大而增大(因为我们有前面的不等式成立)。一般情况下 增大的量会比 要多一些,这时候 Kullback-Leibler divergence 在新的参数 下又不为零了,因此我们可以进入下一轮迭代,重新回到“E”一步去求新的 ;另一方面,如果这里 Kullback-Leibler divergence 在新的参数下还是等于 0 ,那么说明我们已经达到了一个(至少是局部的)最优解,迭代过程可以结束了。
上面的推导中我们可以看到每一次迭代 E 和 M 两个步骤都是在对解进行改进,因此迭代的过程中得到的 likelihood 会逐渐逼近(至少是局部的)最优值。另外,在 M 一步中除了用最大似然之外,也可以引入先验使用 Maximum a Posteriori (MAP) 的方法来做。还有一些很困难的问题,甚至在迭代的过程中 M 一步也不能直接求出最大值,这里我们通过把要求放宽──并不一定要求出最大值,只要能够得到比旧的值更好的结果即可,这样的做法通常称作 Generalized EM (GEM)。
当然,一开始我们就说了,EM 是一个通用的算法,并不只是用来求解 GMM 。下面我们就来举一个用 EM 来做中文分词的例子。这个例子来源于论文 Self-supervised Chinese Word Segmentation 。我在上次 MSTC 搜索引擎系列小课堂讲文本处理的时候提到过。这里为了把注意力集中到 EM 上,我略去一些细节的东西,简单地描述一下基本的模型。
现在我们有一个字符序列 ,并希望得到一个模型 (依赖于参数 )能用来将其词的序列 。按照生成模型的方式来考虑,将 看成是由 生成的序列的话,我们自然希望找到那个生成 的可能性最大的 ,亦即通过最大似然的方式来估计参数 。
然而我们不知道似然函数 应该如何去优化,因此我们引入 latent variable ,如果我们知道 的话,似然值很容易求得:
其中 的值是从模型 中已知的。但是现在我们不知道 的值,因此我们转而取其关于后验概率的期望:
然后将这个期望针对 最大化即完成了 EM 的一次迭代。具体的做法通常是先把一个初始文本(比如所有的 的集合)按照 N-gram 分割(N-gram 在 讲 K-medoids 的那篇文章中介绍过)为 ,形成一个最初的辞典,而模型 的参数 实际上就描述了各个 N-gram 的概率 ,初始值可以直接取为频率值。有了辞典之后对于任意的 ,我们可以根据辞典枚举出所有可能的分割 ,而每个分割的后验概率 就是其中的单词的概率乘积。其他的就是标准的 EM 算法的迭代步骤了。
实际上在实际产品中我们会使用一些带了更多启发式规则的分词方法(比如 MMSEG),而这个方法更大的用处在于从一堆文本中“学习”出一个词典来(也就是 ),并且这个过程是全自动的,主要有两个优点:
- 不需要人参与手工分词、标记等。
- 能自动从文本中学习,换句话说,你给它一些某个领域的专业文章,它能从中学习到这个领域的专业词汇来。
不管怎样,以上两点看起来都非常诱人。不过理论离实际往往还是有不少差距的。我不知道实际分词系统中有没有在用这样的方法来做训练的。之前我曾经用 Wikipedia (繁体中文)上抓下来的一些数据跑过一下小规模的试验,结果还可以,但是也并不如想像中的完美。因为当时也并没有弄明白 EM 是怎么一回事,加上这个过程本身计算负荷还是非常大的,也就没有深入下去。也许以后有时间可以再尝试一下。
总之,EM 是一种应用广泛的算法,虽然讲了点理论也讲了例子,但是一没有贴代码二没有贴图片,似乎实在是不像我的作风,不过精力和篇幅有限,也只能到此为止了。
漫谈 Clustering (番外篇): Expectation Maximization的更多相关文章
- 漫谈 Clustering (番外篇): Dimensionality Reduction
由于总是有各种各样的杂事,这个系列的文章竟然一下子拖了好几个月,(实际上其他的日志我也写得比较少),现在决定还是先把这篇降维的日志写完.我甚至都以及忘记了在这个系列中之前有没有讲过“特征”(featu ...
- 漫谈 Clustering (番外篇): Vector Quantization
在接下去说其他的聚类算法之前,让我们先插进来说一说一个有点跑题的东西:Vector Quantization.这项技术广泛地用在信号处理以及数据压缩等领域.事实上,在 JPEG 和 MPEG-4 等多 ...
- UVW源码漫谈(番外篇)—— Emitter
这两天天气凉了,苏州这边连续好几天都是淅淅沥沥的下着小雨,今天天气还稍微好点.前两天早上起来突然就感冒了,当天就用了一卷纸,好在年轻扛得住,第二天就跟没事人似的.在这里提醒大家一下,天气凉了,睡凉席的 ...
- 【番外篇】ASP.NET MVC快速入门之免费jQuery控件库(MVC5+EF6)
目录 [第一篇]ASP.NET MVC快速入门之数据库操作(MVC5+EF6) [第二篇]ASP.NET MVC快速入门之数据注解(MVC5+EF6) [第三篇]ASP.NET MVC快速入门之安全策 ...
- iOS冰与火之歌(番外篇) - 基于PEGASUS(Trident三叉戟)的OS X 10.11.6本地提权
iOS冰与火之歌(番外篇) 基于PEGASUS(Trident三叉戟)的OS X 10.11.6本地提权 蒸米@阿里移动安全 0x00 序 这段时间最火的漏洞当属阿联酋的人权活动人士被apt攻击所使用 ...
- 给深度学习入门者的Python快速教程 - 番外篇之Python-OpenCV
这次博客园的排版彻底残了..高清版请移步: https://zhuanlan.zhihu.com/p/24425116 本篇是前面两篇教程: 给深度学习入门者的Python快速教程 - 基础篇 给深度 ...
- 可视化(番外篇)——在Eclipse RCP中玩转OpenGL
最近在看有关Eclipse RCP方面的东西,鉴于Gephi是使用opengl作为绘图引擎,所以,萌生了在Eclipse RCP下添加画布,使用opengl绘图的想法,网上有博文详细介绍这方面的内容, ...
- 可视化(番外篇)——SWT总结
本篇主要介绍如何在SWT下构建一个应用,如何安装SWT Designer并破解已进行SWT的可视化编程,Display以及Shell为何物.有何用,SWT中的常用组件.面板容器以及事件模型等. 1.可 ...
- 【重走Android之路】【番外篇】关于==和equals
[重走Android之路][番外篇]关于==和equals 在实际的编程当中,经常会使用==和equals来判断变量是否相同.但是这两种比较方式也常常让人搞得云里雾里摸不着头脑.下面是我个人做的总 ...
随机推荐
- Mysql-6-数据类型和运算符
1.mysql数据类型 (1)数值数据类型:包括整数类型tinyint.smallint.mediumint.int.bigint,浮点小数类型float和double,定点小数类型decimal. ...
- JavaScript中内置对象的一些属性及方法
Javascript对象总结 JS中内置了17个对象,常用的是Array对象.Date对象.正则表达式对象.string对象.Global对象 Array对象中常用方法: Concat():表示把几个 ...
- POJ1024 Tester Program
题目来源:http://poj.org/problem?id=1024 题目大意: 有一个迷宫,迷宫的起点在(0,0)处.给定一条路径,和该迷宫墙的设置,要求验证该路径是否为唯一的最短路径,该种墙的设 ...
- Vue中的指令(听博主说总结的很好)
指令[重点] 作用:简化Dom操作 参考:https://cn.vuejs.org/v2/api/#%E6%8C%87%E4%BB%A4 特点: 1.都是以v-开头 2.除了插值表达式,其它都写在标签 ...
- HTTP的一些理解
URI是Uniform Resource Identifier的缩写,统一资源标识符.URI用字符串标识某一互联网资源,而URL标识资源的地点(互联网上所处的位置).可见URL是URI的子集. 典型的 ...
- Luogu P2833 等式 我是傻子x2
又因为调一道水题而浪费时间...不过细节太多了$qwq$,暴露出自己代码能力的不足$QAQ$ 设$d=gcd(a,b)$,这题不是显然先解出来特解,即解出 $\frac{a}{d}x_0+\frac{ ...
- CBV 与 FBV
FBV:function based view 视图函数,是指之前用的 views.py 中基于函数的开发,url 都是通过函数来实现的,每个 url 对应的函数之间都是独立的. 直接在views.p ...
- 11 Lists
1 Lists 1.1 定义并访问Lists List list = new List[].也可以使用泛型.访问list中的元素,可以使用list.get(i) or list[i]. ...
- GTY's gay friends 线段树判断区间是否有相同数字
http://acm.hdu.edu.cn/showproblem.php?pid=5172 判断一个区间是否为全排列是: 1.区间总和 = (1 + R - L + 1) * (R - L + 1) ...
- PHP的Undefined variable错误怎么解决?
在调试程序时,有可能会出现Undefined variable错误,一般情况下php是不需要定义变量的,但如果服务器什么都报错的,就会出现错误,我们经常接收表单POST过来的数据时报Undefined ...