k- 평균 군집화를 사용할 때 k를 어떻게 결정합니까?


142

k- 평균 군집화 에 대해 연구 해 왔으며 , 분명하지 않은 한 가지는 k 값을 선택하는 방법입니다. 그것은 시행 착오의 문제 일까, 아니면 더 있을까?


34
아 아 ... 그건 정말 (K-평균에 대한) 질문입니다.
mjv 2016

함수 L (로그 가능성)에 대한 코드를 공유 할 수 있습니까? X, Y에 중심이 있고 (x (i = 1,2,3,4, ..., n), y (i = 1,2,3,4, .., n))을 가리키면 어떻게 L을 받습니까?

7
주제에 관한 Wikipedia 기사 링크 : en.wikipedia.org/wiki/…
Amro

11
나는 (사용 대여섯 방법과 유사한 Q 대답했습니다 Rstackoverflow.com/a/15376462/1036500 : 이상 여기에)

답변:


142

베이지안 정보 기준 (BIC)을 최대화 할 수 있습니다.

BIC(C | X) = L(X | C) - (p / 2) * log n

여기서 L(X | C)데이터 집합의 로그 우도되는 X모델에있어서 C, p모델의 변수의 수이고 C, 그리고 n데이터 셋 포인트의 수이다. "X- 평균 : 군집 수를 효율적으로 추정하여 K- 평균 확장"을 참조하십시오 .ICML 2000에서 Dan Pelleg와 Andrew Moore의 .

또 다른 방법은 k더 이상 설명 길이가 줄어들지 않을 때까지 중심 값을 제거하고 계속 제거하는 것입니다 (k 감소). 패턴 분석 및 응용 프로그램 vol. 에서 Horst Bischof, Ales Leonardis 및 Alexander Selb의 "강력한 벡터 정량화를위한 ​​MDL 원리"를 참조하십시오 . 2, p. 1999-59-72.

마지막으로 하나의 군집으로 시작한 다음 각 군집에 지정된 점에 가우스 분포가있을 때까지 군집 분할을 유지할 수 있습니다. 에서 "배우기는 KK -means" (2003 NIPS), 그렉 Hamerly 찰스 Elkan이 작품 더 나은 BIC 이상, 그리고 그 BIC가 충분히 강하게 모델의 복잡성을 처벌하지 않는 몇 가지 증거를 보여줍니다.


좋은 답변입니다! X- 평균의 경우 전체 BIC 점수가 n : = k * 2 (k 군집, 각 군집이 평균 / 편차 매개 변수를 사용하여 가우시안으로 모델링 됨)인지 알고 있습니다. 또한 "부모"BIC> "2 하위"BIC를 결정한 경우 다음 반복에서 해당 클러스터를 다시 분할 하시겠습니까?
Budric

2
@Budric, 이들은 아마도 별도의 질문이어야하며 stats.stackexchange.com에있을 것입니다.
Vebjorn Ljosa

37

기본적으로 군집 수 ( k )와 군집 의 평균 분산이라는 두 변수 사이의 균형을 찾으려고 합니다. 전자를 최소화하면서 후자를 최소화하려고합니다. 물론 군집 수가 증가함에 따라 평균 분산이 감소합니다 ( k = n 의 사소한 경우까지). 및 분산 = 0 ).

데이터 분석에서 항상 그렇듯이 모든 경우에 다른 모든 방법보다 효과적인 진정한 접근 방법은 없습니다. 결국, 당신은 당신 자신의 최고의 판단을 사용해야합니다. 이를 위해 평균 분산에 대한 군집 수를 표시하는 데 도움이됩니다 (여기서 k의 여러 값에 대해 알고리즘을 이미 실행했다고 가정 ). 그런 다음 곡선의 무릎에 클러스터 수를 사용할 수 있습니다.


24

