0

我有一个包含 600 万条消息的 6GB 数据集,我想处理这些消息 - 我的目标是为我的数据集创建一个文档术语矩阵,但我需要进行一些预处理(去除 HTML 标记、词干提取、停用词删除、等)首先。

以下是我目前尝试做这一切的方式:

library(data.table)
library(tm)

wordStem2 <- function(strings){
  sapply(lapply(strsplit(stripWhitespace(strings), " "), wordStem), function(x) paste(x, collapse=" "))
}

load("data/train.RData")
sampletrainDT <- as.data.table(train)
rm(train)
setkey(sampletrainDT, Id)

object.size(sampletrainDT) # 5,632,195,744 bytes

gc()
sampletrainDT[, Body := tolower(Body)]
object.size(sampletrainDT) # 5,631,997,712 bytes, but rsession usage is at 12 GB. gc doesn't help.
gc()
sampletrainDT[, Body := gsub("<(.|\n)*?>", " ", Body)] # remove HTML tags
sampletrainDT[, Body := gsub("\n", " ", Body)] # remove \n
sampletrainDT[, Body := removePunctuation(Body)]
sampletrainDT[, Body := removeNumbers(Body)]
sampletrainDT[, Body := removeWords(Body, stopwords("english"))]
sampletrainDT[, Body := stripWhitespace(Body)]
sampletrainDT[, Body := wordStem2(Body)]

ls 在每一行:

ls()
[1] "sampletrainDT" "wordStem2"  

的每一行sampletrainDT是一条消息,主列是Body。其他包含元数据,如 docid 等。

当我只使用数据的一个子集(10%)时,它运行得非常快(10 分钟),但如果我使用完整的数据集,它甚至不会完成,因为我在这条线上用完了 RAM sampletrainDT[, Body := gsub("<(.|\n)*?>", " ", Body)] # remove HTML tags。在两行之间运行 gc() 似乎并没有改善这种情况。

我花了几天时间在谷歌上搜索一个解决方案,但我还没有找到一个好的解决方案,所以我很想听听其他在这方面有很多经验的人的意见。以下是我正在考虑的一些选项:

  1. ff 或 bigmemory - 难以使用且不适合文本
  2. 数据库
  3. 一次读取块,处理并附加到文件(更适合 Python?)
  4. 来自 tm 库的 PCorpus
  5. Map-reduce - 在本地完成,但希望以内存友好的方式
  6. R只是不是这个工具吗?

我想让它在单台机器(16 GB 笔记本电脑)上运行,而不是在 EC2 上使用大型机器。如果处理得当,6GB 的数据似乎并非不可逾越!

4

1 回答 1

1

我不确定到底发生了什么,但这里有一些有用的提示。首先,这是我用来监控哪些对象占用了内存的函数:

lsBySize<-function(k=20,envir=globalenv()){
  z <- sapply(ls(envir=envir), function(x) object.size(get(x)))
  ret<-sort(z,T)
  if(k>0)
    ret<-ret[1:min(k,length(ret))]

  as.matrix(ret)/10^6
}

gc()随时运行会告诉您当前正在使用多少内存。如果sum(lsBySize(length(ls)))不大约等于 报告的使用的内存量gc(),则发生了一些奇怪的事情。在这种情况下,请编辑 OP 以显示连续运行这两个命令的 R 会话的输出。此外,为了隔离这个问题,最好使用 data.frames,至少现在是这样,因为 data.tables 的内部结构更加复杂和不透明。

于 2013-10-17T18:05:38.553 回答