Statistical-Learning-Method_Code中的EM算法:从混合高斯模型到参数估计
你是否在学习《统计学习方法》时遇到过EM算法(Expectation-Maximization algorithm,期望最大化算法)难以理解的问题?是否想亲手实现这个强大的参数估计算法却不知从何下手?本文将以Statistical-Learning-Method_Code项目中的EM/EM.py为例,带你一步步揭开EM算法的神秘面纱,掌握混合高斯模型(Gaussian Mixture Model, GMM)的参数估计方法。读完本文后,你将能够理解EM算法的核心思想,看懂项目中EM算法的实现代码,并学会如何使用该算法解决实际问题。
EM算法简介
EM算法是一种迭代优化算法,主要用于解决含有隐变量(Latent Variable)的概率模型参数估计问题。在统计学和机器学习中,许多问题都可以归结为含有隐变量的模型参数估计,例如混合高斯模型、隐马尔可夫模型(HMM)、协同过滤等。EM算法通过交替进行"期望步"(E步)和"最大化步"(M步)来逐步逼近模型的最优参数,是解决这类问题的有效方法。
Statistical-Learning-Method_Code项目是手写实现李航《统计学习方法》书中全部算法的开源项目,其中EM/EM.py文件完整实现了基于混合高斯模型的EM算法。该实现以两个高斯分布混合的数据为例,演示了如何使用EM算法估计模型参数,包括每个高斯分布的均值、方差以及混合系数。
混合高斯模型
混合高斯模型是一种常用的概率模型,它假设数据是由多个高斯分布混合而成的。对于一个包含K个高斯分布的混合模型,其概率密度函数可以表示为:
$$ p(y|\theta) = \sum_{k=1}^{K} \alpha_k \phi(y|\mu_k, \Sigma_k) $$
其中,$\alpha_k$是第k个高斯分布的混合系数,满足$\sum_{k=1}^{K} \alpha_k = 1$且$0 \leq \alpha_k \leq 1$;$\phi(y|\mu_k, \Sigma_k)$是第k个高斯分布的概率密度函数,其均值为$\mu_k$,协方差矩阵为$\Sigma_k$;$\theta = (\alpha_1, \alpha_2, ..., \alpha_K, \mu_1, \mu_2, ..., \mu_K, \Sigma_1, \Sigma_2, ..., \Sigma_K)$是模型的参数。
在Statistical-Learning-Method_Code项目的EM/EM.py中,实现了K=2的混合高斯模型。下面我们来看一下该文件中是如何生成混合高斯分布数据的。
数据生成
EM/EM.py中的loadData函数用于生成混合高斯分布的数据。该函数接受两个高斯分布的均值、方差和混合系数作为参数,生成指定长度的混合数据。具体代码如下:
def loadData(mu0, sigma0, mu1, sigma1, alpha0, alpha1):
length = 1000
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
上述代码首先根据混合系数alpha0和alpha1确定两个高斯分布各自生成的数据量,然后使用np.random.normal函数生成对应的数据,最后将两部分数据混合并打乱顺序。通过这种方式,我们就得到了一个由两个高斯分布混合而成的数据集,用于后续的EM算法参数估计。
EM算法的实现
Statistical-Learning-Method_Code项目中的EM/EM.py文件完整实现了EM算法的E步和M步。下面我们将详细介绍这两个步骤的实现过程。
E步(期望步)
E步的主要目的是计算隐变量的后验概率,即给定观测数据和当前模型参数的情况下,隐变量的条件概率分布。在混合高斯模型中,隐变量表示每个观测数据来自哪个高斯分布。
EM/EM.py中的E_step函数实现了这一步骤。该函数接受观测数据集、当前模型参数(两个高斯分布的均值、方差和混合系数)作为输入,计算每个观测数据属于两个高斯分布的后验概率(响应度)。具体代码如下:
def E_step(dataSetArr, alpha0, mu0, sigmod0, alpha1, mu1, sigmod1):
gamma0 = alpha0 * calcGauss(dataSetArr, mu0, sigmod0)
gamma1 = alpha1 * calcGauss(dataSetArr, mu1, sigmod1)
sum = gamma0 + gamma1
gamma0 = gamma0 / sum
gamma1 = gamma1 / sum
return gamma0, gamma1
其中,calcGauss函数用于计算观测数据在给定均值和方差下的高斯分布密度值,其实现如下:
def calcGauss(dataSetArr, mu, sigmod):
result = (1 / (math.sqrt(2 * math.pi) * sigmod)) * \
np.exp(-1 * (dataSetArr - mu) * (dataSetArr - mu) / (2 * sigmod**2))
return result
在E步中,首先计算每个观测数据属于两个高斯分布的联合概率(未归一化的后验概率),然后将其归一化,得到每个观测数据属于两个高斯分布的响应度gamma0和gamma1。
M步(最大化步)
M步的主要目的是在给定隐变量后验概率的情况下,最大化完整数据的对数似然函数,从而更新模型参数。
EM/EM.py中的M_step函数实现了这一步骤。该函数接受当前模型参数、隐变量的后验概率(响应度)和观测数据集作为输入,计算并返回更新后的模型参数。具体代码如下:
def M_step(muo, mu1, gamma0, gamma1, dataSetArr):
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
在M步中,分别根据响应度gamma0和gamma1更新两个高斯分布的均值、方差和混合系数。均值的更新是通过对观测数据进行加权平均得到的,权重为响应度;方差的更新是通过计算加权方差得到的;混合系数的更新则是响应度的平均值。
EM算法的迭代
EM算法通过交替执行E步和M步来逐步更新模型参数,直到参数收敛或达到预设的迭代次数。EM/EM.py中的EM_Train函数实现了这一迭代过程。具体代码如下:
def EM_Train(dataSetList, iter = 500):
dataSetArr = np.array(dataSetList)
alpha0 = 0.5; mu0 = 0; sigmod0 = 1
alpha1 = 0.5; mu1 = 1; sigmod1 = 1
step = 0
while (step < iter):
step += 1
gamma0, gamma1 = E_step(dataSetArr, alpha0, mu0, sigmod0, alpha1, mu1, sigmod1)
mu0, mu1, sigmod0, sigmod1, alpha0, alpha1 = \
M_step(mu0, mu1, gamma0, gamma1, dataSetArr)
return alpha0, mu0, sigmod0, alpha1, mu1, sigmod1
在EM_Train函数中,首先对模型参数进行初始化,然后迭代执行E步和M步,更新模型参数。默认迭代次数为500次,用户也可以根据需要进行调整。
实验结果与分析
为了验证EM算法的有效性,Statistical-Learning-Method_Code项目中的EM/EM.py文件在main函数中进行了实验。该实验首先设置了两个高斯分布的真实参数,生成混合数据集,然后使用EM算法对模型参数进行估计,并将估计结果与真实参数进行比较。
实验设置
在main函数中,设置了两个高斯分布的真实参数如下:
- 第一个高斯分布:混合系数
alpha0 = 0.3,均值mu0 = -2,方差sigmod0 = 0.5 - 第二个高斯分布:混合系数
alpha1 = 0.7,均值mu1 = 0.5,方差sigmod1 = 1
然后调用loadData函数生成混合数据集,并使用EM_Train函数进行参数估计。
实验结果
实验结果显示,经过500次迭代后,EM算法估计得到的模型参数与真实参数非常接近。例如,估计得到的混合系数alpha0约为0.3,alpha1约为0.7;均值mu0约为-2,mu1约为0.5;方差sigmod0约为0.5,sigmod1约为1。这表明EM算法能够有效地估计混合高斯模型的参数。
需要注意的是,EM算法的估计结果可能会受到初始参数的影响,可能会收敛到局部最优解而非全局最优解。因此,在实际应用中,通常需要多次运行EM算法,选择不同的初始参数,以提高得到全局最优解的概率。
总结与展望
本文以Statistical-Learning-Method_Code项目中的EM/EM.py为例,详细介绍了EM算法在混合高斯模型参数估计中的应用。通过对E步和M步的实现代码分析,我们深入理解了EM算法的核心思想和实现过程。实验结果表明,该项目中的EM算法实现能够有效地估计混合高斯模型的参数,为解决含有隐变量的概率模型参数估计问题提供了一个很好的参考。
除了混合高斯模型,EM算法在其他含有隐变量的概率模型中也有广泛的应用,例如隐马尔可夫模型(HMM)的参数估计。Statistical-Learning-Method_Code项目中也包含了HMM的实现,感兴趣的读者可以参考HMM/HMM.py文件进行学习。
未来,我们可以进一步扩展EM算法的应用范围,例如将其应用于图像分割、语音识别、自然语言处理等领域。同时,也可以对EM算法进行改进,提高其收敛速度和估计精度,以更好地满足实际应用的需求。
希望本文能够帮助你更好地理解EM算法,并为你使用Statistical-Learning-Method_Code项目中的EM算法实现提供有益的指导。如果你对EM算法还有其他疑问,或者在使用项目代码时遇到问题,欢迎查阅项目的README.md文件或参考项目中的其他相关文档。
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考