예, 엘보우 방법을 사용하여 가장 많은 수의 클러스터를 찾을 수 있지만 스크립트를 사용하여 팔꿈치 그래프에서 클러스터의 값을 찾는 것이 번거 롭습니다. 팔꿈치 그래프를 관찰하고 팔꿈치 점을 직접 찾을 수 있지만 스크립트에서 찾는 것은 많은 작업이었습니다.

또 다른 옵션은 Silhouette Method 를 사용 하여 찾는 것입니다. Silhouette의 결과는 R의 엘보우 방법의 결과를 완전히 준수합니다.

여기 내가 한 일이 있습니다.

#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")

그것이 도움이되기를 바랍니다!


2
그냥 파이썬 사용자의 실루엣 분석 튜토리얼에 대한 링크를 추가 scikit-learn.org/stable/auto_examples/cluster/...
Chaitanya Shivade

10

코드 예제를 찾는 나와 같은 초보자가 될 수 있습니다. 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)

9

그렉 Hamerly, 찰스 Elkan에 의해 "K-수단의 K 학습", 종이. 가우스 테스트를 사용하여 올바른 클러스터 수를 결정합니다. 또한 저자는이 방법이 BIC보다 낫다고 주장합니다. 허용 된 답변에 언급되어 있습니다.


7

Thumb of Thumb이라는 것이 있습니다. 클러스터 수는 다음과 같이 계산할 수 있다고 말합니다.

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

이게 도움이 되길 바란다!


3

먼저 데이터 의 최소 스패닝 트리 를 작성하십시오. 가장 비싼 K-1 모서리를 제거하면 트리가 K 클러스터로 분할
되므로 MST를 한 번 작성하고 다양한 K에 대한 클러스터 간격 / 메트릭을보고 곡선을 찾을 수 있습니다.

이것은 Single-linkage_clustering 에만 작동 하지만 빠르고 쉽습니다. 또한, MST는 좋은 시각 자료를 만듭니다.
예를 들어 클러스터링을위한 stats.stackexchange 시각화 소프트웨어 에서 MST 플롯을 참조하십시오 .


3

아무도이 훌륭한 기사를 언급하지 않은 것에 놀랐습니다 : 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/

그 후 스칼라에서 구현했으며 사용 사례에 실제로 좋은 결과를 제공하는 구현입니다. 코드는 다음과 같습니다.

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]]
}

산들 바람 0.12와

안녕하세요 @ eirirlar Python으로 동일한 코드를 구현하려고하는데 웹 사이트의 코드를 따르지 못했습니다. 내 게시물보기 : stackoverflow.com/questions/36729826/python-k-means-clustering
piccolo

@ImranRashid 죄송합니다. 2 차원으로 만 테스트했으며 Python 전문가는 아닙니다.
eirirlar

3

2013b 이후의 모든 버전 인 MATLAB을 사용하는 경우 즉, 함수 evalclusters를 사용 k하여 주어진 데이터 세트에 가장 적합한 항목을 찾을 수 있습니다.

-이 기능을 사용하면 3 클러스터링 알고리즘 중에서 선택할 수 있습니다 kmeans, linkage하고 gmdistribution.

- 그것은 또한 당신이 4 클러스터링 평가 기준 중에서 선택할 수 있습니다 CalinskiHarabasz, DaviesBouldin, gapsilhouette.


3

