R'de küme analizi: optimum küme sayısını belirleme


428

R'de bir acemi olmak, k-ortalama analizi yapmak için en iyi kümeleri nasıl seçeceğimi bilmiyorum. Aşağıdaki verilerin bir alt kümesini çizdikten sonra kaç küme uygun olur? Küme dendro analizini nasıl yapabilirim?

n = 1000
kk = 10    
x1 = runif(kk)
y1 = runif(kk)
z1 = runif(kk)    
x4 = sample(x1,length(x1))
y4 = sample(y1,length(y1)) 
randObs <- function()
{
  ix = sample( 1:length(x4), 1 )
  iy = sample( 1:length(y4), 1 )
  rx = rnorm( 1, x4[ix], runif(1)/8 )
  ry = rnorm( 1, y4[ix], runif(1)/8 )
  return( c(rx,ry) )
}  
x = c()
y = c()
for ( k in 1:n )
{
  rPair  =  randObs()
  x  =  c( x, rPair[1] )
  y  =  c( y, rPair[2] )
}
z <- rnorm(n)
d <- data.frame( x, y, z )

4
Tamamıyla kmeans'e bağlı değilseniz, pakette bulunan DBSCAN kümeleme algoritmasını deneyebilirsiniz fpc. Doğru, o zaman iki parametre ayarlamanız gerekiyor ... ama o fpc::dbscanzaman çok sayıda kümeyi otomatik olarak belirlemede oldukça iyi bir iş çıkardığını gördüm . Ayrıca, verilerin size söylediği şey varsa, tek bir küme çıktısı verebilir. @ Ben'in mükemmel yanıtlarındaki yöntemlerden bazıları, k = 1'in gerçekten en iyi olup olmadığını belirlemenize yardımcı olmaz.
Stephan Kolassa

Yanıtlar:


1020

Sorunuz, how can I determine how many clusters are appropriate for a kmeans analysis of my data?zaman burada bazı seçeneklerdir. Wikipedia makale kümelerinin numaralarını belirleyen bu yöntemlerden bazıları iyi yaptı.

İlk olarak, bazı tekrarlanabilir veriler (Q'daki veriler ... benim için net değil):

n = 100
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))))
plot(d)

resim açıklamasını buraya girin

Bir tane . Kareli hata (SSE) dağlama grafiğinin toplamında bir bükülme veya dirsek arayın. Daha fazla bilgi için http://www.statmethods.net/advstats/cluster.html & http://www.mattpeeples.net/kmeans.html adresine bakın . Dirseğin ortaya çıkan arsadaki yeri, kmeanlar için uygun sayıda küme önerir:

mydata <- d
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")

4 kümenin bu yöntemle belirtileceği sonucuna varabiliriz: resim açıklamasını buraya girin

İki . Fpc pamkpaketindeki işlevi kullanarak küme sayısını tahmin etmek için medoidler arasında bölümleme yapabilirsiniz .

library(fpc)
pamk.best <- pamk(d)
cat("number of clusters estimated by optimum average silhouette width:", pamk.best$nc, "\n")
plot(pam(d, pamk.best$nc))

resim açıklamasını buraya girin resim açıklamasını buraya girin

# we could also do:
library(fpc)
asw <- numeric(20)
for (k in 2:20)
  asw[[k]] <- pam(d, k) $ silinfo $ avg.width
k.best <- which.max(asw)
cat("silhouette-optimal number of clusters:", k.best, "\n")
# still 4

Üç . Calinsky kriteri: Kaç kümenin verilere uygun olduğunu teşhis etmek için başka bir yaklaşım. Bu durumda 1 ila 10 grubu deneriz.

require(vegan)
fit <- cascadeKM(scale(d, center = TRUE,  scale = TRUE), 1, 10, iter = 1000)
plot(fit, sortg = TRUE, grpmts.plot = TRUE)
calinski.best <- as.numeric(which.max(fit$results[2,]))
cat("Calinski criterion optimal number of clusters:", calinski.best, "\n")
# 5 clusters!

