无论文档边界如何,都可以有效地计算大型语料库中的词频

Posted

技术标签:

【中文标题】无论文档边界如何,都可以有效地计算大型语料库中的词频【英文标题】:Calculating term frequencies in a big corpus efficiently regardless of document boundaries 【发布时间】:2021-03-29 02:50:50 【问题描述】:

我有一个包含近 200 万份文档的语料库。我想计算整个语料库中术语的术语频率,而不考虑文档边界。

一种天真的方法是将所有文档组合成一个非常大的文档并将其矢量化。

一种精心设计的方法是使用tm 或任何工具构建一个完整的 TDM,其中可以拥有每个文档中每个术语的术语频率,从而在整个语料库中。这是我的做法:

# Build a TDM from the 'corpus' tibble using a filtered 'texts' column:

htgs = VCorpus(VectorSource(subset(x = corpus,
                                   subset = condition)$texts))
# Some preprocessing
htgs = preprocess(htgs)

# Consider terms whose length is between 2 and Inf in the TDM (the default is 3 to Inf):
dtm_htgs = TermDocumentMatrix(htgs,
                              control = list(wordLengths=c(2, Inf)))
> dtm_htgs
<<TermDocumentMatrix (terms: 495679, documents: 1983567)>>
Non-/sparse entries: 5361931/983207145062
Sparsity           : 100%
Maximal term length: 170
Weighting          : term frequency (tf)

但是,尝试解包由此尝试产生的稀疏矩阵,预期会发出内存错误:

> m = as.matrix(dtm_htgs)

Error: cannot allocate vector of size 7325.5 Gb

如何不考虑每个文档的计数,而将语料库中的全局词频作为一个整体就足够了,这样可以节省大量内存?

【问题讨论】:

【参考方案1】:

你也可以试试:

library("quanteda")

topfeats <- tokens(corpus$text, remove_punct = TRUE) %>%
  dfm() %>%
  topfeatures()

根据您的 RAM 和文档的大小,它应该可以处理 200 万个文档。结果是一个全局词频的命名向量,其中名称是词,值是频率。

【讨论】:

【参考方案2】:

如果我将VectorSource 的输入数据结构从character vector 更改为tibble,我显然得到了我想要的,因为该函数会自动将所有文本整合到一个文档中:

> class(subset(corpus, condition)$texts)
[1] "character"
> class(subset(corpus, condition, select = texts))
[1] "tbl_df"     "tbl"        "data.frame"
htgs = VCorpus(VectorSource(subset(x = corpus,
                                   subset = condition,
                                   select = texts)))

# Same code as in the question: 
htgs = preprocess(htgs)
dtm_htgs = TermDocumentMatrix(htgs,
                              control = list(wordLengths=c(2, Inf)))
> dtm_htgs
<<TermDocumentMatrix (terms: 495679, documents: 1)>>
Non-/sparse entries: 495679/0
Sparsity           : 0%
Maximal term length: 170
Weighting          : term frequency (tf)

最后,频率计数可以简单地使用:

m = as.matrix(dtm_htgs)

# Corpus counts
v = sort(rowSums(m),decreasing=TRUE)
d = data.frame(word = names(v),freq=unname(v))

这实际上消除了稀疏性并节省了大量 RAM,这非常有效,使我能够继续处理数据。

在分析 10 个文档的样本后,我发现生成的词频是有效的。可能有一种更简单的方法可以实现这一点,但他的效率非常高,而且能胜任。

【讨论】:

以上是关于无论文档边界如何,都可以有效地计算大型语料库中的词频的主要内容,如果未能解决你的问题,请参考以下文章

Solr 方法来重新索引大型文档语料库

文本分类特征选择方法

在 TensorFlow Embedding 中有效地找到最接近的词

使用 quanteda 在 R 中的大型语料库上计算余弦相似度

如何有效地计算文档流中的文档之间的相似性

有效地将许多大型 CSV 文件中的 XYZ 坐标排序到小图块中