【问题标题】:Fast matrix computation in RR中的快速矩阵计算
【发布时间】:2015-07-29 21:28:42
【问题描述】:

我需要计算:

我可以进一步分解成:

在 R 中我写了这段代码

att_num <- dim(X)[2]
A <- matrix(0, att_num, att_num)
for(i in seq(att_num)) A[,i] <- colSums(dx * X * X[,i])

但是由于循环,它非常慢。这一行占用了我脚本中的大部分计算时间。有什么方法可以改进这种计算?

  • dx 是大小为 [1 x m] 的向量
  • X 是一个大小为 [n x m] 的矩阵

例子:

dx <- sample(1:100, 30, replace=T)
X <- data.frame(replicate(30,sample(0:1,100,rep=TRUE)))

att_num <- dim(X)[2]
A <- matrix(0, att_num, att_num)
for(i in seq(att_num)) A[,i] <- colSums(dx * X * X[,i])

【问题讨论】:

  • 请提供一个可重现的例子
  • crossprod(dx*X, X)
  • 请注意dx 的长度与X 中的观察数量不匹配。它被回收,这可能是也可能不是你需要的。另外,我不确定你的代码是否正确地实现了方程。
  • 抱歉造成混淆,dx 的长度确实总是符合X 中的观察次数。

标签: r matrix


【解决方案1】:
set.seed(42)
dx <- sample(1:100, 30, replace=T)
X <- data.frame(replicate(10,sample(0:1,100,rep=TRUE)))

att_num <- dim(X)[2]
A <- matrix(0, att_num, att_num)
for(i in seq(att_num)) A[,i] <- colSums(dx * X * X[,i])

B <- crossprod(as.matrix(dx * X), as.matrix(X))

all.equal(A, unname(B))
#[1] TRUE

【讨论】:

    【解决方案2】:

    假设 x_i 是 X 的列,那么您可以使用矩阵乘法运算符%*% 以矢量化方式进行:

    library(Matrix)
    set.seed(1234)
    nrows <- 100
    ncols <- 30 # same as length(dx)
    dx <- sample(1:100, ncols, replace=T)
    X <- matrix(sample(0:1, nrows*ncols, replace = TRUE), nrow = nrows, ncol = ncols)
    A <- X %*% Diagonal(length(dx), dx) %*% t(X)
    

    如果 X 有很多零,我强烈建议您将其设置为稀疏格式(查看 Matrix 包中的 sparseMatrix)。请注意,中间的对角矩阵实际上是稀疏的。这节省了大量的内存和计算。

    注意 1: 在下面的 cmets 中,Roland 指出 dx 不只要 X 有行。我建议您准确检查您想要做什么,因为通常情况下应该是这样!另外,通常 x_i 是 X 的列。如果您发布更多信息(例如总和中索引的限制),我可以为您提供更多帮助。

    注意 2:另外,请尝试使用矩阵而不是数据框。数据框要慢很多,因为它们必须单独管理列。

    【讨论】:

    • 请注意,nrow(X) != length(dx) 在他们的示例中。
    • 已修复,谢谢。通常我会认为,在这样的计算中,X 的列数与 d 的长度一样多,因为看起来你正在计算 X 的加权(使用 D = diag(d))协方差矩阵,对吗?跨度>
    • 是的,我也觉得这种差异令人困惑。
    • 问题是,如果实际存在长度差异,正确的代码会有所不同,具体取决于 dx 是否比nrow(X) 短/长,或者您是否想按照您在问题中评论的那样回收它等。
    猜你喜欢
    • 2018-09-03
    • 1970-01-01
    • 1970-01-01
    • 2015-03-18
    • 2011-11-15
    • 2020-03-21
    • 2021-10-26
    • 2019-11-18
    • 2015-09-17
    相关资源
    最近更新 更多