正如您所指出的,集群 1 和集群 2 的平均值非常相似,并且碰巧那里有相当多的数据(请参见直方图上的峰值):
set.seed(111)
data <- read.csv("example.csv", header=TRUE, check.names = FALSE)
fit <- Mclust(data$value, modelNames="E", G = 1:7)
hist(data$value,br=50)
abline(v=fit$parameters$mean,
col=c("#FF000080","#0000FF80","#BEBEBE80","#BEBEBE80"),lty=8)
简而言之,mclust 或 gmm 是概率模型,它估计簇的均值/方差以及属于每个簇的每个点的概率。这与 k-means 提供的硬分配不同。所以模型的似然度就是每个数据点属于每个簇的概率之和,你可以查看一下也在 mclust 的出版物中 https://www.ncbi.nlm.nih.gov/pmc/articles/PMC5096736/
在此模型中,聚类 1 和聚类 2 的均值接近,但它们的预期比例不同:
fit$parameters$pro
[1] 0.28565736 0.42933294 0.25445342 0.03055627
这意味着如果您有一个大约为 1 或 2 均值的数据点,它将一致地分配给聚类 2,例如,让我们尝试预测从 1350 到 1400 的数据点:
head(predict(fit,1350:1400)$z)
1 2 3 4
[1,] 0.3947392 0.5923461 0.01291472 2.161694e-09
[2,] 0.3945941 0.5921579 0.01324800 2.301397e-09
[3,] 0.3944456 0.5919646 0.01358975 2.450108e-09
[4,] 0.3942937 0.5917661 0.01394020 2.608404e-09
[5,] 0.3941382 0.5915623 0.01429955 2.776902e-09
[6,] 0.3939790 0.5913529 0.01466803 2.956257e-09
The $classification
通过取概率最大的列来获得。因此,同样的示例,所有内容都分配给 2:
head(predict(fit,1350:1400)$classification)
[1] 2 2 2 2 2 2
回答你的问题,不,你没有做错任何事,至少对于 GMM 的实现来说,这是一个后备。我想说这有点过度拟合,但你基本上可以只采用具有成员资格的集群。
如果您使用 model="V",我发现解决方案同样有问题:
fitv <- Mclust(Data$value, modelNames="V", G = 1:7)
plot(fitv,what="classification")
使用 scikit learn GMM 我没有看到类似的问题。因此,如果您需要使用具有球形均值的高斯混合,请考虑使用模糊 kmeans:
library(ClusterR)
plot(NULL,xlim=range(data),ylim=c(0,4),ylab="cluster",yaxt="n",xlab="values")
points(data$value,fit_kmeans$clusters,pch=19,cex=0.1,col=factor(fit_kmeans$clusteraxis(2,1:3,as.character(1:3))
如果不需要等方差,可以使用GMM https://rdrr.io/cran/ClusterR/man/GMM.htmlClusterR 包中也有此功能。