Как уменьшить использование памяти в рамках k-средних Прадо, используемых для больших данных в R? - PullRequest
0 голосов
/ 25 марта 2019

Я пытаюсь проверить платформу k-средних Прадо для кластеризации торговых стратегий, основанную на матрице корреляции доходности, найденной в его статье , с использованием R для большого числа стратегий, скажем, 1000.

Он пытается найти оптимальное k и оптимальную инициализацию для k-средних, используя два for цикла по всем возможным k и ряду инициализаций, то есть k переходит от 2 к N-1 , где N - количество стратегий.

Проблема в том, что запуск k-означает, что много раз, особенно с таким количеством кластеров, не хватает памяти, и мой компьютер не использует ни один экземпляр AWS m3.medium, который я могу использовать. (4 ГБ ОЗУ и то и другое, хотя в AWS меньше фоновых процессов, потребляющих ОЗУ).

Итак, довольно пожалуйста, есть идеи, как справиться с этой проблемой памяти? Или, по крайней мере, как оценить объем памяти, необходимый в зависимости от количества используемых стратегий?

Я попробовал пакет biganalytics и его функцию bigkmeans, но этого оказалось недостаточно. Я также знаю, что экземпляры RAM AWS выше, но я хотел бы убедиться, что мой код является оптимальным перед переключением на такой экземпляр. Я также пытался ограничить количество используемых кластеров, что подтвердило, что это основная проблема, занимающая память, но я бы не хотел придерживаться такого решения (ни в сочетании с лучшим экземпляром AWS).

Наибольшее количество стратегий, правильно выполненных в AWS, составило около 500.

Основная часть кода для оптимизации памяти выглядит следующим образом:

D <- nrow(dist)
seq.inits <- rep(1:nr.inits,D-2)
seq.centers <- rep(2:(D-1),each = nr.inits)
KM <- mapply(function(x,y){
  set.seed(x+333)
  kmeans(dist, y)
},seq.inits,seq.centers)

dist - это матрица корреляции-расстояния стратегий "возврата" (т. Е. Число столбцов равно числу строк среди других свойств), а nr.inits - это число инициализаций. Оба являются входными переменными. После этого лучшая кластеризация определяется с использованием оценки силуэта и, возможно, может быть повторной кластеризацией.

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

Мои вопросы, как указано выше:

  1. возможно ли уменьшить использование памяти, чтобы я мог запустить 1000 стратегий на экземпляре m3.medium AWS?

  2. возможно ли, по крайней мере, оценить использование памяти на основе используемых числовых стратегий? (Если я попробую 2:(N-1) кластеров.)

На самом деле, второй вопрос, желательно после оптимизации, для меня важнее. Поскольку я хотел бы попробовать даже гораздо большее количество стратегий, чем «просто» 1000.

Спасибо за ваши ответы заранее!

1 Ответ

0 голосов
/ 27 марта 2019

Несохранение всех результатов одновременно относится ко многим проблемам, даже если вы не используете R. Кроме того, я думаю, что вы не используете kmeans правильно, так как он ожидает ваши входные данные, а не перекрестныематрица расстояний.Точно так же вам не нужно выделять все seq.centers.Вы упоминаете индекс силуэта, который можно вычислить с помощью cluster::silhouette, поэтому:

library(cluster)
data(ruspini) # sample data included in the cluster package

Поскольку ваши данные не меняются, вы можете предварительно вычислить матрицу перекрестных расстояний:

dm <- dist(ruspini)

Одна "итерация" вашего желаемого рабочего процесса будет выглядеть следующим образом:

km <- kmeans(ruspini, 2) # try 2 clusters
score <- mean(cluster::silhouette(km$cluster, dist = dm)[,3L])

Вы хотели бы несколько случайных запусков для одних и тех же кластеров k:

num_starts <- 2L
scores <- sapply(seq_len(num_starts), function(ignored) {
  km <- kmeans(ruspini, 2)
  mean(cluster::silhouette(km$cluster, dist = dm)[,3L])
})

Обратите внимание, что сохраняется только оценка без результатов кластеризации.Вы также хотели бы, чтобы различные значения k:

max_k <- 3L
num_starts <- 2L
scores <- sapply(2L:max_k, function(k) {
  repetitions <- sapply(seq_len(num_starts), function(ignored) {
    km <- kmeans(ruspini, k)
    mean(cluster::silhouette(km$cluster, dist = dm)[,3L])
  })

  max(repetitions)
})

Для каждого значения k мы возвращали только максимальную оценку за все повторения (опять же, экономя место, не сохраняя все).

Чтобы сделать все воспроизводимым, вы используете set.seed вверху;Одного его использования достаточно для последовательных вычислений.Может быть, вы хотели бы использовать распараллеливание, но тогда вам может понадобиться больше оперативной памяти (довольно сложно сказать, сколько, потому что в игре много факторов), и вам нужно быть осторожным с воспроизводимостью.Если вы хотите попробовать, финальный скрипт может выглядеть так:

library(doParallel)
library(cluster)

data(ruspini)
dm <- dist(ruspini)

max_k <- 3L
num_starts <- 2L

# get random seeds for each execution
RNGkind("L'Ecuyer")
set.seed(333L)
current_seed <- .Random.seed # initialize
seeds <- lapply(2L:max_k, function(ignored) {
  lapply(seq_len(num_starts), function(also_ignored) {
    seed <- current_seed
    current_seed <<- parallel::nextRNGStream(current_seed)
    # return
    seed
  })
})

workers <- makeCluster(detectCores())
registerDoParallel(workers)

scores <- foreach(k = 2L:max_k, k_seeds = seeds, .combine = c, .packages = "cluster") %dopar% {
  repetitions <- sapply(seq_len(num_starts), function(i) {
    set.seed(k_seeds[[i]])
    km <- kmeans(ruspini, k)
    mean(cluster::silhouette(km$cluster, dist = dm)[,3L])
  })

  max(repetitions)
}

stopCluster(workers); registerDoSEQ(); rm(workers)

names(scores) <- paste0("k_", 2L:max_k)
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...