【问题标题】:Writing large matrix using R ff使用 R ff 编写大矩阵
【发布时间】:2013-05-28 15:59:36
【问题描述】:

过去几天我一直在发布一个问题,我需要创建一个 7000x7000 距离矩阵。在内存上做这一切给了我无法分配向量错误。我使用的是 Windows XP SP 3、3GB RAM、32 位系统。我原本想使用 bigmemory 库,但它似乎不适用于 Windows。我在ff package 上做了一些阅读,所以这就是我目前的想法:

require(ff)    
ffmat <- ff(vmode="double", dim=c(7000,7000))
ffmat <- as.matrix(dist(data[1:7000, ], diag=TRUE, upper=TRUE))

问题是我仍然遇到向量分配错误。请注意dim(data) = 7000x182(很多变量)。

运行gc() 事后检查会使memory.size() 恢复到正常水平。就好像 R 在写入创建的 ff 之前将结果存储在内存中。有没有办法解决?

【问题讨论】:

  • 您可以查看mmap 而不是ff。我从来没有真正开始研究它,但它可能值得你研究。
  • 你期望什么,data[1:7000, ] 正在将你的 ff 矩阵放入 RAM 中,正如 ff 手册所示(参见 ?Extract.ff)。
  • @jwijffels 感谢您指出这一点。但是,从文档中并不完全清楚这将如何在矩阵上工作。假设我将数据矩阵 7000x180 写入 ff 对象 - ffmat。然后我使用ffmat2 &lt;- ff(vmode="double", dim=c(7000, 7000)) 创建第二个ff 对象。我如何在不使用 RAM 的情况下实际与我的 ffmat 对象保持距离?该文档显示了从一个 ff 对象到另一个的简单分配,但没有关于使用外部方法。
  • 你看过rmazing.wordpress.com/2013/02/22/…,看看人们是如何使用 ff 解决类似问题的吗?
  • @jwijffels 非常感谢!我能够从网站上获取示例并根据我的需要对其进行轮廓化。当我制定细节时,我会发布一个完整的实现。

标签: r matrix


【解决方案1】:

您可能需要将任务分解为多个部分并将各个部分分配给矩阵,而不是一步完成。

distas.matrix 函数不知道结果将是一个 ff 对象,它们只是尝试在内存中发挥作用。

由于 dist 函数不计算不同数据集之间的距离,因此手动计算距离可能是最简单的,尽管包中可能有一个函数可以计算非对角线距离。

【讨论】:

    【解决方案2】:

    “就好像 R 在写入创建的 ff 之前将结果存储在内存中。有什么办法解决这个问题吗?”

    这正是 R 正在做的事情。编写代码的方式有两件事:它创建一个ff 对象,然后用as.matrix 创建的传统矩阵覆盖它。

    您可以扩展dist 函数以使用ff 对象,或者编写您自己的使用ffdist 实现。

    【讨论】:

    • 我的替代方案是蛮力。类似:for (i in 1:7000) { for(j in 1:7000) { ffmat[i,j] &lt;- as.matrix(dist(data[c(i,j),]), diag=FALSE, upper=FALSE) gc() } } 但是,这似乎会持续一天。这甚至会起作用吗?如果是这样,是否需要重复调​​用gc()...可能只是在外循环中?
    • 你的问题仍然是 as.matrix 没有产生 ff 对象,所以你基本上仍然在 R 的约束范围内工作。如果你想暴力破解它,你会至少由更好的硬件提供更好的服务。
    • 在阅读ff 文档时,它提到了以下内容:“对于 'ff' 对象,已知以下类属性:距离矩阵 c("ff_dist","ff_symm","ff" )" 这对我来说意味着可以计算ff 内的距离矩阵,或许可以使用不同的函数。
    • 我现在明白了。但是,这看起来像是由创建的 ff 对象继承的类。例如,当我为原始数据的矩阵创建 ff 对象,然后用ffmat &lt;- as.ff(mydata) 填充它时,$class 属性中的类是"ff_matrix", "ff_array", "ff"。在我看来,这似乎暗示 ff 对象将从距离对象继承 "dist_matrix" 类。但是,由于硬件限制,我无法计算距离矩阵。此外,当我使用我的数据子集尝试 ffmat &lt;- as.ff(dist(mydata, diag=TRUE, upper=TRUE)) 时,它引发了错误。
    【解决方案3】:

    非常感谢 jwijffels 引导我朝着正确的方向前进,并感谢 http://rmazing.wordpress.com/2013/02/22/bigcor-large-correlation-matrices-in-r/ 让我朝着正确的方向开始。

    假设一个名为training.data 的7000x180 数据矩阵。目标是创建一个尺寸为 7000x7000 的对称距离矩阵。实际上,使用daisy() 会创建一个差异度量,但它是相似的逻辑。

    distff <- function(training.data, nblocks=5, verbose=TRUE) {
      require(ff)
      require(cluster)
      ffmat <- ff(vmode="single", dim=c(7000,7000), filename="if so desired")
      nro <- nrow(training.data)
      ### This could be changed to handle rowcounts that have 
      ### modulus(nro/nblocks) != 0
      splt <- split(1:nro, rep(1:nblocks, each = nro/nblocks))
      COMBS <- expand.grid(1:length(splt), 1:length(splt)) 
      COMBS <- t(apply(COMBS, 1, sort)) 
      COMBS <- unique(COMBS) 
      for (i in 1:nrow(COMBS)) {
        COMB <- COMBS[i,]
        ### Since g1 and g2 get appended below, it wouldn't make sense to append the
        ### same group to itself
        if (COMB[1] != COMB[2]) {
          g1 <- splt[[COMB[1]]]
          g2 <- splt[[COMB[2]]]
          slj <- as.matrix(daisy(training.data[c(g1,g2),], metric="gower", 
                                 stand=FALSE))
          ffmat[c(g1,g2), c(g1,g2)] <- slj
          rm(slj)
          gc()
        }
      }
    }
    

    就是这样。我意识到有一些效率低下(比如多次编写几个组)。我没关系,因为它有效。就像我说的,这段代码的大部分是从上面引用的网站借用和定制的。

    【讨论】:

    • 你的意思是return(ffmat)
    • @jbaums 感谢您稍微清理一下代码。 return(Ffmat) 为负数。虽然这是一个函数,但该函数不返回值。它只是将值slj 写入g1g2 指定位置的现有ffmat 对象。
    猜你喜欢
    • 2015-09-07
    • 2014-07-27
    • 1970-01-01
    • 2017-09-29
    • 2012-09-04
    • 2012-05-27
    • 1970-01-01
    • 1970-01-01
    • 2011-09-16
    相关资源
    最近更新 更多