我有Z
,这是一个n=1000 x m=500,000 x p=3
数组,Y
,是一个p=3 x n=1000
矩阵。
对于i
中的每个1:n
,我想矩阵乘法:
Z[i, ,] %*% Y[, i]
我觉得应该有一个更快的方法来做到这一点,可能涉及到张量,或者仅仅是更好的矢量化。
我对矩阵Y
有一种特殊形式,如下文mwe中所述。我对利用这种结构的解决方案以及没有利用这种结构的更通用的解决方案感兴趣。
内存也是一个问题,因为您似乎至少需要将Z
对象的大小增加一倍。我设定m = 10,000使生活更轻松,但实际上m = 500,000。
n=1000; m=10000; p=3
Z = array( rnorm(n*m*p) , dim = c(n, m, p))
Y = matrix(NA, nrow=p, ncol = n)
index = rbinom(n,1,0.5)==1
Y[,index] = c(0,1,2)
Y[,!index] = c(2,1,0)
pryr::object_size(Z)
pryr::object_size(Y)
# methods that do not rely on the structure of Y
method1 = do.call(cbind,matrix(mapply(plyr::alply(.data = Z, .margins = 1), plyr::alply(Y, .margins = 2), FUN = function(x,y) x %*% y , SIMPLIFY = FALSE )))
method2 = do.call(cbind,matrix(map2(.x = plyr::alply(.data = Z, .margins = 1), .y = plyr::alply(Y, .margins = 2 ), ~ .x %*% .y ) ))
method3 = do.call(cbind,lapply(seq_len(dim(Z)[1]),function(i) Z[i,,]%*%Y[,i]))
identical(method1, method2)
identical(method2, method3)
# method that does rely on the structure of Y
fn4 = function(Z, index){
m = dim(Z)[2]; n = dim(Z)[1]
res = matrix(NA, m, n)
method4.1 = apply( Z[index,,], 1, function(x) x %*% c(0,1,2) )
method4.2 = apply( Z[!index,,], 1, function(x) x %*% c(2,1,0) )
res[,index] = method4.1
res[,!index] = method4.2
res
}
method4 = fn4(Z, index)
identical(method4, method3)
bench::mark(
method1 = do.call(cbind,matrix(mapply(plyr::alply(.data = Z, .margins = 1), plyr::alply(Y, .margins = 2), FUN = function(x,y) x %*% y , SIMPLIFY = FALSE ))),
method2 = do.call(cbind,matrix(map2(.x = plyr::alply(.data = Z, .margins = 1), .y = plyr::alply(Y, .margins = 2 ), ~ .x %*% .y ) )),
method3 = do.call(cbind,lapply(seq_len(dim(Z)[1]),function(i) Z[i,,]%*%Y[,i])),
method4 = fn4(Z, index),
iterations = 4
)