对于Matrix NxM,如何用Nx1 1xM进行R乘法?

时间:2016-10-29 21:15:37

标签: r matrix statistics matrix-multiplication

我想做一个简单的列(Nx1)次行(1xM)乘法,得到(NxM)矩阵。 我按顺序创建行的代码,通过转置类似的序列来创建列

row1 <- seq(1:6) 
col1 <- t(seq(1:6))      
col1 * row1

表示R认为矩阵更像列

的输出
     [,1] [,2] [,3] [,4] [,5] [,6]
[1,]    1    4    9   16   25   36

预期输出:NxM矩阵。

操作系统:Debian 8.5
Linux内核:4.6 backports
硬件:华硕Zenbook UX303UA

3 个答案:

答案 0 :(得分:1)

在这种情况下,使用outer将是一个更自然的选择

outer(1:6, 1:6)

一般情况下,对于两个数值向量 xy,矩阵rank-1运算可以计算为

outer(x, y)

如果您想使用实际矩阵乘法例程,请使用tcrossprod

tcrossprod(x, y)

如果您的xy中的任何一个是带尺寸的矩阵,请先使用as.numeric将其转换为矢量。

建议不要使用通用矩阵乘法运算"%*%"。但是,如果您愿意,请确保您获得可投影的维度:x是一列矩阵,y是一行矩阵,因此x %*% y

  

你能谈谈效率吗?

已知Matrix rank-1操作受内存限制。因此,请确保我们使用gc()进行垃圾收集,告诉R在每次复制后从堆中释放内存(否则系统会停止):

x <- runif(500)
y <- runif(500)
xx <- matrix(x, ncol = 1)
yy <- matrix(y, nrow = 1)

system.time(replicate(200, {outer(x,y); gc();}))
#   user  system elapsed 
#  4.484   0.324   4.837 

system.time(replicate(200, {tcrossprod(x,y); gc();}))
#   user  system elapsed 
#  4.320   0.324   4.653 

system.time(replicate(200, {xx %*% yy; gc();}))
#   user  system elapsed 
#  4.372   0.324   4.708 

在表现方面,它们都非常相似。

<强>后续

当我回来时,我看到了另一个不同基准的答案。嗯,问题是,取决于问题的大小。如果您只是尝试一个小例子,则无法消除所有三个函数的函数解释/调用开销。如果你这样做

x <- y <- runif(500)
microbenchmark(tcrossprod(x,y), x %*% t(y), outer(x,y), times = 200)

你会再次看到大致相同的表现。

#Unit: milliseconds
#             expr     min      lq     mean  median      uq      max neval cld
# tcrossprod(x, y) 2.09644 2.42466 3.402483 2.60424 3.94238 35.52176   200   a
#       x %*% t(y) 2.22520 2.55678 3.707261 2.66722 4.05046 37.11660   200   a
#      outer(x, y) 2.08496 2.55424 3.695660 2.69512 4.08938 35.41044   200   a

答案 1 :(得分:1)

这里&#39;当使用的向量长度为​​100时,三种方法的执行速度进行比较。最快的是tcrossprodx%*%t(y)的长度增加17%{{1}延长45%(中位时间)。 在表中,outer(x,y)是评估函数以获得基准分数的次数。

neval

要获得以下图表,请

> x <- runif(100,0,100)
> y <- runif(100,0,100)
> microbenchmark(tcrossprod(x,y), x%*%t(y), outer(x,y), times=5000)
Unit: microseconds
             expr    min      lq     mean  median      uq       max neval
 tcrossprod(x, y) 11.404 16.6140 50.42392 17.7300 18.7555  5590.103  5000
       x %*% t(y) 13.878 19.4315 48.80170 20.5405 21.7310  4459.517  5000
      outer(x, y) 19.238 24.0810 72.05250 25.3595 26.8920 89861.855  5000

enter image description here

编辑:性能取决于library("ggplot2") bench <- microbenchmark(tcrossprod(x,y), x%*%t(y), outer(x,y), times=5000) autplot(bench) x的大小,当然还有运行代码的计算机。我最初使用长度为100的向量进行基准测试,因为这是Masi所询问的。然而,看起来这三种方法对于较大的载体具有非常相似的性能。对于长度为1000的向量,三种方法的中位数时间在我的机器上相差5%。

y

答案 2 :(得分:1)

一种简单的方法是将矢量转换为矩阵

row1.mat = matrix(row1)
col1.mat = matrix(col1)

然后使用dim查看矩阵的维度:

dim(row1.mat)
dim(col1.mat)

如果您希望产品适用于此,则需要6*1矩阵,再乘以1*6矩阵。因此,您需要使用col1.mat转换t(col1.mat)

您可能知道矩阵产品是%*%

row1.mat %*% t(col1.mat)

此方法与其他方法的比较

library("microbenchmark")
x <- runif(1000)
y <- runif(1000)
xx = matrix(x)
yy = matrix(y)
microbenchmark(tcrossprod(x,y),x%*%t(y),outer(x,y), xx %*% t(yy), times=2000)

Unit: milliseconds
             expr      min       lq     mean   median       uq      max neval
 tcrossprod(x, y) 2.829099 3.243785 6.015880 4.801640 5.040636 77.87932  2000
       x %*% t(y) 2.847175 3.251414 5.942841 4.810261 5.049474 86.53374  2000
      outer(x, y) 2.886059 3.277811 5.983455 4.788054 5.074997 96.12442  2000
     xx %*% t(yy) 2.868185 3.255833 6.126183 4.699884 5.056234 87.80024  2000