You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

R中proxy::dist调用自定义DTW函数速度过慢,求优化方案

优化proxy::dist结合自定义DTW距离的计算速度

我完全懂你遇到的这个痛点——当数据规模上去之后,proxy::dist搭配自定义customDTW的速度暴跌,这确实是因为proxy::dist处理自定义方法时,默认是逐对调用你的函数,每一次调用都带额外的函数开销,而且没用到dtw包本身的批量优化能力。下面咱们一步步解决这个问题:

为什么当前实现速度拉胯?

你的customDTW每次只处理一对时间序列,而proxy::dist会对test和train的每一组序列组合都调用一次这个函数。当规模从60×70涨到60×700时,调用次数从4200次暴增到42000次,额外的函数调用开销被放大10倍,再加上dtw本身的计算成本,最终导致耗时呈指数级上升。而你不用proxy::dist的实现应该是用了更高效的批量处理逻辑,所以速度差这么多。

具体优化方案

1. 绕开proxy的逐对调用,直接用dtw批量计算

与其让proxy拆分数据对,不如自己批量处理所有组合,用R的向量化操作减少函数调用次数:

library(dtw)

fastDTWMatrix <- function(test, train, window.size = 20) {
  apply(test, 1, function(ts1) {
    sapply(seq_len(nrow(train)), function(i) {
      dtw(ts1, train[i, ], dist.method = "Euclidean", 
          window.type = "sakoechiba", window.size = window.size)$distance
    })
  }) %>% t()
}

# 调用示例
set.seed(1)
test <- matrix(runif(4200), 60, 70)
train <- matrix(runif(4200), 60, 70)
dMatrix <- fastDTWMatrix(test, train)

这个方法减少了函数调用的层级,sapply的循环效率比proxy的内部循环更高,60×700规模的速度应该能追上你不用proxy的实现。

2. 开启proxy的并行计算

proxy::dist支持并行计算,只需要注册并行后端后开启parallel参数即可:

library(proxy)
library(dtw)
library(doParallel)

# 注册并行集群(留一个核心给系统)
cl <- makeCluster(detectCores() - 1)
registerDoParallel(cl)

# 自定义函数保持简洁
customDTW <- function(ts1, ts2){
  dtw(ts1, ts2, dist.method = "Euclidean", 
      window.type = "sakoechiba", window.size = 20)$distance
}

# 调用时开启并行
dMatrix <- proxy::dist(x = test, y = train, method = customDTW, 
                       by_rows = T, auto_convert_data_frames = T,
                       parallel = TRUE)

# 用完记得关闭集群
stopCluster(cl)

并行计算能把任务分摊到多个CPU核心,大规模数据下耗时会明显降低。

3. 优化自定义函数的额外开销

你的原函数每次都要重复设置dtw参数,还返回整个dtw对象再提取距离,可以简化成直接返回距离,减少不必要的内存操作:

customDTW <- function(ts1, ts2){
  # 直接返回计算结果,避免存储整个dtw对象
  dtw(ts1, ts2, dist.method = "Euclidean", 
      window.type = "sakoechiba", window.size = 20)$distance
}

虽然单次优化幅度不大,但几万次调用下来积少成多。

4. 用专门的时间序列距离包

如果你的核心需求是计算时间序列距离矩阵,推荐用dtwclust包——它专门优化了DTW的批量计算,底层用C++实现,速度比自定义函数快很多,还和proxy兼容:

library(dtwclust)

# 直接用dtwclust的高效DTW实现
dMatrix <- proxy::dist(test, train, method = "dtw_basic", 
                       by_rows = TRUE, window.size = 20)

优化后的预期效果

用上述方案优化后,60×700规模的计算时间应该能大幅降低,接近甚至超过你不用proxy的实现速度,尤其是开启并行或用dtwclust的情况。

内容的提问来源于stack exchange,提问作者Azim

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.28 06:36:46