resim açıklamasını buraya girin

Dört . Parametrelenmiş Gauss karışım modelleri için hiyerarşik kümeleme ile başlatılan Beklenti maksimizasyonu için Bayes Bilgi Kriterlerine göre en uygun modeli ve kümelerin sayısını belirleyin

# See http://www.jstatsoft.org/v18/i06/paper
# http://www.stat.washington.edu/research/reports/2006/tr504.pdf
#
library(mclust)
# Run the function to see how many clusters
# it finds to be optimal, set it to search for
# at least 1 model and up 20.
d_clust <- Mclust(as.matrix(d), G=1:20)
m.best <- dim(d_clust$z)[2]
cat("model-based optimal number of clusters:", m.best, "\n")
# 4 clusters
plot(d_clust)

resim açıklamasını buraya girin resim açıklamasını buraya girin resim açıklamasını buraya girin

Beş . Yakınlık yayılımı (AP) kümelemesi, bkz. Http://dx.doi.org/10.1126/science.1136800

library(apcluster)
d.apclus <- apcluster(negDistMat(r=2), d)
cat("affinity propogation optimal number of clusters:", length(d.apclus@clusters), "\n")
# 4
heatmap(d.apclus)
plot(d.apclus, d)

resim açıklamasını buraya girin resim açıklamasını buraya girin

Altı . Küme Sayısını Tahmin Etmek için Boşluk İstatistiği. Ayrıca hoş bir grafik çıktısı için bazı koda bakın . Burada 2-10 kümeyi deneyin:

library(cluster)
clusGap(d, kmeans, 10, B = 100, verbose = interactive())

Clustering k = 1,2,..., K.max (= 10): .. done
Bootstrapping, b = 1,2,..., B (= 100)  [one "." per sample]:
.................................................. 50 
.................................................. 100 
Clustering Gap statistic ["clusGap"].
B=100 simulated reference sets, k = 1..10
 --> Number of clusters (method 'firstSEmax', SE.factor=1): 4
          logW   E.logW        gap     SE.sim
 [1,] 5.991701 5.970454 -0.0212471 0.04388506
 [2,] 5.152666 5.367256  0.2145907 0.04057451
 [3,] 4.557779 5.069601  0.5118225 0.03215540
 [4,] 3.928959 4.880453  0.9514943 0.04630399
 [5,] 3.789319 4.766903  0.9775842 0.04826191
 [6,] 3.747539 4.670100  0.9225607 0.03898850
 [7,] 3.582373 4.590136  1.0077628 0.04892236
 [8,] 3.528791 4.509247  0.9804556 0.04701930
 [9,] 3.442481 4.433200  0.9907197 0.04935647
[10,] 3.445291 4.369232  0.9239414 0.05055486

Edwin Chen'in boşluk istatistiği uygulamasından elde edilen çıktı: resim açıklamasını buraya girin

Yedi . Ayrıca, küme atamasını görselleştirmek için verilerinizi küme diyagramlarıyla keşfetmeyi faydalı bulabilirsiniz, bkz. Http://www.r-statistics.com/2010/06/clustergram-visualization-and-diagnostics-for-cluster-analysis-r- kod / daha fazla bilgi için.

Sekiz . NbClust paket bir veri kümesi içinde kümelerinin sayısını belirlemek için 30 endeksleri içerir.

library(NbClust)
nb <- NbClust(d, diss=NULL, distance = "euclidean",
        method = "kmeans", min.nc=2, max.nc=15, 
        index = "alllong", alphaBeale = 0.1)
hist(nb$Best.nc[1,], breaks = max(na.omit(nb$Best.nc[1,])))
# Looks like 3 is the most frequently determined number of clusters
# and curiously, four clusters is not in the output at all!

resim açıklamasını buraya girin

Sorunuz şu şekilde how can I produce a dendrogram to visualize the results of my cluster analysisbaşlamalıdır: http://www.statmethods.net/advstats/cluster.html http://www.r-tutor.com/gpu-computing/clustering/hierarchical-cluster-analysis http://gastonsanchez.wordpress.com/2012/10/03/7-ways-to-plot-dendrograms-in-r/ Ve daha egzotik yöntemler için buraya bakın: http://cran.r-project.org/ web / görünümler / Cluster.html

İşte birkaç örnek:

d_dist <- dist(as.matrix(d))   # find distance matrix 
plot(hclust(d_dist))           # apply hirarchical clustering and plot

resim açıklamasını buraya girin

# a Bayesian clustering method, good for high-dimension data, more details:
# http://vahid.probstat.ca/paper/2012-bclust.pdf
install.packages("bclust")
library(bclust)
x <- as.matrix(d)
d.bclus <- bclust(x, transformed.par = c(0, -50, log(16), 0, 0, 0))
viplot(imp(d.bclus)$var); plot(d.bclus); ditplot(d.bclus)
dptplot(d.bclus, scale = 20, horizbar.plot = TRUE,varimp = imp(d.bclus)$var, horizbar.distance = 0, dendrogram.lwd = 2)
# I just include the dendrogram here

resim açıklamasını buraya girin

Ayrıca yüksek boyutlu veriler için, pvclustçok ölçekli önyükleme yeniden örnekleme yoluyla hiyerarşik kümeleme için p değerlerini hesaplayan kitaplık bulunur. İşte belgelerden örnek (benim örneğim gibi düşük boyutlu veriler üzerinde çalışmayacak):

library(pvclust)
library(MASS)
data(Boston)
boston.pv <- pvclust(Boston)
plot(boston.pv)

resim açıklamasını buraya girin

Bunlardan herhangi biri yardımcı olur mu?


