【问题标题】:Numeric matrix is taking far more memory than it should - R数值矩阵占用的内存比它应该的要多得多 - R
【发布时间】:2013-11-15 02:10:08
【问题描述】:

我正在为 Naive Bayes 实现创建一个文档术语矩阵(简称 dtm)(我知道有一个函数可以解决这个问题,但我必须自己编写代码以完成作业。)我编写了一个成功创建 dtm 的函数,问题是生成的矩阵占用了太多内存。例如,一个 100 x 32000 矩阵(由 0 和 1 组成)的大小为 24MB!当尝试使用完整的 10k 文档时,这会导致 r 中的崩溃行为。下面是函数,最后 3 行是一个玩具示例。谁能发现为什么“sparser”函​​数会返回如此大量的内存结果?

listAllWords <- function(docs)
{
  str1 <- strsplit(x=docs, split="\\s", fixed=FALSE)
  dictDupl <- unlist(str1)[!(unlist(str1) %in% stopWords)]
  dictionary <- unique(dictDupl)
}

#function to create the sparse matrix of words as they appear in each article segment
sparser <- function (docs, dictionary) 
{
  num.docs <- length(docs) #dtm rows
  num.words <- length(dictionary) #dtm columns
  dtm <- mat.or.vec(num.docs,num.words) # Instantiate dtm of zeroes
  for (i in 1:num.docs)
  {
    doc.temp <- unlist(strsplit(x=docs[i], split="\\s", fixed=FALSE)) #vectorize words
    num.words.doc <- length(doc.temp)
    for (j in 1:num.words.doc)
    {
      ind <- which(dictionary == doc.temp[j]) #loop over words and find index in dict.
      dtm[i,ind] <- 1 #indicate this word is in this document
    }
  }
  return(dtm)
}


docs <- c("the first document contains words", "the second document is also made of words", "the third document is words and a number 4")
dictionary <- listAllWords(docs)
dtm <- sparser(docs,dictionary)

如果有什么不同,我会在 Mac OSX 的 R Studio 中运行,64 位

【问题讨论】:

  • 小注:您的示例代码并非完全独立,我们没有stopWords。无论如何,您只需要一个矩阵本身的示例,就像我在下面所做的那样。

标签: r function matrix


【解决方案1】:

当然,您的问题的一部分是您实际上并没有存储整数,而是双精度数。注意:

m <- mat.or.vec(100,32000)
m1 <- matrix(0L,100,32000)

> object.size(m)
25600200 bytes
> object.size(m1)
12800200 bytes

并注意mat.or.vec 的代码中缺少“L”:

> mat.or.vec
function (nr, nc) 
if (nc == 1L) numeric(nr) else matrix(0, nr, nc)
<bytecode: 0x1089984d8>
<environment: namespace:base>

您还需要明确分配1L,否则我认为 R 将在第一次分配时将所有内容转换为双精度数。您可以通过简单地在值 1 之上分配一个 m1 值并重新检查对象大小来验证这一点。

我可能还应该提到函数storage.mode,它可以帮助您验证您使用的是整数。

【讨论】:

  • 感谢@joran 的提示!我尝试在函数中使用 matrix(0L,nr,nc) 而不是 mat.or.vec,但是生成的矩阵与以前的大小相同。使用storage.mode(dtm) &lt;- "integer" 将大小减半,但看起来仍然很大。或者......也许我只是不太了解应该占用多少存储矩阵......
  • @datapaRty 请记住,我说过更改mat.or.vec 是不够的。第一次分配1(或任何其他非整数)时,它会将所有内容转换为双精度。
  • 我确实将 mat.or.vec 更改为 matrix 并使用了 0L 分配。我使用matrix 中的1L 分配重新检查并再次转换为双打,正如你所建议的那样。由于我只能通过转换为整数来减少所需的存储空间,因此解决方案可能是编写一个更智能的算法,从而产生更小的矩阵(比如 32000 x 5(这是分类器的类数)。)
【解决方案2】:

如果你想经济地存储 0/1 值,我建议raw 类型。

m8 <- matrix(0,100,32000)
m4 <- matrix(0L,100,32000)
m1 <- matrix(raw(1),100,32000)

raw 类型每个值只占用 1 个字节:

> object.size(m8)
25600200 bytes
> object.size(m4)
12800200 bytes
> object.size(m1)
3200200 bytes

以下是如何使用它:

> m1[2,2] = as.raw(1)
> m1[2,2]
[1] 01
> as.integer(m1[2,2])
[1] 1

【讨论】:

    【解决方案3】:

    如果您真的想要经济实惠,请查看ffbit 软件包。

    【讨论】:

      猜你喜欢
      • 2015-04-19
      • 2015-05-31
      • 2015-05-16
      • 2020-01-28
      • 2023-04-09
      • 2023-03-06
      • 2013-01-13
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多