WAF*_*WAF 5 performance r distance image-processing
以下是文献如何解释如何计算两个时间序列的多维动态时间扭曲:
library(dtw)
x<- cbind(1:10,1)
y<- cbind(11:15,2)
cxdist <-dist(x,y,method="euclidean")
dtw(cxdist)$distance
Run Code Online (Sandbox Code Playgroud)
事实上,它首先计算交叉距离矩阵,然后将其用作 dtw 函数的输入。
我想在具有相当大图像的图像分类中使用多维动态时间扭曲。图像值存储在如下所示的数据框中:
inDf <- data.frame(matrix(rnorm(60), ncol = 6))
colnames(inDf) <- c('var1t1','var2t1','var1t2','var2t2','var1t3','var2t3')
Run Code Online (Sandbox Code Playgroud)
在这个例子中,有两个变量(var1 和 var2)被观察了 3 次。
问题是如何以尽可能高的计算强度获得 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;
')
Run Code Online (Sandbox Code Playgroud)
它使用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))
}
Run Code Online (Sandbox Code Playgroud)
现在我们可以转向文献例子。
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
Run Code Online (Sandbox Code Playgroud)
请注意,这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")]
Run Code Online (Sandbox Code Playgroud)
我不完全确定你的数据结构,但无论如何你总是可以根据你的需要准备变量。
比较和基准测试:
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
Run Code Online (Sandbox Code Playgroud)
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
Run Code Online (Sandbox Code Playgroud)
另外,如果你只对$distance你可以传递distance.only=T到dtw()- 它会带来一些加速。