簡體   English   中英

高效的多維動態時間扭曲實現

[英]Efficient multidimensional dynamic time warping implementation

以下是文獻如何解釋如何計算兩個時間序列的多維動態時間扭曲:

 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返回class 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.distdist大約快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() - 它可以提高速度。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM