R에 발견 된 군집의 중심을 취하여 군집을 새로운 데이터 세트에 할당하는 기능이 있습니까?


14

내가 다차원 데이터 세트의 두 부분으로,의 그들을 부르 자 traintest. 열차 데이터 세트를 기반으로 모델을 빌드 한 다음 테스트 데이터 세트에서 모델을 검증하려고합니다. 클러스터 수는 알려져 있습니다.

R에서 k- 평균 군집화를 적용하려고 시도했으며 군집 중심을 포함하는 객체를 얻었습니다.

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

R에 발견 된 군집의 중심을 취하여 군집을 테스트 데이터 세트에 할당하는 기능이 있습니까?

시도 할 수있는 다른 방법 / 알고리즘은 무엇입니까?


@ user2598356 사이트에 오신 것을 환영합니다. 보다 일반적인 (R이 아닌) 방식으로 프레임을 구성 할 수 있습니까? R 기능 만 요청하는 경우이 질문은 CV에 대한 주제가 아닙니다 ( 도움말 페이지 참조 ). 또한 재현 가능한 예제 가 없기 때문에 Stack Overflow 에서도 주제가 맞지 않습니다 . 여기 또는 SO 주제로 편집 할 수 있다면 그렇게하십시오. 그렇지 않으면이 Q가 닫힐 수 있습니다.
gung-Monica Monica 복원

이 질문은 R 함수를 찾는 것과 관련이 있기 때문에 주제가 아닌 것 같습니다.
gung-Monica Monica 복원

1
그러나 마지막 질문은 "내가 시도 할 수있는 다른 방법 / 알고리즘은 무엇입니까?"입니다. 실제로 내가 얻은 대답은 CV의 주제 인 메소드의 구현과 관련이 있습니까? 아니면 틀렸습니까?
user2598356

1
@ gung 당신이 옳을 수도 있는데,이 경우 user259 ...를 초대하여이 질문에 대한 마이그레이션을 초대했습니다. 그러나 다른 방법과 알고리즘에 대한 질문의 마지막 부분은 우리 커뮤니티가 유용한 도움과 조언을 제공 할 수있는 좋은 위치에있을 수 있음을 시사합니다.
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")

클러스터 할당

또는 k-means에 대해 구현 된 메소드 가있는 flexclust 패키지를 사용할 수 있습니다 predict.

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 플롯

클러스터 함수의 결과를 클래스의 객체 와 같이 stats::kmeans또는 그 반대로 변환하는 변환 방법 도 있습니다.cluster::pamkcca

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 December

1

step1 : 벡터와 행렬의 각 행 사이의 거리를 계산하는 함수

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

step3. 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.