k- 평균에 매개 변수로 제공 할 군집 k의 수를 모르면 자동으로 찾는 4 가지 방법이 있습니다.

  • G- 평균 알고리즘 : 통계적 테스트를 사용하여 k- 평균 중심을 2 개로 분할할지 여부를 결정하는 군집 수를 자동으로 검색합니다. 이 알고리즘은 데이터의 하위 집합이 가우스 분포 (이벤트의 정확한 이항 분포를 근사하는 연속 함수)를 따르는 가설에 대한 통계적 테스트를 기반으로 클러스터 수를 탐지하기위한 계층 적 접근 방식을 취하며, 그렇지 않은 경우 클러스터를 분할합니다. . 그것은 적은 수의 중심으로 시작합니다 (예 : 하나의 클러스터 만 (k = 1)), 알고리즘은 그것을 두 개의 중심 (k = 2)으로 나누고이 두 중심을 다시 분할합니다 (k = 4). 합계. G- 평균이이 4 개의 중심을 받아들이지 않으면 답은 이전 단계입니다.이 경우에는 2 개의 중심 (k = 2)입니다. 이것은 데이터 세트가 분할 될 클러스터의 수입니다. G- 평균은 인스턴스를 그룹화 한 후 얻을 수있는 군집 수를 예측할 수 없을 때 매우 유용합니다. "k"매개 변수를 잘못 선택하면 잘못된 결과가 나타날 수 있습니다. g- 평균의 병렬 버전을p- 평균 . G- 평균 소스 : 소스 1 소스 2 소스 3

  • x-means : 효율적으로 클러스터 위치 공간과 클러스터 수를 검색하여 BIC (Bayesian Information Criterion) 또는 AIC (Akaike Information Criterion) 측정을 최적화합니다. 이 버전의 k- 평균은 숫자 k를 찾고 k- 평균을 가속화합니다.

  • 온라인 k- 평균 또는 스트리밍 k- 평균 : 전체 데이터를 한 번 스캔하여 k- 평균을 실행할 수 있으며 최적의 k 수를 자동으로 찾습니다. Spark가 구현합니다.

  • MeanShift 알고리즘 : 클러스터의 수에 대한 사전 지식이 필요하지 않고 클러스터의 모양을 제한하지 않는 비모수 적 클러스터링 기술입니다. 평균 이동 클러스터링은 매끄러운 밀도의 샘플에서 "블롭"을 발견하는 것을 목표로합니다. 중심 기반 알고리즘으로, 중심에 대한 후보를 지정된 지역 내 포인트의 평균으로 업데이트하여 작동합니다. 그런 다음 이러한 후보를 후 처리 단계에서 필터링하여 거의 중복되는 부분을 제거하여 최종 중심 세트를 형성합니다. 소스 : source1 , source2 , source3


2

나는 여기에서 찾은 솔루션을 사용했습니다 : 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()

여기에 이미지 설명을 입력하십시오



1

이라는 데이터 매트릭스가 있다고 가정하면 다음 DATA과 같이 (실루엣 분석에 의해) 클러스터 수를 추정하여 메도 이드 주변에서 파티셔닝을 수행 할 수 있습니다.

library(fpc)
maxk <- 20  # arbitrary here, you can set this to whatever you like
estimatedK <- pamk(dist(DATA), krange=1:maxk)$nc

1

가능한 대답 중 하나는 유전자 알고리즘과 같은 메타 휴리스틱 알고리즘을 사용하여 k를 찾는 것입니다. 간단합니다. 임의의 K (일부 범위)를 사용하고 Silhouette And Fit과 같은 최적의 K 기반 찾기와 같은 측정으로 유전자 알고리즘의 적합 함수를 평가할 수 있습니다.

https://en.wikipedia.org/wiki/Silhouette_(clustering)


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})

데이터와 라이브러리 추가를 선택하고 km = []을 Percentage ': 2}에 복사하고 마지막으로 파이썬을 실행하고 참조하십시오
sumit

스택 오버플로에 오신 것을 환영합니다! 이 코드는 문제를 해결하는 데 도움이 될 수 있지만 질문에 그리고 / 또는 어떻게 대답 하는지 는 설명하지 않습니다 . 이러한 추가 맥락을 제공하면 장기적인 교육 가치가 크게 향상 될 것입니다. 제발 편집 제한 및 가정이 적용되는 것을 포함하여, 설명을 추가 답변을.
Toby Speight

1

또 다른 방법은 SOP (Self Organizing Maps)를 사용하여 최적의 클러스터 수를 찾는 것입니다. SOM (Self-Organizing Map)은 감독되지 않은 신경망 방법론으로, 문제 해결을 위해 입력 만 클러스터링에 사용하면됩니다. 이 접근법은 고객 세분화에 관한 논문에서 사용되었습니다.

