使用k-means聚类时如何确定k?

Jas*_*ker 136 cluster-analysis k-means

我一直在研究k-means聚类,有一点不清楚你是如何选择k的值的.这只是一个反复试验的问题,还是有更多的问题?

Veb*_*osa 140

您可以最大化贝叶斯信息准则(BIC):

BIC(C | X) = L(X | C) - (p / 2) * log n
Run Code Online (Sandbox Code Playgroud)

其中L(X | C)在所述数据集的对数似然X根据模型C,p是在模型参数的数量C,并且n是在数据集中的点的数量.参见Dan Pelleg和Andrew Moore在ICML 2000中的"X-means:扩展K -means并有效估计簇的数量".

另一种方法是从较大的值开始k并继续移除质心(减少k),直到它不再减少描述长度.参见Horst Bischof,Ales Leonardis和Alexander Selb在Pattern Analysis and Applications vol.中的"MDL原理用于鲁棒矢量量化".2,p.1999年9月59日至72日.

最后,您可以从一个群集开始,然后继续分割群集,直到分配给每个群集的点具有高斯分布.在"学习k -me 中的k "(NIPS 2003)中,Greg Hamerly和Charles Elkan展示了一些证据表明这比BIC更好,并且BIC并没有足够强烈地惩罚模型的复杂性.

  • @Budric,这些应该是单独的问题,也许在stats.stackexchange.com上. (2认同)

Jan*_*ger 36

基本上,您希望在两个变量之间找到平衡:聚类数(k)和聚类的平均方差.您希望最小化前者,同时最小化后者.当然,随着聚类数量的增加,平均方差减小(直到k = n和方差= 0 的平凡情况).

与数据分析一样,在所有情况下,没有一种方法比其他方法更好.最后,你必须使用自己最好的判断.为此,有助于根据平均方差绘制聚类数(假设您已经为几个k值运行了算法).然后,您可以使用曲线拐点处的簇数.


小智 23

是的,您可以使用Elbow方法找到最佳数量的聚类,但我发现使用脚本从肘图中找到聚类的值很麻烦.您可以观察肘图并自己找到肘部点,但是从脚本中找到它的工作很多.

所以另一种选择是使用Silhouette Method来找到它.Silhouette的结果完全符合R中Elbow方法的结果.

这就是我所做的.

#Dataset for Clustering
n = 150
g = 6 
set.seed(g)
d <- data.frame(x = unlist(lapply(1:g, function(i) rnorm(n/g, runif(1)*i^2))), 
                y = unlist(lapply(1:g, function(i) rnorm(n/g, runif(1)*i^2))))
mydata<-d
#Plot 3X2 plots
attach(mtcars)
par(mfrow=c(3,2))

#Plot the original dataset
plot(mydata$x,mydata$y,main="Original Dataset")

#Scree plot to deterine the number of clusters
wss <- (nrow(mydata)-1)*sum(apply(mydata,2,var))
  for (i in 2:15) {
    wss[i] <- sum(kmeans(mydata,centers=i)$withinss)
}   
plot(1:15, wss, type="b", xlab="Number of Clusters",ylab="Within groups sum of squares")

# Ward Hierarchical Clustering
d <- dist(mydata, method = "euclidean") # distance matrix
fit <- hclust(d, method="ward") 
plot(fit) # display dendogram
groups <- cutree(fit, k=5) # cut tree into 5 clusters
# draw dendogram with red borders around the 5 clusters 
rect.hclust(fit, k=5, border="red")

#Silhouette analysis for determining the number of clusters
library(fpc)
asw <- numeric(20)
for (k in 2:20)
  asw[[k]] <- pam(mydata, k) $ silinfo $ avg.width
k.best <- which.max(asw)

cat("silhouette-optimal number of clusters:", k.best, "\n")
plot(pam(d, k.best))

# K-Means Cluster Analysis
fit <- kmeans(mydata,k.best)
mydata 
# get cluster means 
aggregate(mydata,by=list(fit$cluster),FUN=mean)
# append cluster assignment
mydata <- data.frame(mydata, clusterid=fit$cluster)
plot(mydata$x,mydata$y, col = fit$cluster, main="K-means Clustering results")
Run Code Online (Sandbox Code Playgroud)

希望能帮助到你!!

  • 只需向python用户添加到Silhouette Analysis教程的链接,即可http://scikit-learn.org/stable/auto_examples/cluster/plot_kmeans_silhouette_analysis.html#sphx-glr-auto-examples-cluster-plot-kmeans-silhouette-analysis- py (2认同)

bha*_*tel 9

可能是像我这样的初学者寻找代码示例.有关silhouette_score的信息, 请点击此处.

from sklearn.cluster import KMeans
from sklearn.metrics import silhouette_score

range_n_clusters = [2, 3, 4]            # clusters range you want to select
dataToFit = [[12,23],[112,46],[45,23]]  # sample data
best_clusters = 0                       # best cluster number which you will get
previous_silh_avg = 0.0

for n_clusters in range_n_clusters:
    clusterer = KMeans(n_clusters=n_clusters)
    cluster_labels = clusterer.fit_predict(dataToFit)
    silhouette_avg = silhouette_score(dataToFit, cluster_labels)
    if silhouette_avg > previous_silh_avg:
        previous_silh_avg = silhouette_avg
        best_clusters = n_clusters

# Final Kmeans for best_clusters
kmeans = KMeans(n_clusters=best_clusters, random_state=0).fit(dataToFit)
Run Code Online (Sandbox Code Playgroud)


Par*_*kar 7

看看这篇论文,由Greg Hamerly,Charles Elkan撰写的"以k-means学习k".它使用高斯检验来确定正确的簇数.此外,作者声称这种方法比接受的答案中提到的BIC更好.


小智 6

有一种所谓的经验法则。它说可以通过

k = (n/2)^0.5

其中n是样本中元素的总数。您可以在以下纸张上检查此信息的准确性:

http://www.ijarcsms.com/docs/paper/volume1/issue6/V1I6-0015.pdf

还有另一种称为G均值的方法,您的分布遵循高斯分布或正态分布。它包括增加k直到所有k组都遵循高斯分布。它需要大量统计信息,但可以完成。来源如下:

http://papers.nips.cc/paper/2526-learning-the-k-in-k-means.pdf

我希望这有帮助!