มีฟังก์ชั่นใน R ที่นำศูนย์กลางของกลุ่มที่พบและกำหนดกลุ่มให้กับชุดข้อมูลใหม่


14

ฉันมีสองส่วนของชุดข้อมูลหลายมิติขอเรียกพวกเขาและtrain testและฉันต้องการสร้างแบบจำลองตามชุดข้อมูลรถไฟแล้วตรวจสอบความถูกต้องของชุดข้อมูลทดสอบ จำนวนของกลุ่มเป็นที่รู้จักกัน

ฉันพยายามใช้การจัดกลุ่ม k-mean ใน R และได้วัตถุที่มีศูนย์กลางของกลุ่ม:

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

มีฟังก์ชั่นใน R ที่นำศูนย์กลางของกลุ่มที่พบและกำหนดกลุ่มให้กับชุดข้อมูลการทดสอบของฉันหรือไม่?

ฉันสามารถลองวิธีการ / ขั้นตอนวิธีอื่นได้อย่างไร


ยินดีต้อนรับสู่เว็บไซต์ @ user2598356 คุณช่วยจัดวางสิ่งนี้ด้วยวิธีทั่วไป (แบบไม่เฉพาะเจาะจง R) ได้หรือไม่? หากคุณเพียงแค่ขอฟังก์ชั่น R คำถามนี้จะไม่เป็นหัวข้อสำหรับ CV (ดูหน้าความช่วยเหลือของเรา) ยิ่งไปกว่านั้นมันจะเป็นหัวข้อนอกStack Overflowเช่นกันเนื่องจากไม่มีตัวอย่างที่ทำซ้ำได้ หากคุณสามารถแก้ไขสิ่งนี้เพื่อให้เป็นหัวข้อที่นี่หรือบน SO โปรดทำเช่นนั้น มิเช่นนั้นคำถามนี้อาจถูกปิด
gung - Reinstate Monica

คำถามนี้ดูเหมือนจะไม่เป็นหัวข้อเพราะเป็นเรื่องเกี่ยวกับการหาฟังก์ชั่น R
gung - Reinstate Monica

1
แต่สิ่งที่เกี่ยวกับคำถามสุดท้าย: "อะไรคือวิธีการ / ขั้นตอนวิธีอื่น ๆ ที่ฉันสามารถลองได้" จริงๆแล้วคำตอบที่ฉันได้รับเกี่ยวข้องกับการใช้งานวิธีการที่เป็นหัวข้อของ CV หรือฉันผิด
user2598356

1
@gung คุณอาจถูกต้องซึ่งในกรณีนี้ฉันเชิญผู้ใช้ 259 ... เพื่อตั้งค่าสถานะคำถามนี้เพื่อการโยกย้าย อย่างไรก็ตามคำถามสุดท้ายเกี่ยวกับวิธีการและขั้นตอนวิธีอื่น ๆ แสดงให้เห็นว่าชุมชนของเราอาจอยู่ในตำแหน่งที่ดีที่จะให้ความช่วยเหลือและคำแนะนำที่เป็นประโยชน์
whuber

ขอบคุณ! ฟังก์ชั่นใช้งานได้ดี แต่ใช้เวลานานเกินไปถ้าคุณมีแถวมากกว่า 50k ความคิดใดที่ทำให้มันเบาลง?

คำตอบ:


11

คุณสามารถคำนวณการกำหนดคลัสเตอร์สำหรับชุดข้อมูลใหม่ด้วยฟังก์ชันต่อไปนี้:

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

การกำหนดคลัสเตอร์

หรือคุณสามารถใช้แพ็คเกจflexclustซึ่งมีpredictวิธีการใช้งานสำหรับวิธี k:

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

พล็อตแบบยืดหยุ่น

นอกจากนี้ยังมีวิธีการแปลงเพื่อแปลงผลลัพธ์จากฟังก์ชั่นคลัสเตอร์เช่นstats::kmeansหรือcluster::pamไปยังวัตถุของคลาสkccaและในทางกลับกัน:

as.kcca(cl, data=x)
# kcca object of family ‘kmeans’ 
#
# call:
# as.kcca(object = cl, data = x)
#
# cluster sizes:
#
#  1  2 
#  50 50 

ขอบคุณมาก! คำถามเพียงข้อเดียว: วิธี kcca เกี่ยวข้องกับจำนวนการเริ่มต้นอย่างไร (เป็นการวิเคราะห์ที่เหมาะสมที่สุดเมื่อเทียบกับจุดเริ่มต้น)
user2598356

คุณหมายถึงอะไรกับจำนวนการเริ่มต้น? stepFlexclustฟังก์ชั่นการจัดกลุ่มอัลกอริทึมทำงานซ้ำ ๆ สำหรับตัวเลขที่แตกต่างกันของกลุ่มและผลตอบแทนขั้นต่ำภายในแก้ปัญหาระยะคลัสเตอร์สำหรับแต่ละ
rcs

1

ขั้นที่ 1: ระยะการคำนวณฟังก์ชันระหว่างเวกเตอร์และแต่ละแถวของเมทริกซ์

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

ขั้นตอนที่ 2: ฟังก์ชั่นที่ใช้คอมพิวเตอร์ vec2mat กับทุกแถวของ 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)))
}

ขั้นตอนที่ 3 ใช้ฟังก์ชัน mat2mat

calc_mat2mat_dist(my_input_mat, kmeans_model$centers)

step4 เลือกใช้ plyr :: ddply และ doMC เพื่อขนาน mat2mat สำหรับชุดข้อมูลขนาดใหญ่

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

}
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.