以下是文献解释如何计算两个时间序列的多维动态时间扭曲的方法:

 library(dtw)
 x<- cbind(1:10,1)
 y<- cbind(11:15,2)
 cxdist <-dist(x,y,method="euclidean")
 dtw(cxdist)$distance

实际上,它首先计算交叉距离矩阵,然后将其用作dtw函数中的输入。

我想在具有很大图像的图像分类中使用多维动态时间扭曲。
图像值存储在看起来像这样的数据框中:
 inDf <- data.frame(matrix(rnorm(60), ncol = 6))
 colnames(inDf) <- c('var1t1','var2t1','var1t2','var2t2','var1t3','var2t3')

在此示例中,两次观察到两个变量(var1和var2)。

问题是关于计算强度,如何获得尽可能高的效率的dtw距离矩阵?

这里有一些想法:
-遍历输入图像矩阵的每个值,将向量整形为矩阵,以便能够计算交叉距离,然后计算dtw距离并将其存储在专用矩阵中。
当然,这是计算量最大的解决方案

最佳答案

处理密集型计算时,始终考虑使用Rcpp包是很有意义的。如果要更快地获得具有欧几里得距离的距离矩阵,则可以实现相应的Rcpp函数:

library(Rcpp)
library(inline)

# Rcpp function for euclidean distance
fastdist <- cxxfunction(signature(x="matrix", y="matrix"), plugin="Rcpp",
body='
  Rcpp::NumericMatrix dx(x);
  Rcpp::NumericMatrix dy(y);

  const int N = dx.nrow();
  const int M = dy.nrow();

  Rcpp::NumericMatrix res(N, M);

  for(int i=0; i<N; i++){
    for(int j=0; j<M; j++){
      res(i,j) = sqrt(sum((dx(i,_)-dy(j,_))*(dx(i,_)-dy(j,_))));
    }
  }

  return res;
')

它使用Rcpp语法sugar来使代码更紧凑和易读。但是,有时最好具有用于检查类型,强制等的包装函数。这不是必需的-您可以直接调用fastdist。但是,无论如何,包装器可能看起来像这样:
# Wrapper R function
fast.dist <- function(x, y){
  stopifnot(class(x) %in% c("data.frame","matrix") &
            class(y) %in% c("data.frame","matrix") &
            ncol(x)==ncol(y))

  fastdist(as.matrix(x), as.matrix(y))
}

现在我们来看文学实例。
library(dtw)

# EXAMPLE 1
x<- cbind(1:10,1)
y<- cbind(11:15,2)
# Check results
all.equal(fast.dist(x,y), dist(x,y,method="euclidean"), check.attributes=F)
# [1] "target is matrix, current is crossdist"
all.equal(fast.dist(x,y), matrix(dist(x,y,method="euclidean"), ncol=nrow(y)))
# [1] TRUE

注意,dist返回类crossdist的结果。因此,为了进行比较,应将其强制为matrix

现在是您的主要问题-我们首先生成数据:
# EXAMPLE 2
set.seed(1234)
N <- 100
inDf <- data.frame(matrix(rnorm(6*N), ncol = 6))
colnames(inDf) <- c('var1t1','var2t1','var1t2','var2t2','var1t3','var2t3')

# Extracting variables
var1 <- inDf[,c("var1t1","var1t2","var1t3")]
var2 <- inDf[,c("var2t1","var2t2","var2t3")]

我不确定您的数据结构,但是无论如何,您始终可以根据需要准备变量。

比较和基准测试:
library(rbenchmark)

all.equal(fast.dist(var1,var2), matrix(dist(var1,var2), ncol=N))
# [1] TRUE
benchmark(fast.dist(var1,var2), dist(var1,var2), order="relative")[,1:4]
#                    test replications elapsed relative
# 1 fast.dist(var1, var2)          100   0.081    1.000
# 2      dist(var1, var2)          100   0.246    3.037

在这种情况下,fast.dist大约比dist快3倍。但是,随着N的增长,相对速度会下降。

还要注意,正如评论中提到的那样,dtw可以自己计算距离矩阵。但是,预先计算距离矩阵会更有效。请参阅下面的快速测试:
cxdist <- fast.dist(var1,var2)
benchmark(dtw(cxdist)$distance, dtw(var1,var2)$distance, order="relative")[,1:4]
#                       test replications elapsed relative
# 1     dtw(cxdist)$distance          100   0.476    1.000
# 2 dtw(var1, var2)$distance          100   0.736    1.546

另外,如果您只对$distance感兴趣,则可以将distance.only=T传递给dtw()-这样可以加快速度。

09-27 10:52