Numpy 期望最大化(GMM-EM)从未找到正确的参数。(高斯混合)

Numpy 期望最大化(GMM-EM)从未找到正确的参数。(高斯混合),numpy,machine-learning,statistics,scipy,gaussian,Numpy,Machine Learning,Statistics,Scipy,Gaussian,我试图学习混合高斯(1D)中参数估计的期望最大化。然而,该算法似乎很少找到正确的参数。我想知道我是否做错了什么 数据由3个不同位置的三个高斯数生成(x=-10、x=5和x=10): 我检查了直方图,x是正确的。通过EM更新完成参数学习: # model and initialization M = 3 # number of mixtures alpha = np.ones(M)*.5 # -> likelihood of the mixture mu = np.random.random

我试图学习混合高斯(1D)中参数估计的期望最大化。然而,该算法似乎很少找到正确的参数。我想知道我是否做错了什么

数据由3个不同位置的三个高斯数生成(
x=-10、x=5和x=10
):

我检查了直方图,x是正确的。通过EM更新完成参数学习:

# model and initialization
M = 3 # number of mixtures
alpha = np.ones(M)*.5 # -> likelihood of the mixture
mu = np.random.random(M)*10 # -> mean of the gaussian
sigma = np.ones(M)*1.0 # -> std of the gaussian

w_mt = np.zeros((M,len(x))) # -> q(mixture | data, parameter)

# EM
for 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) # normalization
    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 # avoid numerical problems
#模型和初始化
M=3#混合料数量
α=np.一(M)*.5#->混合物的可能性
mu=np.随机.随机(M)*10#->高斯分布的平均值
sigma=np.one(M)*1.0#->高斯分布的标准
w_mt=np.zeros((M,len(x))#->q(混合数据,参数)
#EM
对于范围(100)内的i:
打印“α:”,α,“μ:”,μ,“σ:”,σ
#电子步
对于范围内的m(m):
w_mt[m]=alpha[m]*mlab.normpdf(x,mu[m],sigma[m])
C=np.和(w_mt,轴=0)#归一化
w_mt=w_mt/C
#M步
α=np.和(w_mt,轴=1)/len(x)
μ=np.和(w_mt*x,轴=1)/np.和(w_mt,轴=1)
sigma=np.sum(w_mt*pow(x-mu[:,np.newaxis],2),axis=1)/np.sum(w_mt,axis=1)
西格玛[西格玛<0.1]=0.1#避免数值问题
我希望算法(至少有时)能够找到std~=1.0的正确的
mu
(即-10,5,10)。然而,算法似乎永远无法做到这一点。谢谢你的帮助

更新:


特德·金的修正似乎解决了这个问题。我在计算std时忘了取的平方根。如果有人感兴趣,这里是更新代码的链接:

西格玛是标准偏差,但代码中的西格玛是变化(即西格玛**2)

试一试


通过将平均值
mu
视为向量,将
Sigma
视为协方差矩阵而不是方差,这也可以推广到更高的维度

例如,
k
th高斯的协方差矩阵
Sigma_k
可以在EMM步中用MLE计算,其中
phi[i,k]
表示
i
th数据点属于
k
th簇的概率,在前面的EM算法的E-step中计算

Sigma[k,:,:]=sum([phi[i,k]*np.outer(X[i,:]-mu[k,:],X[i,:]-mu[k,:]),用于范围(n)]内的i)/n_[k]

下图显示了具有
k=3
群集中心的GMM-EM软群集的工作原理:


有关更多详细信息,我们可以参考博文。

如果您碰巧有带宽,我使用了很多您的代码,但遇到了问题。我在这里发布了:
# model and initialization
M = 3 # number of mixtures
alpha = np.ones(M)*.5 # -> likelihood of the mixture
mu = np.random.random(M)*10 # -> mean of the gaussian
sigma = np.ones(M)*1.0 # -> std of the gaussian

w_mt = np.zeros((M,len(x))) # -> q(mixture | data, parameter)

# EM
for 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) # normalization
    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 # avoid numerical problems
sigma = np.sqrt(np.sum(w_mt*pow(x - mu[:,np.newaxis],2),axis=1) / np.sum(w_mt,axis=1))