Почему использование собственной функции приближения в proxy :: dist делает ее такой медленной в R? - PullRequest
0 голосов
/ 18 мая 2018

Я пытаюсь использовать функцию proxy::dist с пользовательской матрицей расстояний, но то, что у меня сейчас, очень медленно.

Это воспроизводимый пример того, как я вызываю свою пользовательскую функцию:

set.seed(1)
test <- matrix(runif(4200), 60, 70)
train <- matrix(runif(4200), 60, 70)
dMatrix <- proxy::dist(x = test, y = train, method = customDTW,
                     by_rows = T, 
                     auto_convert_data_frames = T)

, который должен вычислять расстояние между каждым временным рядом в матрице test со всеми временными рядами в матрице train (каждая строка является временным рядом).

Моя пользовательская функция:

customDTW <- function(ts1, ts2){

  d <- dtw(ts1, ts2,
      dist.method = "Euclidean",
      window.type = "sakoechiba",
      window.size = 20
  )
  return(d$distance)
}

Проблема в том, что по сравнению с тем, когда я использую method="DTW", или даже со случаем, когда я сам вычисляю матрицу расстояний, это чрезвычайно медленно, и как длина временного рядаили их число растет, экспоненциально становится медленнее.Конечно, это коренится во вложенном цикле, но меня удивляет масштаб эффекта.Должна быть еще одна причина, по которой я этого не вижу.

Мой вопрос о том, как еще я мог бы реализовать свой customDTW, чтобы сделать его быстрее, используя proxy::dist?


Это мой маленький эксперимент по времени выполнения:

Время выполнения для 60X7 (с использованием proxy::dist + customDTW)

user  system elapsed 
2.852   0.012   2.867

Время выполнения для60X70 (с использованием proxy::dist + customDTW)

user  system elapsed 
5.384   0.000   5.382 

Время выполнения для 60X700 (с использованием proxy::dist + customDTW)

user  system elapsed 
509.088  18.652 529.115

Время выполнения для60X700 ( без с использованием proxy::dist)

user  system elapsed 
26.696   0.004  26.753

Ответы [ 3 ]

0 голосов
/ 19 мая 2018

Это то, что, как я обнаружил, улучшает скорость, но все же не так быстро, как я ожидаю.(Любая другая идея по-прежнему очень приветствуется.)

Хитрость заключается в том, чтобы зарегистрировать пользовательскую функцию расстояния с помощью proxy (т. Е. Реестр близости здесь ), поэтомучто вы можете использовать его как встроенную меру расстояния.Итак, сначала:

proxy::pr_DB$set_entry(FUN = customDTW, names=c("customDTW"),
                         loop = TRUE, type = "metric", distance = TRUE)

и теперь вы можете использовать его, как если бы он уже был в пакете proxy.

dMatrix <- proxy::dist(x = test, y = train, method = "customDTW",
                         by_rows = T,
                         auto_convert_data_frames = T)

Примечание: Если выЕсли вы хотите использовать этот метод, то метод customDTW должен иметь дело с одной парой временных рядов, а не со всеми.Таким образом, customDTW будет выглядеть так:

customDTW2 <- function(ts1, ts2){

  d <- dtw(ts1, ts2,
      dist.method = "Euclidean",
      window.type = "sakoechiba",
      window.size = 20
  )
  return(d$distance)
}

Подробнее см. ?pr_DB.

0 голосов
/ 20 мая 2018

R является интерпретируемым языком, и под капотом он реализован на C. Прокси-пакет, насколько я понимаю, использует возможности интерпретации R изнутри C для вызова кода R несколько раз, но это все еще не можетизбегайте затрат на интерпретацию, поэтому почти любая «чистая» реализация R будет медленнее.

Указание loop=TRUE при регистрации функции с прокси означает, что вышеупомянутое произойдет (прокси будет интерпретировать код R несколько раз для заполненияматрица расстояний).Если вы действительно хотите ускорить процесс, вам нужно реализовать саму заливку в C / C ++ и зарегистрировать функцию с прокси с помощью loop=FALSE;это то, что делает dtwclust (среди прочего).

Возможно, вы захотите взглянуть на пакет parallelDist , если хотите протестировать свои собственные пользовательские функции C / C ++, даже если вы неЯ не хочу использовать распараллеливание.

0 голосов
/ 18 мая 2018

DTW медленный по своей природе. Рассматривали ли вы попытку использования dtwclust (параллельная реализация dtw)

https://github.com/asardaes/dtwclust

https://cran.r -project.org / web / packages/dtwclust/vignettes/dtwclust.pdf

...