Apakah ada fungsi dalam R yang mengambil pusat-pusat cluster yang ditemukan dan menetapkan cluster ke set data baru

14

Saya memiliki dua bagian dari kumpulan data multidimensi, sebut saja traindan test. Dan saya ingin membangun model berdasarkan pada set data kereta dan kemudian memvalidasinya pada set data uji. Jumlah cluster diketahui.

Saya mencoba menerapkan k-means clustering di R dan saya mendapatkan objek yang berisi pusat-pusat cluster:

kClust <- kmeans(train, centers=N, nstart=M)

Apakah ada fungsi dalam R yang mengambil pusat-pusat cluster yang ditemukan dan menetapkan cluster untuk set data pengujian saya?

Apa metode / algoritma lain yang dapat saya coba?

pengguna2598356
sumber
Selamat datang di situs ini, @ user2598356. Bisakah Anda membingkai ini dengan cara yang lebih umum (non-R spesifik)? Jika Anda hanya meminta fungsi R, pertanyaan ini akan di luar topik untuk CV (lihat halaman bantuan kami ). Selain itu, itu akan menjadi off-topik di Stack Overflow juga, karena tidak memiliki contoh yang dapat direproduksi . Jika Anda dapat mengedit ini untuk menjadikannya sesuai topik di sini atau di SO, silakan lakukan. Jika tidak, Q ini dapat ditutup.
gung - Reinstate Monica
Pertanyaan ini tampaknya di luar topik karena ini tentang menemukan fungsi R.
gung - Reinstate Monica
1
Tetapi bagaimana dengan pertanyaan terakhir: "Apa metode / algoritma lain yang bisa saya coba?". Sebenarnya jawaban yang saya dapatkan menyangkut implementasi metode yang merupakan topik CV, atau apakah saya salah?
user2598356
1
@ung Anda mungkin benar, dalam hal ini saya mengundang pengguna259 ... untuk menandai pertanyaan ini untuk migrasi. Namun, bagian terakhir dari pertanyaan tentang metode dan algoritma lain menunjukkan bahwa komunitas kami mungkin berada dalam posisi yang baik untuk menawarkan bantuan dan saran yang bermanfaat.
Whuber
Terima kasih! Fungsi ini berfungsi dengan baik, tetapi butuh terlalu banyak waktu jika Anda memiliki lebih dari 50 ribu baris. Adakah ide untuk membuatnya lebih ringan?

Jawaban:

11

Anda bisa menghitung penugasan cluster untuk set data baru dengan fungsi berikut:

clusters <- function(x, centers) {
  # compute squared euclidean distance from each sample to each cluster center
  tmp <- sapply(seq_len(nrow(x)),
                function(i) apply(centers, 1,
                                  function(v) sum((x[i, ]-v)^2)))
  max.col(-t(tmp))  # find index of min distance
}

# create a simple data set with two clusters
set.seed(1)
x <- rbind(matrix(rnorm(100, sd = 0.3), ncol = 2),
           matrix(rnorm(100, mean = 1, sd = 0.3), ncol = 2))
colnames(x) <- c("x", "y")
x_new <- rbind(matrix(rnorm(10, sd = 0.3), ncol = 2),
               matrix(rnorm(10, mean = 1, sd = 0.3), ncol = 2))
colnames(x_new) <- c("x", "y")

cl <- kmeans(x, centers=2)

all.equal(cl[["cluster"]], clusters(x, cl[["centers"]]))
# [1] TRUE
clusters(x_new, cl[["centers"]])
# [1] 2 2 2 2 2 1 1 1 1 1

plot(x, col=cl$cluster, pch=3)
points(x_new, col= clusters(x_new, cl[["centers"]]), pch=19)
points(cl[["centers"]], pch=4, cex=2, col="blue")

tugas cluster

atau Anda bisa menggunakan paket flexclust , yang memiliki predictmetode yang diimplementasikan untuk k-means:

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

plot flexclust

