我在尝试为机器学习中的k-means方法找到合适的k聚类。我使用了肘部法,但它耗时且复杂度高。有人能告诉我另一个替代方法吗?非常感谢
回答:
你可以用来评估聚类结果的一个指标是轮廓系数。这个值基本上是计算出来的:
silhouette coefficient = 1 - (intra-cluster cohesion) / (inter-cluster separation)
这个值的范围是从-1到+1,但通常你希望值更接近1.0。因此,如果你运行一个聚类算法(例如k-means或层次聚类)来生成3个聚类,你可以调用轮廓库来计算一个轮廓系数值,例如0.50。如果你再次运行你的算法来生成4个聚类,你可能会计算出另一个轮廓系数值,例如0.55。你可以得出结论,4个聚类是更好的聚类,因为它有更高的轮廓系数。
以下是我使用R在二维空间中创建三个不同聚类的示例数据集。注意:现实世界的数据永远不会像这样干净,且聚类之间的分隔如此明显。即使是像费希尔 Iris 数据集这样简单的数据,也会在标记的聚类之间有重叠。
然后你可以使用R的轮廓库来计算轮廓系数。(更多信息可以在STHDA网站找到。)以下是轮廓信息的图表。你想要的一个指标在左下角,显示“平均轮廓宽度:xxx”。那个值是所有水平条的平均值。
这是K=2聚类的轮廓系数。
plot(silhouette(kmeans(df, centers=2)$cluster, dist(df)))
这是K=3聚类的轮廓系数。
plot(silhouette(kmeans(df, centers=3)$cluster, dist(df)))
这是K=4聚类的轮廓系数。
plot(silhouette(kmeans(df, centers=4)$cluster, dist(df)))
通过查看轮廓系数,你可以得出结论,K=3聚类是最好的聚类,因为它具有最高的轮廓系数。
你可以通过简单地扫描多个K值候选(例如从2到10)并跟踪找到的最高轮廓系数来以编程方式找到最佳的K值。下面我已经做了同样的事情,同时还构建了一个轮廓系数(y轴)与K值(x轴)的图表。输出显示:
最佳轮廓系数=0.888926出现在k=3
library(cluster) # for silhouettelibrary(ggplot2) # for ggplotlibrary(scales) # for pretty_breaks# 创建包含聚类在点(1,1)、(2,4)和(3,1)周围的二维数据集示例x<- c(rnorm(n=25, mean=1,sd=.1), rnorm(n=25,mean=2,sd=.1),rnorm(n=25,mean=3,sd=.2))y<- c(rnorm(n=25, mean=1,sd=.1), rnorm(n=25,mean=4,sd=.1),rnorm(n=25,mean=1,sd=.2))df <- data.frame(x=x, y=y)xMax <- max(x)yMax <- max(y)print(ggplot(df, aes(x,y)) + geom_point() + xlim(0, max(xMax, yMax)) + ylim(0, max(xMax,yMax)))# 使用Iris数据集。#df <- subset(iris, select=-c(Species))#df <- scale(df)# 运行多个候选K值聚类。xValues <- c() # 保存k值(x轴)yValues <- c() # 保存轮廓系数值(y轴)bestKValue <- 0bestSilhouetteCoefficient <- 0kSequence <- seq(2, 5)for (kValue in kSequence) { xValues <- append(xValues, kValue) kmeansResult <- kmeans(df, centers=kValue, nstart=5) silhouetteResult <- silhouette(kmeansResult$cluster, dist(df)) silhouetteCoefficient <- mean(silhouetteResult[,3]) yValues <- append(yValues, silhouetteCoefficient) if (silhouetteCoefficient > bestSilhouetteCoefficient) { bestSilhouetteCoefficient <- silhouetteCoefficient bestKValue <- kValue }}# 创建一个数据框供ggplot绘制累积的轮廓值。dfSilhouette <- data.frame(k=xValues, silhouetteCoefficient=yValues)# 创建轮廓系数的ggplot线图。silhouettePlot<- ggplot(data=dfSilhouette, aes(k)) + geom_line(aes(y=silhouetteCoefficient)) + xlab("k") + ylab("平均轮廓宽度") + ggtitle("平均轮廓宽度") + scale_x_continuous(breaks=pretty_breaks(n=20)) print(silhouettePlot)printf <- function(...) cat(sprintf(...))printf("最佳轮廓系数=%f出现在k=%d", bestSilhouetteCoefficient, bestKValue )
注意,我使用了来自这里的答案中的printf函数。
与你的问题相关的一个问题在这里。