【问题标题】:How to do R multiplication with Nx1 1xM for Matrix NxM?对于矩阵 NxM,如何用 Nx1 1xM 进行 R 乘法?
【发布时间】:2017-03-12 10:45:07
【问题描述】:

我想做一个简单的列 (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 反向移植
硬件:华硕 Zenbook UX303UA

【问题讨论】:

  • 您在寻找row1 %*% col1吗? row1 是一个向量,而不是矩阵。

标签: r matrix statistics matrix-multiplication


【解决方案1】:

在这种情况下使用outer 会是更自然的选择

outer(1:6, 1:6)

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

outer(x, y)

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

tcrossprod(x, y)

如果您的xy 中的任何一个是具有维度的矩阵,请先使用as.numeric 将其转换为向量。

不建议为此使用通用矩阵乘法运算"%*%"。但是,如果您愿意,请确保您获得合适的维度:x 是单列矩阵,y 是单行矩阵,所以 x %*% y


你能谈谈效率吗?

已知矩阵 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

【讨论】:

  • 好的,知道了。是的,我运行测试以确认它。很高兴有不同的方法来查看如何完成并单独评估每一项。
【解决方案2】:

这里是当使用的向量长度为​​ 100 时三种方法的执行速度比较。最快的是 tcrossprodx%*%t(y) 需要多 17%,outer(x,y) 需要多 45%(中位数时间)。 在表中,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

要得到下图,有

library("ggplot2")
bench <- microbenchmark(tcrossprod(x,y), x%*%t(y), outer(x,y), times=5000)
autplot(bench)

编辑:性能取决于xy 的大小,当然还有运行代码的机器。我最初使用长度为 100 的向量进行基准测试,因为这就是 Masi 所要求的。但是,对于较大的向量,这三种方法的性能似乎非常相似。对于长度为 1000 的向量,在我的机器上,这三种方法的中值时间相差在 5% 以内。

> x <- runif(1000)
> y <- runif(1000)
> microbenchmark(tcrossprod(x,y),x%*%t(y),outer(x,y),times=2000)
Unit: milliseconds
             expr      min       lq     mean   median       uq       max neval
 tcrossprod(x, y) 1.870282 2.030541 4.721175 2.916133 4.482346  75.77459  2000
       x %*% t(y) 1.861947 2.067908 4.921061 3.067670 4.527197 105.60500  2000
      outer(x, y) 1.886348 2.078958 5.114886 3.033927 4.556067  93.93450  2000

【讨论】:

  • 我真的很喜欢你的新成员!对于更大的数据案例非常有用。你能说一下你是如何得到图表的吗? - - 表格末尾的neval 是什么?
  • 如果你已经安装了 microbenchmark 包并做
  • 糟糕,最后一条评论搞砸了。如果您安装了 microbenchmark 包并执行bench &lt;- microbenchmark(tcrossprod(x,y), x%*%t(y), outer(x,y), times=5000),那么如果您有 ggplot2 包,您可以执行autoplot(bench) 来获取图表。在表中,neval 是函数被评估以获得基准分数的次数。
  • 我已将您的评论更新为您的答案。你怎么解释这个数字?以图形方式获得所有这些基本统计值真是太好了。
  • autoplot生成的图是violin plot。更多信息可以找到here。您还可以执行 'boxplot(bench, outline=F)' 来绘制表格中给出的汇总统计数据。
【解决方案3】:

查看此问题的一种简单方法是将向量转换为矩阵

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

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

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

如果您希望产品为此工作,您需要一个6*1 矩阵,乘以一个1*6 矩阵。所以你需要使用t(col1.mat)转置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

【讨论】:

  • 我真的很喜欢这个提议。我真的很喜欢看到包含大量数据条目的基准摘要。这种数据结构帮助我从数学角度思考问题。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2023-04-06
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多