Ada juga metode konversi untuk mengkonversi hasil dari fungsi cluster seperti stats::kmeansatau cluster::pamke objek kelas kccadan sebaliknya:

as.kcca(cl, data=x)
# kcca object of family ‘kmeans’ 
#
# call:
# as.kcca(object = cl, data = x)
#
# cluster sizes:
#
#  1  2 
#  50 50 
rcs
sumber
Terima kasih banyak! Hanya satu pertanyaan: bagaimana metode kcca menangani jumlah awal (apakah ini mengoptimalkan analisis sehubungan dengan poin awal)?
user2598356
Apa yang Anda maksud dengan jumlah awal? The stepFlexclustFungsi berjalan mengelompokkan algoritma berulang kali untuk nomor yang berbeda dari cluster dan mengembalikan minimum dalam cluster solusi jarak untuk setiap.
rcs
1

step1: fungsi penghitungan jarak antara vektor dan setiap baris matriks

calc_vec2mat_dist = function(x, ref_mat) {
    # compute row-wise vec2vec distance 
    apply(ref_mat, 1, function(r) sum((r - x)^2))
}

langkah 2: fungsi yang menerapkan komputer vec2mat ke setiap baris input_matrix

calc_mat2mat_dist = function(input_mat, ref_mat) {

    dist_mat = apply(input_mat, 1, function(r) calc_vec2mat_dist(r, ref_mat))

    # transpose to have each row for each input datapoint
    # each column for each centroids
    cbind(t(dist_mat), max.col(-t(dist_mat)))
}

langkah3. terapkan fungsi mat2mat

calc_mat2mat_dist(my_input_mat, kmeans_model$centers)

step4. Opsional gunakan plyr :: ddply dan doMC untuk memparalelkan mat2mat untuk dataset besar

library(doMC)
library(plyr)

pred_cluster_para = function(input_df, center_mat, cl_feat, id_cols, use_ncore = 8) {
    # assign cluster lables for each individual (row) in the input_df 
    # input: input_df   - dataframe with all features used in clustering, plus some id/indicator columns
    # input: center_mat - matrix of centroid, K rows by M features
    # input: cl_feat    - list of features (col names)
    # input: id_cols    - list of index cols (e.g. id) to include in output 
    # output: output_df - dataframe with same number of rows as input, 
    #         K columns of distances to each clusters
    #         1 column of cluster_labels
    #         x column of indices in idx_cols

    n_cluster = nrow(center_mat)
    n_feat = ncol(center_mat)
    n_input = nrow(input_df)

    if(!(typeof(center_mat) %in% c('double','interger') & is.matrix(center_mat))){
        stop('The argument "center_mat" must be numeric matrix')
    } else if(length(cl_feat) != n_feat) {
        stop(sprintf('cl_feat size: %d , center_mat n_col: %d, they have to match!',length(cl_feat), n_feat))
    } else {
        # register MultiCore backend through doMC and foreach package
        doMC::registerDoMC(cores = use_ncore)

        # create job_key for mapping/spliting the input data
        input_df[,'job_idx'] = sample(1:use_ncore, n_input, replace = TRUE)

        # create row_key for tracing the original row order which will be shuffled by mapreduce
        input_df[,'row_idx'] = seq(n_input)

        # use ddply (df input, df output) to split-process-combine
        output_df = ddply(
            input_df[, c('job_idx','row_idx',cl_feat,id_cols)], # input big data 
            'job_idx',                       # map/split by job_idx
            function(chunk) {                # work on each chunk
                dist = data.frame(calc_mat2mat_dist(chunk[,cl_feat], center_mat))
                names(dist) = c(paste0('dist2c_', seq(n_cluster)), 'pred_cluster')
                dist[,id_cols] = chunk[,id_cols]
                dist[,'row_idx'] = chunk[,'row_idx']
                dist                        # product of mapper
                        }, .parallel = TRUE) # end of ddply
        # sort back to original row order

        output_df = output_df[order(output_df$row_idx),]
        output_df[c('job_idx')] = NULL
        return(output_df)
    }

}
XX
sumber