Phân tích cụm trong R: xác định số lượng cụm tối ưu


428

Là một người mới chơi R, tôi không chắc chắn làm thế nào để chọn số cụm tốt nhất để phân tích k-mean. Sau khi vẽ một tập hợp con của dữ liệu dưới đây, có bao nhiêu cụm sẽ phù hợp? Làm thế nào tôi có thể thực hiện phân tích dendro cụm?

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
Nếu bạn chưa hoàn toàn kết hôn với kmeans, bạn có thể thử thuật toán phân cụm DBSCAN, có sẵn trong fpcgói. Đó là sự thật, sau đó bạn phải đặt hai tham số ... nhưng tôi đã thấy rằng fpc::dbscansau đó thực hiện công việc khá tốt khi tự động xác định một số cụm tốt. Ngoài ra, nó thực sự có thể xuất ra một cụm duy nhất nếu đó là những gì dữ liệu cho bạn biết - một số phương pháp trong câu trả lời xuất sắc của @ Ben sẽ không giúp bạn xác định liệu k = 1 có thực sự tốt nhất hay không.
Stephan Kolassa

Câu trả lời:


1020

Nếu câu hỏi của bạn là how can I determine how many clusters are appropriate for a kmeans analysis of my data?, thì đây là một số tùy chọn. Các bài viết wikipedia về việc xác định số lượng các cụm có một đánh giá tốt của một số các phương pháp này.

Đầu tiên, một số dữ liệu có thể tái tạo (dữ liệu trong Q là ... không rõ ràng đối với tôi):

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)

nhập mô tả hình ảnh ở đây

Một . Tìm kiếm một uốn cong hoặc khuỷu tay trong tổng số âm mưu scree lỗi bình phương (SSE). Xem http://www.statmethods.net/advstats/cluster.html & http://www.mattpeeples.net/kmeans.html để biết thêm. Vị trí của khuỷu tay trong ô kết quả cho thấy một số cụm phù hợp cho kmeans:

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

Chúng tôi có thể kết luận rằng 4 cụm sẽ được chỉ định bằng phương pháp này: nhập mô tả hình ảnh ở đây

Hai . Bạn có thể thực hiện phân vùng xung quanh medoid để ước tính số lượng cụm sử dụng pamkchức năng trong gói fpc.

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

nhập mô tả hình ảnh ở đây nhập mô tả hình ảnh ở đây

# 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

Ba . Tiêu chí Calinsky: Một cách tiếp cận khác để chẩn đoán có bao nhiêu cụm phù hợp với dữ liệu. Trong trường hợp này, chúng tôi cố gắng 1 đến 10 nhóm.

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!

nhập mô tả hình ảnh ở đây

Bốn . Xác định mô hình tối ưu và số lượng cụm theo Tiêu chí Thông tin Bayes cho tối đa hóa kỳ vọng, được khởi tạo bằng cách phân cụm theo phân cấp cho các mô hình hỗn hợp Gaussian được tham số hóa

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

nhập mô tả hình ảnh ở đây nhập mô tả hình ảnh ở đây nhập mô tả hình ảnh ở đây

Năm . Phân cụm ảnh hưởng (AP), xem 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)

nhập mô tả hình ảnh ở đây nhập mô tả hình ảnh ở đây

Sáu . Thống kê khoảng cách để ước tính số lượng cụm. Xem thêm một số mã cho một đầu ra đồ họa đẹp . Đang thử 2-10 cụm tại đây:

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

Đây là kết quả từ việc thực hiện thống kê khoảng cách của Edwin Chen: nhập mô tả hình ảnh ở đây

Bảy . Bạn cũng có thể thấy hữu ích khi khám phá dữ liệu của mình với clustergram để trực quan hóa việc gán cụm, xem http://www.r-statistic.com/2010/06/clustergram-visualization-and-diagnostics-for-cluster-analysis-r- mã / để biết thêm chi tiết.

Tám . Các gói NbClust cung cấp 30 chỉ số để xác định số lượng các cụm trong một tập dữ liệu.

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!

nhập mô tả hình ảnh ở đây

Nếu câu hỏi của bạn là how can I produce a dendrogram to visualize the results of my cluster analysis, thì bạn nên bắt đầu với những điều sau: 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/ Và xem tại đây để biết thêm các phương pháp kỳ lạ: http://cran.r-project.org/ web / lượt xem / Cluster.html

