最快的R等价于MATLAB的reshape()方法?

are*_*gme 4 performance matlab r vectorization reshape

我正在将一个MATLAB脚本转换为R并对此感到后悔,因为它现在速度较慢.我试图尽可能地使用"矢量化函数",但我对R来说相对较新,并且不知道这是什么意思.如果使用大量运算符(包括括号),我对循环的研究只比R中的apply()方法慢.否则,我不知道R可以做些什么来进一步放慢速度.这是我希望加速的代码.

somPEs   <- 9;
inputPEs <- 6;
initial_w <- matrix(1, nrow=somPEs, ncol=inputPEs) 
w <- apply(initial_w, 1, function(i) runif(i));
# Reshape w to a 3D matrix of dimension: c(sqrt(somPEs), sqrt(somPEs), inputPEs)
nw <- array(0, dim=c(sqrt(somPEs), sqrt(somPEs), inputPEs))
for (i in 1:inputPEs) {
  nw[,,i] <- matrix(w[i,], nrow=sqrt(somPEs), ncol=sqrt(somPEs), byrow=TRUE)
}
w <- nw;
Run Code Online (Sandbox Code Playgroud)

在MATLAB中,此代码由称为"reshape"的内置函数执行,如下所示:

w = reshape(w,[sqrt(somPEs) sqrt(somPEs) inputPEs]);
Run Code Online (Sandbox Code Playgroud)

我计算了当前的R代码并且它实际上超级快,但我仍然想学习矢量化以及如何将我的代码转换为apply()以便于阅读.

user  system elapsed 
0.003   0.000   0.002 
Run Code Online (Sandbox Code Playgroud)

jos*_*ber 5

第一步是将数组w从大小转换6x93x3x6大小,在您的情况下,可以通过转置然后更改维度来完成:

neww <- t(w)
dim(neww) <- c(sqrt(somPEs), sqrt(somPEs), inputPEs)
Run Code Online (Sandbox Code Playgroud)

这几乎是我们想要的,除了前两个尺寸被翻转.您可以使用该aperm功能转置它们:

neww <- aperm(neww, c(2, 1, 3))
Run Code Online (Sandbox Code Playgroud)

这比循环遍历矩阵并逐行复制数据要快得多.为了看到这一点,让我们看一个包含10,000行和100列的更大示例(将映射到10x10x10k矩阵):

josilber <- function(w) {
  neww <- t(w)
  dim(neww) <- c(sqrt(dim(w)[2]), sqrt(dim(w)[2]), dim(w)[1])
  aperm(neww, c(2, 1, 3))
}
OP <- function(w) {
  nw <- array(0, dim=c(sqrt(dim(w)[2]), sqrt(dim(w)[2]), dim(w)[1]))
  for (i in 1:(dim(w)[1])) {
    nw[,,i] <- matrix(w[i,], nrow=sqrt(dim(w)[2]), ncol=sqrt(dim(w)[2]), byrow=TRUE)
  }
  nw
}
bigw <- matrix(runif(1000000), nrow=10000, ncol=100)
all.equal(josilber(bigw), OP(bigw))
# [1] TRUE
microbenchmark(josilber(bigw), OP(bigw))
# Unit: milliseconds
#            expr       min       lq      mean     median        uq       max neval
#  josilber(bigw)  8.483245  9.08430  14.46876   9.431534  11.76744  135.7204   100
#        OP(bigw) 83.379053 97.07395 133.86606 117.223236 129.28317 1553.4381   100
Run Code Online (Sandbox Code Playgroud)

使用t,dim和的方法aperm在中值运行时比循环方法快10倍.