0

我正在尝试使用出色的 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 > 1 的 n-gram,那就更糟了:

> 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

我找到了这个相关的帖子,但它看起来是密集矩阵强制的问题,后来解决了,它对我的​​情况没有帮助。

有没有更好的方法可以在内存有限的情况下处理这个问题,而不必将语料库数据分解成碎片?

[编辑] 根据要求, 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
4

2 回答 2

3

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

根据评论更新。

至于加载,稀疏矩阵/数组听起来是个好主意,想想看,它也可能是存储的好主意(特别是如果你碰巧只处理二元组)。如果您的数据那么大,那么您可能无论如何都必须考虑索引(这应该有助于存储:而不是将单词存储在 bigrams 中,索引所有单词并存储索引元组)。但这也取决于您的“完整 n-gram 模型”应该用于什么。如果要查找文本中(相对少量)单词的条件概率,那么您可以只对存储的 ngram 文件进行搜索(grep)。我不确定在这样一个简单的任务中索引开销是否合理。如果您确实需要模型中所有 12GB 的 ngram,并且模型必须逐个计算一些无法完成的东西,

但是还有一个更一般的建议,我也经常给学生一个建议:从小处着手。代替 12BG,对数据的小子集进行训练和测试。在您弄清楚确切的实现和消除错误时为您节省大量时间 - 特别是如果您碰巧不确定这些事情是如何工作的。

于 2016-03-30T19:47:35.127 回答
1

现在可能为时已晚,但我最近遇到了一个非常相似的问题(n-grams、R、Quanteda 和大文本源)。找了两天没找到满意的解决办法,发到本论坛等都没有得到答复。我知道我必须在最后对数据进行分块并组合结果,但不知道如何进行分块。最后,我在这里找到了一个有点不优雅的解决方案,并在下面的帖子中回答了我自己的问题

我使用 'tm' 包 VCorpus 对语料库进行切片,然后使用 corpus() 函数将这些块提供给 quanteda。

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

于 2017-01-12T22:10:12.630 回答