Đây là vài ví dụ:

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

nhập mô tả hình ảnh ở đây

# 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

nhập mô tả hình ảnh ở đây

Ngoài ra, đối với dữ liệu kích thước cao là pvclustthư viện tính toán các giá trị p để phân cụm theo phân cấp thông qua việc lấy mẫu bootstrap nhiều tầng. Đây là ví dụ từ tài liệu (sẽ không hoạt động trên dữ liệu chiều thấp như trong ví dụ của tôi):

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

nhập mô tả hình ảnh ở đây

Có ai giúp tôi không?


Đối với bản thảo cuối cùng (Bản ghi hình cụm với AU / BP) đôi khi thật tiện lợi khi vẽ hình chữ nhật xung quanh các nhóm có giá trị p tương đối cao: pvrect (phù hợp, alpha = 0,95)
Igor Elbert

Điều này thật đúng với gì mà tôi đã tìm kiếm. Tôi mới biết về R và tôi sẽ mất rất nhiều thời gian để tìm thấy thứ này. Cảm ơn @Ben đã trả lời chi tiết như vậy. Bạn có thể vui lòng hướng dẫn cho tôi xem tôi có thể tìm thấy logic đằng sau mỗi một trong số các phương thức này không, như số liệu hoặc tiêu chí mà chúng đang sử dụng để xác định số lượng cụm tối ưu hoặc mỗi một trong số chúng khác nhau như thế nào. Sếp của tôi muốn tôi nói điều đó, vì vậy chúng tôi có thể quyết định nên sử dụng một trong những phương pháp nào. Cảm ơn trước.
nasia jaffri

1
@Aleksandr Blekh Bạn cũng có thể thử chuyển bất kỳ phương pháp đồ họa nào sang phân tích. Ví dụ, tôi sử dụng phương pháp "khuỷu tay" (lần đầu tiên được đề cập trong câu trả lời), nhưng cố gắng tìm nó một cách phân tích. Điểm khuỷu tay có thể là điểm có độ cong tối đa. Đối với dữ liệu rời rạc, đó là điểm có chênh lệch trung tâm bậc hai tối đa (tương tự đạo hàm bậc hai tối đa đối với dữ liệu liên tục). Xem stackoverflow.com/a/4473065/1075993stackoverflow.com/q/2018178/1075993 . Tôi đoán rằng các phương pháp đồ họa khác cũng có thể được chuyển đổi sang phân tích.
Andrey Sapegin

1
@AndreySapegin: Tôi có thể, nhưng: 1) thành thật mà nói, tôi không coi đó là một giải pháp tao nhã (IMHO, trong hầu hết các trường hợp, phương pháp trực quan nên duy trì hình ảnh, trong khi phương pháp phân tích nên duy trì phân tích); 2) Tôi đã tìm ra giải pháp phân tích cho vấn đề này, bằng cách sử dụng một hoặc một số Rgói (nó có trên GitHub của tôi - bạn có thể xem qua); 3) giải pháp của tôi dường như hoạt động đủ tốt, cộng với, đã được một thời gian và tôi đã hoàn thiện phần mềm luận văn, báo cáo luận án (luận án) và hiện tôi đang chuẩn bị cho việc bảo vệ :-). Bất kể, tôi đánh giá cao nhận xét và liên kết của bạn. Tất cả là tốt nhất!
Alexanderr Blekh

1
2,2 triệu hàng nằm trong bộ dữ liệu phân cụm hiện tại của tôi. Không có gói R nào hoạt động trên đó, tôi mong đợi. Họ chỉ bật máy tính của tôi và sau đó nó rơi ra từ kinh nghiệm của tôi. Tuy nhiên, có vẻ như tác giả biết công cụ của mình cho dữ liệu nhỏ và cho trường hợp chung mà không liên quan đến dung lượng phần mềm. Không có điểm trừ do tác phẩm tốt rõ ràng của tác giả. Xin vui lòng chỉ biết R cũ đơn giản là khủng khiếp với 2,2 triệu hàng - hãy tự mình thử nếu bạn không tin tưởng tôi. H2O giúp nhưng được giới hạn trong một khu vườn nhỏ có tường hạnh phúc.
Geoffrey Anderson

21

Thật khó để thêm một cái gì đó quá một câu trả lời phức tạp. Mặc dù tôi cảm thấy chúng ta nên đề cập identifyở đây, đặc biệt vì @Ben hiển thị rất nhiều ví dụ về dendrogram.

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

