我正在尝试学习期望最大化算法,用于高斯混合模型(一维)的参数估计。然而,该算法似乎很少能找到正确的参数。我想知道我是否做错了什么。
数据是由位于三个不同位置的高斯分布生成的(x=-10, x=5, 和 x=10
):
import numpy as npimport matplotlib.mlab as mlabimport matplotlib.pyplot as plt# 数据集由均值为-10, 10和5的三个高斯分布生成。 x1 = 1.0 * np.random.randn(10000) - 10.0x2 = 1.0 * np.random.randn(10000) + 10.0x3 = 1.0 * np.random.randn(10000) + 5.0x = np.hstack([x1,x2,x3]) # 最终数据集
我检查了直方图,x 是正确的。参数学习是通过EM更新完成的:
# 模型和初始化M = 3 # 混合数量alpha = np.ones(M)*.5 # -> 混合的可能性mu = np.random.random(M)*10 # -> 高斯分布的均值sigma = np.ones(M)*1.0 # -> 高斯分布的标准差w_mt = np.zeros((M,len(x))) # -> q(混合 | 数据, 参数)# EMfor i in range(100): print "alpha:", alpha, "mu:", mu, "sigma:", sigma # E-step for m in range(M): w_mt[m] = alpha[m] * mlab.normpdf(x,mu[m],sigma[m]) C = np.sum(w_mt, axis=0) # 归一化 w_mt = w_mt / C # M-step alpha = np.sum(w_mt,axis=1) / len(x) mu = np.sum(w_mt*x,axis=1)/np.sum(w_mt,axis=1) sigma = np.sum(w_mt*pow(x - mu[:,np.newaxis],2),axis=1) / np.sum(w_mt,axis=1) sigma[sigma < 0.1] = 0.1 # 避免数值问题
我期望算法至少有时能找到正确的mu
(即-10,5,10),标准差约为1.0。然而,算法似乎从未能做到这一点。任何帮助都将不胜感激
更新:
某人的修复似乎解决了这个问题。我忘记了在计算std
时取平方根。如果有人感兴趣,这里是更新代码的链接:链接
回答:
sigma 是标准差,但你代码中的 sigma 是方差(即 sigma ** 2)。
试试
sigma = np.sqrt(np.sum(w_mt*pow(x - mu[:,np.newaxis],2),axis=1) / np.sum(w_mt,axis=1))