使用R和Quanteda计算大型语料库中的n-gram

时间:2016-03-29 12:32:21

标签: r nlp out-of-memory quanteda

我正在尝试使用伟大的Quanteda包从大型语料库(R中的对象大小约为1Gb)构建n-gram。 我没有可用的云资源,因此我使用自己的笔记本电脑(Windows和/或Mac,12Gb RAM)进行计算。

如果我将数据分解为片段,代码可以工作,我得到各种大小的n-gram的(部分)dfm,但是当我尝试在整个语料库上运行代码时,不幸的是我用这个来达到内存限制语料库大小,并得到以下错误(unigrams,单个单词的示例代码):

> dfm(corpus, verbose = TRUE, stem = TRUE,
      ignoredFeatures = stopwords("english"),
      removePunct = TRUE, removeNumbers = TRUE)
Creating a dfm from a corpus ...
... lowercasing
... tokenizing
... indexing documents: 4,269,678 documents
... indexing features: 
Error: cannot allocate vector of size 1024.0 Mb

In addition: Warning messages:
1: In unique.default(allFeatures) :
  Reached total allocation of 11984Mb: see help(memory.size)

如果我尝试使用n>来构建n-gram,那就更糟了1:

> dfm(corpus, ngrams = 2, concatenator=" ", verbose = TRUE,
     ignoredFeatures = stopwords("english"),
     removePunct = TRUE, removeNumbers = TRUE)

Creating a dfm from a corpus ...
... lowercasing
... tokenizing
Error: C stack usage  19925140 is too close to the limit

我找到了this related post,但它看起来是密集矩阵强制的问题,后来解决了,在我的情况下它没有用。

有没有更好的方法来处理这个有限的内存量,而不必将语料库数据分解成碎片?

[编辑]根据要求,sessionInfo()数据:

> sessionInfo()
R version 3.2.3 (2015-12-10)
Platform: x86_64-w64-mingw32/x64 (64-bit)
Running under: Windows 7 x64 (build 7601) Service Pack 1

locale:
[1] LC_COLLATE=English_United States.1252  LC_CTYPE=English_United States.1252   
[3] LC_MONETARY=English_United States.1252 LC_NUMERIC=C                          
[5] LC_TIME=English_United States.1252    

attached base packages:
[1] stats     graphics  grDevices utils     datasets  methods   base     

other attached packages:
[1] data.table_1.9.6 dplyr_0.4.3      quanteda_0.9.4  

loaded via a namespace (and not attached):
 [1] magrittr_1.5    R6_2.1.2        assertthat_0.1  Matrix_1.2-3    rsconnect_0.4.2 DBI_0.3.1      
 [7] parallel_3.2.3  tools_3.2.3     Rcpp_0.12.3     stringi_1.0-1   grid_3.2.3      chron_2.3-47   
[13] lattice_0.20-33 ca_0.64

2 个答案:

答案 0 :(得分:3)

是的,确切地说是把它分成几块,但是听我说。不是导入整个语料库,而是导入它的一部分(它是在文件中:然后逐个文件导入;它是在一个巨大的txt文件中 - 很好,使用readLines)。计算你的n-gram,将它们存储在另一个文件中,读取下一个文件/行,再次存储n-gram。这更灵活,不会遇到RAM问题(当然,它需要比原始语料库更多的空间,具体取决于n的值)。之后,您可以按常规方式从文件中访问ngrams。

根据评论更新。

至于加载,稀疏矩阵/数组听起来是个好主意,想到它,它也可能是一个好主意(特别是如果你恰好只处理bigrams)。如果你的数据很大,你可能不得不考虑索引(这应该有助于存储:而不是在bigrams中存储单词,索引所有单词并存储索引元组)。但这也取决于你的全套n-gram模型"应该是为了。如果要查找文本中(相对较少数量)单词的条件概率,则可以对存储的ngram文件进行搜索(grep)。我不确定在这么简单的任务中索引开销是否合理。如果你真的需要一个模型中所有12GB的ngrams,并且模型必须计算一些不能一件一件地完成的东西,那么你仍然需要一个集群/云。

但是还有一个更普遍的建议,一个我经常给学生的建议:从小开始。而不是12BG,训练和测试数据的小子集。在确定具体实施方案并消除错误时,可以节省大量时间 - 特别是如果您不确定这些工作是如何工作的。

答案 1 :(得分:1)

现在可能太晚了,但最近我遇到了一个非常类似的问题(n-gram,R,Quanteda和大文本来源)。我搜索了两天而不能 找到一个满意的解决方案,发布在这个论坛和其他人,并没有得到答案。我知道我必须将数据块化并最终结合结果,但无法解决如何进行分块的问题。最后,我发现了一个有点不优雅的解决方案,可以在以下帖子here

中解决我自己的问题。

我使用&t;< tm'来切断语料库。然后包VCorpus使用corpus()函数将块提供给quanteda。

我想我会在提供代码解决方案时发布它。希望它会阻止其他人花两天时间搜索。