identifycho phép bạn tương tác chọn các cụm từ một dendrogram và lưu trữ các lựa chọn của bạn vào một danh sách. Nhấn Esc để rời khỏi chế độ tương tác và trở về bảng điều khiển R. Lưu ý rằng danh sách này chứa các chỉ số, không phải là các tên gọi (trái ngược với cutree).


10

Để xác định cụm k tối ưu trong các phương pháp phân cụm. Tôi thường sử dụng Elbowphương pháp đi kèm với xử lý Song song để tránh hiện tượng mất thời gian. Mã này có thể lấy mẫu như thế này:

Phương pháp khuỷu tay

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

Chạy khuỷu tay song song

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)

Nó hoạt động tốt.


2
Các chức năng khuỷu tay và css đến từ gói GMD: cran.r-project.org/web/packages/GMD/GMD.pdf
Rohan

6

Câu trả lời tuyệt vời từ Ben. Tuy nhiên, tôi ngạc nhiên rằng phương pháp Tuyên truyền quan hệ (AP) đã được đề xuất ở đây chỉ đề xuất tìm số cụm cho phương thức k-mean, trong đó nói chung AP thực hiện công việc phân cụm dữ liệu tốt hơn. Xin vui lòng xem bài báo khoa học hỗ trợ phương pháp này trong Khoa học tại đây:

Frey, Brendan J. và Delbert Dueck. "Phân cụm bằng cách chuyển tin nhắn giữa các điểm dữ liệu." khoa học 315.5814 (2007): 972-976.

Vì vậy, nếu bạn không thiên về k-nghĩa là tôi đề nghị sử dụng AP trực tiếp, nó sẽ phân cụm dữ liệu mà không yêu cầu biết số lượng cụm:

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

Nếu khoảng cách euclide âm không phù hợp, thì bạn có thể sử dụng các biện pháp tương tự khác được cung cấp trong cùng một gói. Ví dụ: đối với các điểm tương đồng dựa trên tương quan Spearman, đây là những gì bạn cần:

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

Xin lưu ý rằng các chức năng cho sự tương đồng trong gói AP chỉ được cung cấp cho đơn giản. Trong thực tế, hàm apcluster () trong R sẽ chấp nhận bất kỳ ma trận tương quan nào. Điều tương tự trước đây với corSimMat () có thể được thực hiện với điều này:

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

hoặc là

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

tùy thuộc vào những gì bạn muốn phân cụm trên ma trận của bạn (hàng hoặc cols).


6

Các phương thức này rất tuyệt nhưng khi cố gắng tìm k cho các tập dữ liệu lớn hơn nhiều, chúng có thể bị chậm điên rồ trong R.

Một giải pháp tốt mà tôi đã tìm thấy là gói "Rweka", có triển khai hiệu quả thuật toán X-Means - phiên bản mở rộng của K-Means có tỷ lệ tốt hơn và sẽ xác định số lượng cụm tối ưu cho bạn.

Trước tiên, bạn sẽ muốn đảm bảo rằng Weka được cài đặt trên hệ thống của bạn và cài đặt XMeans thông qua công cụ quản lý gói của Weka.

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

Một giải pháp đơn giản là thư viện factoextra. Bạn có thể thay đổi phương pháp phân cụm và phương pháp để tính toán số lượng nhóm tốt nhất. Ví dụ: nếu bạn muốn biết số cụm tốt nhất cho k- có nghĩa là:

Dữ liệu: mtcars

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

Cuối cùng, chúng ta có được một biểu đồ như:

nhập mô tả hình ảnh ở đây


2

Các câu trả lời là tuyệt vời. Nếu bạn muốn tạo cơ hội cho một phương pháp phân cụm khác, bạn có thể sử dụng phân cụm theo phân cấp và xem cách phân chia dữ liệu.

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

nhập mô tả hình ảnh ở đây

Tùy thuộc vào số lượng lớp bạn cần, bạn có thể cắt chương trình dendro của bạn như;

> 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

Nếu bạn gõ ?cutreebạn sẽ thấy các định nghĩa. Nếu tập dữ liệu của bạn có ba lớp, nó sẽ đơn giản cutree(hc.complete, k = 3). Tương đương cho cutree(hc.complete,k = 2)cutree(hc.complete,h = 4.9).


Tôi thích phường hơn hoàn thành.
Chris
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.