0

我正在尝试在数据集 data=[[x,y],...] 上实现期望最大化算法(高斯混合模型)。我正在使用mv_norm.pdf(data, mean,cov)函数来计算集群责任。但是在 6-7 次迭代后计算新的协方差值(cov 矩阵)后,cov 矩阵变得奇异,即 cov 的行列式为 0(非常小的值),因此它给出了错误

ValueError:输入矩阵必须是半正定的

raise np.linalg.LinAlgError('奇异矩阵')

有人可以为此提出任何解决方案吗?

#E-step: Compute cluster responsibilities, given cluster parameters
def calculate_cluster_responsibility(data,centroids,cov_m):
    pdfmain=[[] for i in range(0,len(data))]
    for i in range(0,len(data)):
        sum1=0
        pdfeach=[[] for m in range(0,len(centroids))]
        pdfeach[0]=1/3.*mv_norm.pdf(data[i], mean=centroids[0],cov=[[cov_m[0][0][0],cov_m[0][0][1]],[cov_m[0][1][0],cov_m[0][1][1]]])
        pdfeach[1]=1/3.*mv_norm.pdf(data[i], mean=centroids[1],cov=[[cov_m[1][0][0],cov_m[1][0][1]],[cov_m[1][1][0],cov_m[0][1][1]]])
        pdfeach[2]=1/3.*mv_norm.pdf(data[i], mean=centroids[2],cov=[[cov_m[2][0][0],cov_m[2][0][1]],[cov_m[2][1][0],cov_m[2][1][1]]])
        sum1+=pdfeach[0]+pdfeach[1]+pdfeach[2]
        pdfeach[:] = [x / sum1 for x in pdfeach]
        pdfmain[i]=pdfeach

    global old_pdfmain
    if old_pdfmain==pdfmain:
        return
    old_pdfmain=copy.deepcopy(pdfmain)
    softcounts=[sum(i) for i in zip(*pdfmain)]
    calculate_cluster_weights(data,centroids,pdfmain,soft counts)

最初,我为每个聚类协方差传递了 [[3,0],[0,3]],因为预期的聚类数为 3。

4

1 回答 1

1

有人可以为此提出任何解决方案吗?

问题是您的数据存在于一些严格小于输入数据的维度中。换句话说,例如您的数据位于一个圆圈上,而您有 3 维数据。因此,当您的方法尝试估计适合您的数据的 3 维椭圆体(协方差矩阵)时 - 它会失败,因为最佳椭圆是 2 维椭圆(第三维为 0)。

如何解决?您将需要对协方差估计器进行一些正则化。有很多可能的解决方案,都在 M 步,而不是 E 步,问题在于计算协方差:

  • 简单的解决方案,而不是像cov = np.cov(X)添加一些正则化术语那样做一些事情,比如cov = np.cov(X) + eps * np.identity(X.shape[1])eps
  • 使用更好的估计器,例如来自 scikit-learn 的 LedoitWolf 估计器

最初,我为每个聚类协方差传递了 [[3,0],[0,3]],因为预期的聚类数为 3。

这是没有意义的,协方差矩阵值与簇的数量无关。你可以用任何或多或少合理的东西来初始化它。

于 2016-10-01T09:53:57.933 回答