2

我正在尝试将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",甚至与我自己计算距离矩阵的情况相比,这非常慢,并且随着时间序列的长度或数量的增长,它会以指数方式变慢。当然,这植根于嵌套循环,但我对效果的规模感到惊讶。我没有看到它一定有另一个原因。

我的问题是,我还能如何实现 mycustomDTW以使其更快,使用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
4

3 回答 3

2

DTW本质上很慢您是否考虑过尝试使用dtwclust(dtw的并行实现)

https://github.com/asardaes/dtwclust

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

于 2018-05-18T18:04:34.420 回答
1

这是我发现的似乎可以提高速度的方法,但仍然没有我预期的那么快。(任何其他想法仍然非常受欢迎。)

诀窍是注册自定义距离函数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

于 2018-05-18T22:14:25.480 回答
1

R 是一种解释性语言,并且在底层是用 C 实现的。据我了解,代理包是在 C 中使用 R 的解释功能多次调用 R 代码,但这仍然无法避免解释的开销,因此几乎任何“纯” R 实现都会变慢。

使用代理注册函数时指定loop=TRUE意味着会发生上述情况(代理将多次解释R代码以填充距离矩阵)。如果你真的想加快速度,你需要在 C/C++ 中实现填充本身,并使用代理注册函数loop=FALSE;这就是 dtwclust 所做的(除其他外)。

如果您想测试自己的自定义 C/C++ 函数,即使您不想使用并行化,也可能需要查看parallelDist包。

于 2018-05-19T21:06:59.200 回答