我一直在研究k-means clustering,有一点不清楚的是你如何选择k的值。这只是一个试验和错误的问题,还是还有更多呢?
答案 0 :(得分:137)
您可以最大化贝叶斯信息准则(BIC):
BIC(C | X) = L(X | C) - (p / 2) * log n
其中L(X | C)
是根据模型X
的数据集C
的对数似然,p
是模型C
中的参数数量,并且n
是数据集中的点数。
请参阅Dan Pelleg和Andrew Moore在ICML 2000中的"X-means: extending K-means with efficient estimation of the number of clusters"。
另一种方法是从k
的较大值开始并继续删除质心(减少k),直到它不再减少描述长度。请参阅模式分析和应用第一卷中的Horst Bischof,Ales Leonardis和Alexander Selb的"MDL principle for robust vector quantisation"。 2,p。 59-72,1999。
最后,您可以从一个群集开始,然后继续分割群集,直到分配给每个群集的点具有高斯分布。在"Learning the k in k-means"(NIPS 2003)中,Greg Hamerly和Charles Elkan展示了一些证据表明这比BIC更好,并且BIC并没有足够强烈地惩罚模型的复杂性。
答案 1 :(得分:36)
基本上,您希望在两个变量之间找到平衡:群集数量( k )和群集的平均方差。您希望最小化前者,同时最小化后者。当然,随着聚类数量的增加,平均方差减小(直到 k = n 和方差= 0)的平凡情况。
与数据分析一样,在所有情况下,没有一种方法比其他方法更好。最后,你必须使用自己最好的判断。为此,有助于根据平均方差绘制聚类数(假设您已经为 k 的多个值运行了算法)。然后你可以使用曲线拐点处的簇数。
答案 2 :(得分: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")
希望它有所帮助!!
答案 3 :(得分:8)
可能是像我这样的初学者寻找代码示例。 silhouette_score 的信息 可用here.
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)
答案 4 :(得分:7)
查看this论文,&#34;用k-means学习k&#34;作者:Greg Hamerly,Charles Elkan。它使用高斯检验来确定正确的簇数。此外,作者声称这种方法比接受答案中提到的BIC更好。
答案 5 :(得分:4)
有一种称为经验法则的东西。它表示簇的数量可以通过k =(n / 2)^ 0,5来计算,其中n是样本中元素的总数。 您可以在以下文件中查看此信息的准确性:
http://www.ijarcsms.com/docs/paper/volume1/issue6/V1I6-0015.pdf
还有另一种叫做G-means的方法,你的分布遵循高斯分布或正态分布。 它包括增加k,直到你的所有k组都遵循高斯分布。 它需要大量的统计数据,但可以完成。 这是来源:
http://papers.nips.cc/paper/2526-learning-the-k-in-k-means.pdf
我希望这有帮助!
答案 6 :(得分:3)
首先构建minimum spanning tree数据。
移除K-1最昂贵的边缘将树分成K个簇,
所以你可以构建一次MST,查看各种K的簇间距/度量,
并采取曲线的膝盖。
这仅适用于Single-linkage_clustering, 但为此,它快速而简单。另外,MST可以提供良好的视觉效果 例如,参见下面的MST图 stats.stackexchange visualization software for clustering
答案 7 :(得分:3)
如果您使用MATLAB(自2013b以来的任何版本),您可以使用函数evalclusters
来找出给定数据集的最佳k
应该是什么。
此功能可让您从3种聚类算法中进行选择 - kmeans
,linkage
和gmdistribution
。
它还允许您从4个群集评估标准中进行选择 - CalinskiHarabasz
,DaviesBouldin
,gap
和silhouette
。
答案 8 :(得分:2)
我很惊讶没人提到这篇优秀的文章: http://www.ee.columbia.edu/~dpwe/papers/PhamDN05-kmeans.pdf
在听完其他几条建议后,我在阅读本博文时终于看到了这篇文章: https://datasciencelab.wordpress.com/2014/01/21/selection-of-k-in-k-means-clustering-reloaded/
之后我在Scala中实现了它,这个实现为我的用例提供了非常好的结果。这是代码:
import breeze.linalg.DenseVector
import Kmeans.{Features, _}
import nak.cluster.{Kmeans => NakKmeans}
import scala.collection.immutable.IndexedSeq
import scala.collection.mutable.ListBuffer
/*
https://datasciencelab.wordpress.com/2014/01/21/selection-of-k-in-k-means-clustering-reloaded/
*/
class Kmeans(features: Features) {
def fkAlphaDispersionCentroids(k: Int, dispersionOfKMinus1: Double = 0d, alphaOfKMinus1: Double = 1d): (Double, Double, Double, Features) = {
if (1 == k || 0d == dispersionOfKMinus1) (1d, 1d, 1d, Vector.empty)
else {
val featureDimensions = features.headOption.map(_.size).getOrElse(1)
val (dispersion, centroids: Features) = new NakKmeans[DenseVector[Double]](features).run(k)
val alpha =
if (2 == k) 1d - 3d / (4d * featureDimensions)
else alphaOfKMinus1 + (1d - alphaOfKMinus1) / 6d
val fk = dispersion / (alpha * dispersionOfKMinus1)
(fk, alpha, dispersion, centroids)
}
}
def fks(maxK: Int = maxK): List[(Double, Double, Double, Features)] = {
val fadcs = ListBuffer[(Double, Double, Double, Features)](fkAlphaDispersionCentroids(1))
var k = 2
while (k <= maxK) {
val (fk, alpha, dispersion, features) = fadcs(k - 2)
fadcs += fkAlphaDispersionCentroids(k, dispersion, alpha)
k += 1
}
fadcs.toList
}
def detK: (Double, Features) = {
val vals = fks().minBy(_._1)
(vals._3, vals._4)
}
}
object Kmeans {
val maxK = 10
type Features = IndexedSeq[DenseVector[Double]]
}
答案 9 :(得分:1)
一个可能的答案是使用像遗传算法这样的元启发式算法来找到k。 这很简单。您可以使用随机K(在某些范围内)并使用像Silhouette这样的一些测量来评估遗传算法的拟合函数 并根据拟合函数找出最佳K.
答案 10 :(得分:1)
如果您不知道要作为k均值参数提供的簇k的数目,那么有四种方法可以自动找到它:
G均值算法:它使用统计检验来自动确定集群数,以决定是否将k均值中心一分为二。该算法采用分层方法来检测聚类的数量,该方法基于对数据子集遵循高斯分布(近似于事件的精确二项式分布的连续函数)的假设的统计检验,如果没有,它将对聚类进行拆分。它以少数几个中心开始,例如仅说一个群集(k = 1),然后该算法将其拆分为两个中心(k = 2),然后再次将这两个中心分别拆分为(k = 4),其中有四个中心总。如果G-means不接受这四个中心,则答案是上一步:在这种情况下为两个中心(k = 2)。这是您的数据集将被划分的聚类数。当您没有对实例分组后将获得的群集数量的估计时,G均值非常有用。请注意,对“ k”参数的不便选择可能会给您带来错误的结果。 g均值的并行版本称为p-means。 G均值来源: source 1 source 2 source 3
x-means:一种新算法,可以有效地搜索聚类位置的空间和聚类数量,以优化贝叶斯信息准则(AIC)或贝叶斯信息准则(AIC)度量。此版本的k均值可以找到数字k,并且可以加速k均值。
在线k均值或流式k均值:它允许通过扫描整个数据一次来执行k均值,并自动找到k的最佳数量。 Spark实现了它。
MeanShift algorithm:这是一种非参数聚类技术,不需要先验聚类数量,也不限制聚类的形状。均值漂移聚类旨在发现平滑密度的样本中的“斑点”。这是基于质心的算法,通过将质心的候选更新为给定区域内点的均值来工作。然后在后处理阶段对这些候选对象进行过滤,以消除几乎重复的对象,从而形成最后的质心集。来源:source1,source2,source3
答案 11 :(得分:1)
另一种方法是使用自组织图(SOP)查找最佳数目的群集。 SOM(自组织图)是一种无监督的神经 网络方法,只需要输入即可 聚类以解决问题。在有关客户细分的论文中使用了这种方法。
本文的参考文献是
Abdellah Amine等人,《电子商务使用中的客户细分模型》 聚类技术和LRFM模型:案例 世界科学,工程和技术研究院摩洛哥在线商店的研究 国际计算机与信息工程杂志 Vol:9,No:8,2015,1999-2010
答案 12 :(得分:1)
km=[]
for i in range(num_data.shape[1]):
kmeans = KMeans(n_clusters=ncluster[i])#we take number of cluster bandwidth theory
ndata=num_data[[i]].dropna()
ndata['labels']=kmeans.fit_predict(ndata.values)
cluster=ndata
co=cluster.groupby(['labels'])[cluster.columns[0]].count()#count for frequency
me=cluster.groupby(['labels'])[cluster.columns[0]].median()#median
ma=cluster.groupby(['labels'])[cluster.columns[0]].max()#Maximum
mi=cluster.groupby(['labels'])[cluster.columns[0]].min()#Minimum
stat=pd.concat([mi,ma,me,co],axis=1)#Add all column
stat['variable']=stat.columns[1]#Column name change
stat.columns=['Minimum','Maximum','Median','count','variable']
l=[]
for j in range(ncluster[i]):
n=[mi.loc[j],ma.loc[j]]
l.append(n)
stat['Class']=l
stat=stat.sort(['Minimum'])
stat=stat[['variable','Class','Minimum','Maximum','Median','count']]
if missing_num.iloc[i]>0:
stat.loc[ncluster[i]]=0
if stat.iloc[ncluster[i],5]==0:
stat.iloc[ncluster[i],5]=missing_num.iloc[i]
stat.iloc[ncluster[i],0]=stat.iloc[0,0]
stat['Percentage']=(stat[[5]])*100/count_row#Freq PERCENTAGE
stat['Cumulative Percentage']=stat['Percentage'].cumsum()
km.append(stat)
cluster=pd.concat(km,axis=0)## see documentation for more info
cluster=cluster.round({'Minimum': 2, 'Maximum': 2,'Median':2,'Percentage':2,'Cumulative Percentage':2})
答案 13 :(得分:1)
假设您有一个名为DATA
的数据矩阵,您可以通过估计群集数量(通过轮廓分析)对medoids进行分区,如下所示:
library(fpc)
maxk <- 20 # arbitrary here, you can set this to whatever you like
estimatedK <- pamk(dist(DATA), krange=1:maxk)$nc
答案 14 :(得分:1)
我的想法是使用Silhouette Coefficient来找到最佳群集编号(K)。详细说明为here。
答案 15 :(得分:0)
我使用了我在这里找到的解决方案:http://efavdb.com/mean-shift/,它对我来说效果非常好:
import numpy as np
from sklearn.cluster import MeanShift, estimate_bandwidth
from sklearn.datasets.samples_generator import make_blobs
import matplotlib.pyplot as plt
from itertools import cycle
from PIL import Image
#%% Generate sample data
centers = [[1, 1], [-.75, -1], [1, -1], [-3, 2]]
X, _ = make_blobs(n_samples=10000, centers=centers, cluster_std=0.6)
#%% Compute clustering with MeanShift
# The bandwidth can be automatically estimated
bandwidth = estimate_bandwidth(X, quantile=.1,
n_samples=500)
ms = MeanShift(bandwidth=bandwidth, bin_seeding=True)
ms.fit(X)
labels = ms.labels_
cluster_centers = ms.cluster_centers_
n_clusters_ = labels.max()+1
#%% Plot result
plt.figure(1)
plt.clf()
colors = cycle('bgrcmykbgrcmykbgrcmykbgrcmyk')
for k, col in zip(range(n_clusters_), colors):
my_members = labels == k
cluster_center = cluster_centers[k]
plt.plot(X[my_members, 0], X[my_members, 1], col + '.')
plt.plot(cluster_center[0], cluster_center[1],
'o', markerfacecolor=col,
markeredgecolor='k', markersize=14)
plt.title('Estimated number of clusters: %d' % n_clusters_)
plt.show()
答案 16 :(得分:0)
嗨,我将简单明了地进行解释,我想使用“ NbClust”库确定簇。
现在,如何使用'NbClust'函数确定正确的群集数量:您可以使用实际数据和群集检查Github中的实际项目-该'kmeans'算法的扩展也使用正确的'中心”。
Github项目链接:https://github.com/RutvijBhutaiya/Thailand-Customer-Engagement-Facebook
答案 17 :(得分:0)
您可以通过直观地检查数据点来选择群集的数量,但是您很快就会意识到,除了最简单的数据集之外,所有其他过程在此过程中都存在很多歧义。这并不总是不好的,因为您正在做无监督学习,并且在标记过程中存在一些固有的主观性。在这里,具有该特定问题或类似问题的先前经验将帮助您选择正确的价值。
如果您需要有关应使用的簇数的一些提示,则可以应用Elbow方法:
首先,计算某些k值(例如2、4、6、8等)的平方误差总和(SSE)。 SSE定义为群集的每个成员与其质心之间的平方距离的总和。数学上:
SSE = ∑Ki = 1∑x∈cidist(x,ci)2
如果针对SSE绘制k,您会发现随着k的增大,误差减小;反之,这是因为当簇的数量增加时,它们应该较小,因此失真也较小。弯头法的想法是选择SSE突然减小的k。如下图所示,这会在图形中产生“肘部效果”:
在这种情况下,k = 6是Elbow方法选择的值。考虑到Elbow方法是一种启发式方法,因此,在您的特定情况下它可能会或可能不会很好地起作用。有时,肘部不止一个,甚至根本没有。在这种情况下,您通常最终会通过评估k-means在您要解决的特定聚类问题中的表现来计算出最佳k。
答案 18 :(得分:0)
我研究了跪着的Python软件包(跪着算法)。它动态地找到簇号作为曲线开始变平的点。给定一组x和y值,knee将返回函数的拐点。膝关节是最大弯曲点。这是示例代码。
y = [7342.1301373073857, 6881.7109460930769, 6531.1657905495022,
6356.2255554679778, 6209.8382535595829, 6094.9052166741121,
5980.0191582610196, 5880.1869867848218, 5779.8957906367368,
5691.1879324562778, 5617.5153566271356, 5532.2613232619951,
5467.352265375117, 5395.4493783888756, 5345.3459908298091,
5290.6769823693812, 5243.5271656371888, 5207.2501206569532,
5164.9617535255456]
x = range(1, len(y)+1)
from kneed import KneeLocator
kn = KneeLocator(x, y, curve='convex', direction='decreasing')
print(kn.knee)
答案 19 :(得分:0)