分享

经典机器学习算法-第二十章EM算法

 NeighborMrSun 2023-02-27 发布于湖南
EDUCATION AND TRAINING


一、极大似然估计

    作为一种迭代算法,EM 算法用于包含隐变量的概率模型参数的极大似然估计。EM 算法包括两个步骤:E步,求期望(expectation);M步,求极大(maximization)。本章首先介绍常规的极大似然估计方法,然后介绍 EM算法并以经典的三硬币模型为例进行辅助说明;最后给出基于 NumPy的 EM算法实现。

    极大似然估计(maximumlikelihoodestimation,MLE)是统计学领域中一种经典的参数估计方法。对于某个随机样本满足某种概率分布,但其中的统计参数未知的情况,极大似然估计可以让我们通过若干次试验的结果来估计参数的值。

    以一个经典的例子进行说明,比如我们想了解某高校学生的身高分布。我们先假设该校学生的身高服从一个正态分布图片,其中的分布参数未知。全校有数万名学生,要一个个实测肯定不现实,所以我们决定用统计抽样的方法,随机选取 100名学生测得其身高。

    要通过这 100人的身高来估算全校学生的身高,需要明确下面几个问题。第一个问题是抽到这100人的概率是多少。因为每个人的选取都是独立的,所以抽到这 100人的概率可以表示为单个概率的乘积:


图片

    上式即为似然函数。通常为了计算方便,我们会对似然函数取对数:


图片

    第二个问题是为什么刚好抽到这 100 人。按照极大似然估计的理论,在学校这么多学生中我们恰好抽到这 100人而不是另外 100 人,正是因为这 100人出现的概率极大,即其对应的似然函数最大


图片

    最后一个问题是如何求解。这比较容易,直接对 L(0)求导并令其为0即可。

    所以极大似然估计法可以看作由抽样结果对条件的反推,即已知某个参数能体得这此样本出现的概率极大,我们就直接把该参数作为参数估计的直实值。



二、EM算法

    如何理解隐变量呢,比如现在有200个身高数据,其中100个是男生,100个是女生,但是我们不知道其中每个样本是男生还是女生的,这样就是一个隐变量,就是我们通过观测数据无法观测出来的。

    最近看到了一个介绍EM算法的例子:

    我们要做一个投掷硬币的实验,现在有两个硬币A和B,这两个硬币都是有偏的。现在要做5组实验,每次实验从两个硬币中随机抽取一个,然后连续抛10次。设参数图片分别为硬币A、B正面朝上的概率,如下图所示的五组实验数据,如果我们知道了每次抛的是哪个硬币,那么计算上面那两个参数就非常的简单。


图片

但如果不知道每次抛的是哪个硬币呢?如下图所示:


图片

这时候就需要用到EM算法:

图片一个初始值;

(E步)估计每组实验是硬币A、硬币B的概率,分别计算每组实验中,选择A硬币且正面朝上次数的期望值,选择B硬币且正面朝上次数的期望值;

(M步)利用第三步求得的期望值重新计算图片

当迭代到一定次数,或者算法收敛到一定精度,结束算法,否则,回到第2步。

如下图所示:


图片

图中:


图片

    上面是一个十分简单的EM算法的例子,EM算法的思想也很简单就是通过设置参数的初始值然后通过E步和M步不断迭代进行求解,但是实际应用过程中EM算法的计算往往不是这么简单的,需要引入Jenson不等式进行求解。



三、三硬币基于 NumPy的 EM算法实现
# 导入numpy库 import numpy as np
### EM算法过程函数定义def em(data, thetas, max_iter=30, eps=1e-3): ''' 输入: data:观测数据 thetas:初始化的估计参数值 max_iter:最大迭代次数 eps:收敛阈值 输出: thetas:估计参数 ''' # 初始化似然函数值 ll_old = -np.infty for i in range(max_iter): ### E步:求隐变量分布 # 对数似然 log_like = np.array([np.sum(data * np.log(theta), axis=1) for theta in thetas]) # 似然 like = np.exp(log_like) # 求隐变量分布 ws = like/like.sum(0) # 概率加权 vs = np.array([w[:, None] * data for w in ws]) ### M步:更新参数值 thetas = np.array([v.sum(0)/v.sum() for v in vs]) # 更新似然函数 ll_new = np.sum([w*l for w, l in zip(ws, log_like)]) print('Iteration: %d' % (i+1)) print('theta_B = %.2f, theta_C = %.2f, ll = %.2f' % (thetas[0,0], thetas[1,0], ll_new)) # 满足迭代条件即退出迭代 if np.abs(ll_new - ll_old) < eps: break ll_old = ll_new return thetas
# 观测数据,5次独立试验,每次试验10次抛掷的正反次数# 比如第一次试验为5次正面5次反面observed_data = np.array([(5,5), (9,1), (8,2), (4,6), (7,3)])# 初始化参数值,即硬币B的正面概率为0.6,硬币C的正面概率为0.5thetas = np.array([[0.6, 0.4], [0.5, 0.5]])thetas = em(observed_data, thetas, max_iter=30, eps=1e-3)

图片

    本站是提供个人知识管理的网络存储空间,所有内容均由用户发布,不代表本站观点。请注意甄别内容中的联系方式、诱导购买等信息,谨防诈骗。如发现有害或侵权内容,请点击一键举报。
    转藏 分享 献花(0

    0条评论

    发表

    请遵守用户 评论公约

    类似文章 更多