2013-12-16 11 views
30

Bir veri çerçevesi üzerinde df1 k-aracı kümeleme çalıştırıyorum ve her gözlem için en yakın küme merkezini hesaplamak için basit bir yaklaşım arıyorum. yeni veri çerçevesi df2 (aynı değişken isimleriyle). Eğitim seti olarak df1 ve test setinde df2'yi düşünün; Eğitim setini kümelemek ve her test noktasını doğru kümeye atamak istiyorum.K-araçları kümelemeden sonra yeni veriler için kümeler atamak için basit bir yaklaşım

Ben apply fonksiyonu ve bir kaç basit kullanıcı tanımlı fonksiyonları ile bunun nasıl biliyor

(benzer konuda önceki mesajlar genellikle önerdi şey): Ancak

df1 <- data.frame(x=runif(100), y=runif(100)) 
df2 <- data.frame(x=runif(100), y=runif(100)) 
km <- kmeans(df1, centers=3) 
closest.cluster <- function(x) { 
    cluster.dist <- apply(km$centers, 1, function(y) sqrt(sum((x-y)^2))) 
    return(which.min(cluster.dist)[1]) 
} 
clusters2 <- apply(df2, 1, closest.cluster) 

, bu kümelenme hazırlık yapıyorum Öğrencilerin apply işlevini bilmedikleri bir ders için örnek, bu yüzden df2'ye yerleşik bir işlevle küme atayabilseydim çok tercih ederim. En yakın kümeyi bulmak için uygun yerleşik işlevler var mı?

+1

(http://manuals.bioinformatics.ucr.edu/home/R_BioCondManual# [burada R kodu ve açıklamaları ile farklı bir kümelenme yöntemleri denemek için bir kaynaktır] TOC-Kümeleme-Alıştırmalar) Ayrıca, belleğe dayanmayan ve bir K-anlamına gelen [biganalytics paketi] (http://cran.r-project.org/web/packages/biganalytics/biganalytics.pdf) bulunmaktadır. algoritma – marbel

+1

Öğrencileri 'apply() '(tekrar tekrar kullanacakları şekilde) ile tanıştırmak ve özel günler için hatırlamak zorunda kalacakları farklı paketlere tanıtmaktan ziyade nispeten basit bir yöntem kullanmaktan daha mantıklı görünmektedir. (eğer bir daha kullanırlarsa). – naught101

cevap

31

Sen k-ortalama bir hayata predict yöntemi vardır flexclust paketini kullanabilirsiniz:

library("flexclust") 
data("Nclus") 

set.seed(1) 
dat <- as.data.frame(Nclus) 
ind <- sample(nrow(dat), 50) 

dat[["train"]] <- TRUE 
dat[["train"]][ind] <- FALSE 

cl1 = kcca(dat[dat[["train"]]==TRUE, 1:2], k=4, kccaFamily("kmeans")) 
cl1  
# 
# call: 
# kcca(x = dat[dat[["train"]] == TRUE, 1:2], k = 4) 
# 
# cluster sizes: 
# 
# 1 2 3 4 
#130 181 98 91 

pred_train <- predict(cl1) 
pred_test <- predict(cl1, newdata=dat[dat[["train"]]==FALSE, 1:2]) 

image(cl1) 
points(dat[dat[["train"]]==TRUE, 1:2], col=pred_train, pch=19, cex=0.3) 
points(dat[dat[["train"]]==FALSE, 1:2], col=pred_test, pch=22, bg="orange") 

flexclust plot

Orada stats::kmeans veya cluster::pam gibi küme fonksiyonları sonuçlarını dönüştürmek için aynı zamanda dönüşüm yöntemleri sınıfının nesnelerine ve bunun tam tersi:

7

Hem sorudaki yaklaşım hem de esnek baskı yaklaşımları hakkında fark ettiğim bir şey, bunların oldukça yavaş olmalarıdır (her biri 2 özellikli 1 milyon gözlemle bir eğitim ve test için kıyaslanmıştır).

makul hızlı orijinal modeli olduğunu takılması:

set.seed(144) 
df1 <- data.frame(x=runif(1e6), y=runif(1e6)) 
df2 <- data.frame(x=runif(1e6), y=runif(1e6)) 
system.time(km <- kmeans(df1, centers=3)) 
# user system elapsed 
# 1.204 0.077 1.295 

Söz gönderilmiş çözüm ayrı her test kümesi noktası için closest.cluster çağırır beri test-set küme atamaları hesaplamayla yavaş:

system.time(pred.test <- apply(df2, 1, closest.cluster)) 
# user system elapsed 
# 42.064 0.251 42.586 

arada, flexclust paket pr olsa (kcca ile yeni bir tane kendimizi ne olursa olsun biz as.kcca ile donatılmış modeli dönüştürmek olmadığının yükü bir sürü eklemek veya uygun görünüyor Hızlı k-en yakın bir kd ağacı gibi komşular çözümü içinde her test-set gözlem yakın komşuluk bulmak için kullandığı: sonunda ediction

# APPROACH #1: Convert from the kmeans() output 
system.time(km.flexclust <- as.kcca(km, data=df1)) 
# user system elapsed 
# 87.562 1.216 89.495 
system.time(pred.flexclust <- predict(km.flexclust, newdata=df2)) 
# user system elapsed 
# 0.182 0.065 0.250 

# Approach #2: Fit the k-means clustering model in the flexclust package 
system.time(km.flexclust2 <- kcca(df1, k=3, kccaFamily("kmeans"))) 
# user system elapsed 
# 125.193 7.182 133.519 
system.time(pred.flexclust2 <- predict(km.flexclust2, newdata=df2)) 
# user system elapsed 
# 0.198 0.084 0.302 

Burada başka mantıklı yaklaşım olduğu görülmektedir) çok daha hızlıdır küme merkezlerinin kümesi. Bu kompakt yazılı ve nispeten hızlı bir edilebilir:

library(FNN) 
system.time(pred.knn <- get.knnx(km$center, df2, 1)$nn.index[,1]) 
# user system elapsed 
# 0.315 0.013 0.345 
all(pred.test == pred.knn) 
# [1] TRUE 
+1

Bu cevap inanılmaz derecede değerli. Bir k-aracı modelinde tahmin() 'in kullanılmasıyla ilgili genel gider sadece deliydi. Benim için bir rasterin küçük bir bölümünü işlemek 1,5 saat sürdü. Küme merkezlerinizin yaklaşımını kullanarak, işlemi 15 saniyeden daha kısa sürede çalıştırabildim. Çok teşekkür ederim. – SeldomSeenSlim