논문의 참조는

Abdellah Amine et al., 클러스터링 기술 및 LRFM 모델을 사용한 전자 상거래에서의 고객 세분화 모델 : 모로코 온라인 매장 사례, 세계 과학 기술 공학 아카데미 국제 컴퓨터 및 정보 공학 저널 Vol : 9, No : 8 , 2015, 1999-2010


0

안녕하세요, 간단하고 간단하게 설명하겠습니다. 'NbClust'라이브러리를 사용하여 클러스터를 결정하고 싶습니다.

이제 'NbClust'함수를 사용하여 올바른 클러스터 수를 결정하는 방법 : 실제 데이터 및 클러스터를 사용하여 Github의 실제 프로젝트를 확인할 수 있습니다.이 'kmeans'알고리즘에 대한 범위도 올바른 수의 '센터'를 사용하여 수행됩니다.

Github 프로젝트 링크 : https://github.com/RutvijBhutaiya/Thailand-Customer-Engagement-Facebook


github 링크를 추가하는 대신 코드에 도달 할 수없는 경우에도 다른 사람들을 도울 수있는 몇 가지 주요 코드 줄을 추가 할 수 있습니까?
Giulio Caccin

0

데이터 포인트를 육안으로 검사하여 클러스터 수를 선택할 수 있지만, 가장 간단한 데이터 세트를 제외한 모든 프로세스에 대해이 프로세스에 많은 모호성이 있음을 곧 알게 될 것입니다. 감독되지 않은 학습을 수행하고 라벨링 프로세스에 고유 한 주관성이 있기 때문에 항상 나쁜 것은 아닙니다. 여기서 특정 문제 또는 이와 비슷한 문제에 대한 이전 경험이 있으면 올바른 가치를 선택하는 데 도움이됩니다.

사용해야하는 군집 수에 대한 힌트를 원하면 Elbow 방법을 적용 할 수 있습니다.

먼저 k의 일부 값 (예 : 2, 4, 6, 8 등)에 대한 제곱 오차의 합 (SSE)을 계산하십시오. SSE는 군집의 각 구성원과 중심 사이의 제곱 거리의 합으로 정의됩니다. 수학적으로 :

SSE = ∑Ki = 1∑x∈cidist (x, ci) 2

SSE에 대해 k를 플로팅하면 k가 커질수록 오류가 줄어드는 것을 볼 수 있습니다. 클러스터 수가 증가하면 더 작아야하기 때문에 왜곡도 작아지기 때문입니다. 엘보우 방법의 아이디어는 SSE가 갑자기 감소하는 k를 선택하는 것입니다. 다음 그림에서 볼 수 있듯이 그래프에 "팔꿈치 효과"가 생성됩니다.

여기에 이미지 설명을 입력하십시오

이 경우 k = 6은 엘보우 방법이 선택한 값입니다. 엘보우 방법은 휴리스틱이므로 특정 경우에는 제대로 작동하지 않을 수 있습니다. 때로는 팔꿈치가 두 개 이상이거나 팔꿈치가 전혀없는 경우가 있습니다. 이러한 상황에서는 일반적으로 해결하려는 특정 군집 문제와 관련하여 k- 평균의 성능을 평가하여 최상의 k를 계산하게됩니다.


0

나는 Python 패키지 kneed (Kneedle 알고리즘)에서 일했습니다. 곡선이 평평 해지기 시작하는 지점으로 군집 수를 동적으로 찾습니다. 니 포인트는 최대 곡률의 포인트입니다. 샘플 코드는 다음과 같습니다.

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 = 범위 (1, len (y) +1)

니들 임포트에서 KneeLocator kn = KneeLocator (x, y, 곡선 = '볼록한', 방향 = '감소')

프린트 (무릎)


다른 사람들이 배울 수 있도록 답변에 설명을 추가하십시오
Nico Haase
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.