Проблема производительности с базовым R - PullRequest
0 голосов
/ 28 ноября 2018

Я реализую алгоритм kmeans в R, однако у меня ужасные проблемы с производительностью.Я пришел из Python, Java и C ++, поэтому я не очень-то привык к кодированию на языке R, и поэтому я хотел знать, могу ли я получить совет по базовым операциям для выполнения.

Во-первых, моя функция - получитьрасстояние между двумя точками:

distance <- function(pt1, pt2){
  pt1 <- pt1[0:NUMBER_OF_FEATURES]
  pt2 <- pt2[0:NUMBER_OF_FEATURES]

  pt2 <- t(pt2)
  sum <- 0
  counter <- 1
  for (i in 1:nrow(pt2)){
    sum <- sum + ((pt1[counter] - pt2[counter])^2)
    counter <- counter + 1
  }
  value <- sqrt(sum)
  return(value)
} 

Не похоже, что я могу намного лучше понять то, что понимаю, но я знаю, что на самом деле не следует использовать циклы for в R.

Также у меня есть другая функция, которая фокусируется на обновлении центроидов каждого кластера, и я закодировал это так:

update_centroids <- function(ptlst, centroids){
  centroids <- matrix(, nrow = NUMBER_OF_CLUSTERS, ncol = NUMBER_OF_FEATURES)

  for (i in 1:NUMBER_OF_CLUSTERS){
    temp <- ptlst[which(ptlst$cluster == i),]
    temp <- temp[0:NUMBER_OF_FEATURES]
    print(ncol(temp))
    centroid <- c()
    for (j in 1:ncol(temp)){
      centroid <- c(centroid, mean(as.numeric(unlist(temp[j]))))
    }
    print(centroid)
    centroids[i,] <- centroid
  }
  print(centroids)
}

Опять же, насколько я понимаю, я не должен кодировать эту часть, как это, ноиспользуйте общую запись, которая сделает это намного быстрее.

В целом мой полный алгоритм выполняется на наборе данных iris за 2,24 секунды, в то время как моя собственная реализация на python выполняется за 0,03 секунды

Так что я ясноделать что-то не так здесь, и есть что-то, и это занимает огромное количество времени, но я не могу достать это

Заранее спасибо за ваши ответы, Shraneid

РЕДАКТИРОВАТЬ: файл сгенерированный dput

1 Ответ

0 голосов
/ 28 ноября 2018
distance <- function(pt1, pt2){
  pt1 <- pt1[1:NUMBER_OF_FEATURES]
  pt2 <- pt2[1:NUMBER_OF_FEATURES]
  x <- sum((pt1 - pt2)^2)
  value <- sqrt(x)
  return(value)
} 

Для второй функции вы растете объект внутри цикла, который медленен в R.

Я думаю, ваши данные выглядят так:

NUMBER_OF_CLUSTERS <- 2
NUMBER_OF_FEATURES <- 4 
n <- 100
set.seed(13)
ptlst <- data.frame(cluster = sample.int(NUMBER_OF_CLUSTERS, n, replace = T),
                    replicate(NUMBER_OF_FEATURES, rnorm(n)))
head(ptlst)
#   cluster         X1          X2         X3          X4
# 1       2  0.2731292 -2.84476384  0.6137843  2.10781521
# 2       1  0.7555251  1.71457759  0.4126145  1.57738122
# 3       1 -0.3490184 -1.22881682 -0.4588937  0.06149504
# 4       1 -0.5461908 -0.31407296 -0.6731785 -0.23792899
# 5       2  0.2343620 -0.06991232  0.1930543 -0.17730688
# 6       1 -0.2978282 -0.83760143  1.3829291 -1.17393025

Итак, мы можемпопробуйте:

update_centroids <- function(ptlst){
  t(sapply(1:NUMBER_OF_CLUSTERS, function(i) {
    temp <- ptlst[which(ptlst$cluster == i),]
    colMeans(temp)
  }))
}
update_centroids(ptlst)
#      cluster          X1         X2          X3         X4
# [1,]       1  0.07365732 -0.0725119 -0.08745870 0.03406371
# [2,]       2 -0.24100628 -0.1044056  0.09288702 0.40949754

или с помощью data.table

require(data.table)
x <- as.data.table(ptlst)
x[, lapply(.SD, mean), keyby = cluster]
#    cluster          X1         X2          X3         X4
# 1:       1  0.07365732 -0.0725119 -0.08745870 0.03406371
# 2:       2 -0.24100628 -0.1044056  0.09288702 0.40949754

Я предлагаю вам начать с чтения некоторых руководств по R:

https://r4ds.had.co.nz/introduction.html https://cran.r -project.org / web / packages / data.table / vignettes / datatable-intro.html

и т. Д.

В Интернете много полезных материалов.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...