Son dendogram için (AU / BP'li Küme Dendogramı) bazen nispeten yüksek p değerleri olan grupların etrafında dikdörtgenler çizmek uygundur: pvrect (uygun, alfa = 0.95)
Igor Elbert

Tam da aradığım şey buydu. R'de yeniyim ve bunu bulmam çok uzun sürecekti. Bu kadar ayrıntılı cevap verdiğiniz için @Ben teşekkürler. Lütfen bana bu yöntemlerin her birinin arkasındaki mantığı nerede bulabileceğim konusunda yol gösterebilir misiniz, örneğin, optimum küme sayısını belirlemek için hangi metrik veya ölçütleri kullanıyorlar veya her biri birbirinden nasıl farklı. Patronum bunu söylememi istiyor, böylece hangi yöntemlerden birini kullanacağımıza karar verebiliriz. Şimdiden teşekkürler.
nasia jaffri

1
@Aleksandr Blekh Herhangi bir grafik metodu analitik hale getirmeyi de deneyebilirsiniz. Örneğin, "dirsek" yöntemini kullanıyorum (ilk cevapta belirtildi), ancak analitik olarak bulmaya çalışıyorum. Dirsek noktası maksimum eğriliğe sahip nokta olabilir. Kesikli veriler için, maksimum ikinci derece merkezi fark (nokta ile sürekli veri için analog ila maksimum ikinci derece türevi) noktasıdır. Bkz. Stackoverflow.com/a/4473065/1075993 ve stackoverflow.com/q/2018178/1075993 . Diğer grafiksel yöntemlerin de analitik hale getirilebileceğini tahmin ediyorum.
Andrey Sapegin

1
@AndreySapegin: Yapabilirdim, ama: 1) açıkçası, bunu zarif bir çözüm olarak görmüyorum (IMHO, çoğu durumda görsel yöntemler görsel kalmalı, analitik olanlar analitik kalmalıdır); 2) Bir veya birkaç Rpaket kullanarak bunun analitik çözümünü anladım (GitHub'ımda - bir göz atabilirsiniz); 3) benim çözüm yeterince iyi görünüyor, artı, bir süre oldu ve ben zaten benim tez yazılımı, tez raporu (tez) kesinleşmiş ve şu anda savunma hazırlanıyor :-). Ne olursa olsun, yorumunuzu ve bağlantılarınızı çok takdir ediyorum. Herşey gönlünce olsun!
Aleksandr Blekh

1
Mevcut kümeleme veri kümemde 2,2 milyon satır var. Bu R paketlerinin hiçbiri üzerinde çalışmıyor, sanırım. Onlar sadece benim bilgisayar pop ve sonra benim deneyim düşüyor. Bununla birlikte, yazar, yazılım kapasitesi dikkate alınmadan küçük veriler ve genel durum için eşyalarını biliyor gibi görünüyor. Yazarın açık ve iyi çalışması nedeniyle hiçbir puan düşülmemiştir. Hepiniz sadece eski R'nin 2,2 milyon satırda korkunç olduğunu bilin - bana güvenmiyorsanız kendiniz deneyin. H2O, küçük duvarlı bir mutlu bahçeye yardımcı olur, ancak sınırlıdır.
Geoffrey Anderson

21

Bu kadar ayrıntılı bir cevap eklemek de zor. identifyBurada bahsetmemiz gerektiğini hissediyorum , özellikle @Ben birçok dendrogram örneği gösterdiğinden.

d_dist <- dist(as.matrix(d))   # find distance matrix 
plot(hclust(d_dist)) 
clusters <- identify(hclust(d_dist))

identifyetkileşimli olarak bir dendrogramdan kümeler seçmenize ve seçimlerinizi bir listeye kaydetmenize olanak tanır. Etkileşimli moddan çıkmak ve R konsoluna dönmek için Esc tuşuna basın. Listenin rownames'i değil, indeksleri içerdiğine dikkat edin (aksine cutree).


10

Kümeleme yöntemlerinde optimum k-kümesini belirlemek için. ElbowZaman tüketmekten kaçınmak için genellikle Paralel işleme eşlik eden yöntemi kullanıyorum . Bu kod şöyle örneklenebilir:

Dirsek yöntemi

elbow.k <- function(mydata){
dist.obj <- dist(mydata)
hclust.obj <- hclust(dist.obj)
css.obj <- css.hclust(dist.obj,hclust.obj)
elbow.obj <- elbow.batch(css.obj)
k <- elbow.obj$k
return(k)
}

Dirsek paralel çalışıyor

no_cores <- detectCores()
    cl<-makeCluster(no_cores)
    clusterEvalQ(cl, library(GMD))
    clusterExport(cl, list("data.clustering", "data.convert", "elbow.k", "clustering.kmeans"))
 start.time <- Sys.time()
 elbow.k.handle(data.clustering))
 k.clusters <- parSapply(cl, 1, function(x) elbow.k(data.clustering))
    end.time <- Sys.time()
    cat('Time to find k using Elbow method is',(end.time - start.time),'seconds with k value:', k.clusters)

İyi çalışıyor.


2
Dirsek ve css fonksiyonları GMD paketinden geliyor: cran.r-project.org/web/packages/GMD/GMD.pdf
Rohan

6

Ben'in muhteşem cevabı. Bununla birlikte, Afinite Yayılımı (AP) yönteminin sadece k-ortalamaları yöntemi için küme sayısını bulmak için önerildiğine şaşırdım, burada genel olarak AP verileri kümelemek için daha iyi bir iş yapar. Lütfen Bilim'deki bu yöntemi destekleyen bilimsel makaleye bakın:

Frey, Brendan J. ve Delbert Dueck. Msgstr "Veri noktaları arasında mesaj ileterek kümeleme." science 315.5814 (2007): 972-976.

K-araçlarına karşı önyargılı değilseniz, doğrudan AP'yi kullanmanızı öneririm, bu da kümelerin sayısını bilmeden verileri kümelendirir:

library(apcluster)
apclus = apcluster(negDistMat(r=2), data)
show(apclus)

