"Vectorized"矩阵乘法
"Vectorized" matrix multiplication
假设我有两个矩阵 x 和 y,尺寸均为 100x2。我想创建一个列表,这样对于 x 和 y 的每一行,我都有矩阵 t(x) %*% y。例如,通过 for 循环:
x = matrix(rnorm(10), nrow = 5)
y = matrix(rnorm(10), nrow = 5)
myList = list()
for(i in 1:5){
myList[[i]] = t(x[i, , drop = FALSE]) %*% y[i, ]
}
是否有更有效的方法来进行此计算?我试图弄清楚如何表达这个矩阵乘法但没有运气。我也考虑过 mapply,但似乎我需要将 x 和 y 转换为向量列表而不是矩阵才能使用 mapply,而且我怀疑这是否是正确的方法。
Map
的一种方式
Map(function(x,y) matrix(x,ncol=1)%*%y ,
split(x, row(x)), split(y, row(y)))
似乎 Map 是最好的方法:
library(rbenchmark)
x = matrix(rnorm(10000), nrow = 5000)
y = matrix(rnorm(10000), nrow = 5000)
myList = list()
loopTest = function(){
for(i in 1:nrow(x)){
myList[[i]] = t(x[i, , drop = FALSE]) %*% y[i, ]
}
}
loopTest2 = function(){
for(i in 1:nrow(x)){
myList[[i]] = outer(x[i, ], y[i, ])
}
}
mapTest = function(){
Map(function(x,y) matrix(x,ncol=1)%*%y ,
split(x, row(x)), split(y, row(y)))
}
mapplyTest = function(){
mapply(function(x,y) matrix(x,ncol=1)%*%y,
x = split(x, row(x)), y = split(y, row(y)))
}
benchmark(loopTest(), mapTest(), mapplyTest(), replications = 100)
这给了我:
test elapsed
loopTest() 10.471
loopTest2() 12.225
mapplyTest() 3.100
mapTest() 2.252
但是,循环方法确实适用于较小的数据集,比如只有 5 行。
您可以使用
缩短(并可能稍微加快)您的代码
NewList <- list()
for (i in 1:nrow(x)) NewList[[i]] <- outer(x[i,],y[i,])
#> all.equal(NewList,myList)
#[1] TRUE
或者,等价地,
for (i in 1:nrow(x)) NewList[[i]] <- x[i,] %o% y[i,]
假设我有两个矩阵 x 和 y,尺寸均为 100x2。我想创建一个列表,这样对于 x 和 y 的每一行,我都有矩阵 t(x) %*% y。例如,通过 for 循环:
x = matrix(rnorm(10), nrow = 5)
y = matrix(rnorm(10), nrow = 5)
myList = list()
for(i in 1:5){
myList[[i]] = t(x[i, , drop = FALSE]) %*% y[i, ]
}
是否有更有效的方法来进行此计算?我试图弄清楚如何表达这个矩阵乘法但没有运气。我也考虑过 mapply,但似乎我需要将 x 和 y 转换为向量列表而不是矩阵才能使用 mapply,而且我怀疑这是否是正确的方法。
Map
Map(function(x,y) matrix(x,ncol=1)%*%y ,
split(x, row(x)), split(y, row(y)))
似乎 Map 是最好的方法:
library(rbenchmark)
x = matrix(rnorm(10000), nrow = 5000)
y = matrix(rnorm(10000), nrow = 5000)
myList = list()
loopTest = function(){
for(i in 1:nrow(x)){
myList[[i]] = t(x[i, , drop = FALSE]) %*% y[i, ]
}
}
loopTest2 = function(){
for(i in 1:nrow(x)){
myList[[i]] = outer(x[i, ], y[i, ])
}
}
mapTest = function(){
Map(function(x,y) matrix(x,ncol=1)%*%y ,
split(x, row(x)), split(y, row(y)))
}
mapplyTest = function(){
mapply(function(x,y) matrix(x,ncol=1)%*%y,
x = split(x, row(x)), y = split(y, row(y)))
}
benchmark(loopTest(), mapTest(), mapplyTest(), replications = 100)
这给了我:
test elapsed
loopTest() 10.471
loopTest2() 12.225
mapplyTest() 3.100
mapTest() 2.252
但是,循环方法确实适用于较小的数据集,比如只有 5 行。
您可以使用
缩短(并可能稍微加快)您的代码NewList <- list()
for (i in 1:nrow(x)) NewList[[i]] <- outer(x[i,],y[i,])
#> all.equal(NewList,myList)
#[1] TRUE
或者,等价地,
for (i in 1:nrow(x)) NewList[[i]] <- x[i,] %o% y[i,]