Negatif öklid mesafeleri uygun değilse, aynı pakette sağlanan başka bir benzerlik önlemi kullanabilirsiniz. Örneğin, Spearman korelasyonlarına dayanan benzerlikler için ihtiyacınız olan şey budur:

sim = corSimMat(data, method="spearman")
apclus = apcluster(s=sim)

AP paketindeki benzerlikler için bu işlevlerin yalnızca basitlik için sağlandığını lütfen unutmayın. Aslında, R'deki apcluster () işlevi herhangi bir korelasyon matrisini kabul edecektir. Daha önce aynı corSimMat () ile yapılabilir:

sim = cor(data, method="spearman")

veya

sim = cor(t(data), method="spearman")

matrisinizde ne sıralamak istediğinize bağlı olarak (satırlar veya sütunlar).


6

Bu yöntemler harika ama çok daha büyük veri kümeleri için k bulmaya çalışırken, bunlar R'de çılgınca yavaş olabilir.

Bulduğum iyi bir çözüm, X-Means algoritmasının etkili bir uygulamasına sahip olan "RWeka" paketidir - K-Means'in daha iyi ölçeklenen ve sizin için optimum küme sayısını belirleyecek genişletilmiş bir sürümü.

Öncelikle Weka'nın sisteminize yüklendiğinden emin olmak ve XMeans'in Weka'nın paket yöneticisi aracıyla kurulmasını sağlamak isteyeceksiniz.

library(RWeka)

# Print a list of available options for the X-Means algorithm
WOW("XMeans")

# Create a Weka_control object which will specify our parameters
weka_ctrl <- Weka_control(
    I = 1000,                          # max no. of overall iterations
    M = 1000,                          # max no. of iterations in the kMeans loop
    L = 20,                            # min no. of clusters
    H = 150,                           # max no. of clusters
    D = "weka.core.EuclideanDistance", # distance metric Euclidean
    C = 0.4,                           # cutoff factor ???
    S = 12                             # random number seed (for reproducibility)
)

# Run the algorithm on your data, d
x_means <- XMeans(d, control = weka_ctrl)

# Assign cluster IDs to original data set
d$xmeans.cluster <- x_means$class_ids

6

Basit bir çözüm kütüphane factoextra. Kümeleme yöntemini ve en iyi grup sayısını hesaplama yöntemini değiştirebilirsiniz. Örneğin, bir k- için en iyi küme sayısını bilmek istiyorsanız:

Veri: mtcars

library(factoextra)   
fviz_nbclust(mtcars, kmeans, method = "wss") +
      geom_vline(xintercept = 3, linetype = 2)+
      labs(subtitle = "Elbow method")

Son olarak, şöyle bir grafik alırız:

resim açıklamasını buraya girin


2

Cevaplar harika. Başka bir kümeleme yöntemine şans vermek istiyorsanız, hiyerarşik kümelemeyi kullanabilir ve verilerin nasıl bölündüğünü görebilirsiniz.

> set.seed(2)
> x=matrix(rnorm(50*2), ncol=2)
> hc.complete = hclust(dist(x), method="complete")
> plot(hc.complete)

resim açıklamasını buraya girin

Kaç derse ihtiyacınız olduğuna bağlı olarak dendrogramınızı şu şekilde kesebilirsiniz;

> cutree(hc.complete,k = 2)
 [1] 1 1 1 2 1 1 1 1 1 1 1 1 1 2 1 2 1 1 1 1 1 2 1 1 1
[26] 2 1 1 1 1 1 1 1 1 1 1 2 2 1 1 1 2 1 1 1 1 1 1 1 2

Eğer yazarsanız ?cutreetanımları göreceksiniz. Veri kümenizde üç sınıf varsa, basitçe olacaktır cutree(hc.complete, k = 3). Eşdeğer için cutree(hc.complete,k = 2)olduğunu cutree(hc.complete,h = 4.9).


Wards'ı tam olarak tercih ederim.
Chris
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.