Gensim 短语模型词汇长度与迭代添加文档的数量不对应

Gensim phrases model vocabulary length does not correspond to amount of iteratively added documents

我反复应用...

bigram.add_vocab(<List of List with Tokens>)

更新方法...

bigram = gensim.models.phrases.Phrases(min_count=bigramMinFreq, threshold=10.0)

Gensim 短语模型。每次迭代最多添加约 10'000 个文档。因此,我的直觉是短语模型随着每个添加的文档集而增长。我通过检查二元词汇表的长度来检查这种直觉......

len(bigram.vocab))

此外,我还检查了冻结短语模型中短语的数量...

bigram_freezed = bigram.freeze()
len(bigram_freezed.phrasegrams)

结果输出如下所示:

Data of directory:  000  is loaded
Num of Docs: 97802
Updated Bigram Vocab is:  31819758
Amount of phrasegrams in freezed bigram model:  397554
-------------------------------------------------------
Data of directory:  001  
Num of Docs: 93368
Updated Bigram Vocab is:  17940420
Amount of phrasegrams in freezed bigram model:  429162
-------------------------------------------------------
Data of directory:  002  
Num of Docs: 87265
Updated Bigram Vocab is:  36120292
Amount of phrasegrams in freezed bigram model:  661023
-------------------------------------------------------
Data of directory:  003
Num of Docs: 55852
Updated Bigram Vocab is:  20330876
Amount of phrasegrams in freezed bigram model:  604504
-------------------------------------------------------
Data of directory:  004
Num of Docs: 49390
Updated Bigram Vocab is:  31101880
Amount of phrasegrams in freezed bigram model:  745827
-------------------------------------------------------
Data of directory:  005
Num of Docs: 56258
Updated Bigram Vocab is:  19236483
Amount of phrasegrams in freezed bigram model:  675705
-------------------------------------------------------
...

可以看出,冻结的二元模型的双元词汇数和短语元数都没有持续增加。我预计这两个计数都会随着文档的增加而增加。

我不明白phrase.vocabphraser.phrasegrams指的是什么? (如果需要,我可以添加整个相应的 Jupyter Notebook 单元格)

默认情况下,为了避免使用无限量的 RAM,Gensim Phrases class 使用默认参数 max_vocab_size=40000000,根据源代码和文档:

https://radimrehurek.com/gensim/models/phrases.html#gensim.models.phrases.Phrases

不幸的是,这个上限背后的机制非常粗糙 & non-intuitive。每当它们 survey-dict 中所有已知键的总数达到此阈值(默认为 40,000,000)时,就会执行 prune 操作,丢弃 all 令牌计数(unigrams & bigrams)在 low-frequencies 直到总数 unique-keys 低于阈值。并且,它将未来 p运行es 的 low-frequency 下限设置为至少与此 p运行e 所需的一样高。

例如,第一次命中时,可能需要丢弃所有 1-count 标记。由于 word-frequencies 的典型 Zipfian 分布,这一步可能不仅会使已知标记的总数稍微低于阈值,而且 大量 低于阈值。并且,任何后续的 p运行e 将首先消除 至少 出现次数少于 2 的所有内容。

这会导致您看到锯齿波计数。当模型无法容纳 max_vocab_size 时,它会过度收缩。在处理一个very-large语料库的过程中,它可能会这样做很多次。因此,lower-frequency words/bigrams 的最终计数也可能是严重的低估 - 取决于某个键的计数是否在各种 prune-thresholds 中幸存下来。 (这也受令牌在语料库中出现位置的影响。仅在语料库中 最后一个 p运行e 之后出现的令牌仍将具有精确计数,即使它只出现一次!虽然出现任何次数的稀有标记可能会被严重低估,但如果它们在每个先前的 p运行e.)

总是低于截止值

最好的解决方案是使用精确计数 uses/correlates 一些溢出存储 on-disk,到最后只有 p运行e(如果有的话),确保只有 truly-least-frequent 键被丢弃。不幸的是,Gensim 从未实施过该选项。

在许多情况下,next-best 可能会使用 memory-efficient 近似计数算法,该算法模糊地保持 much-larger 个键的正确计数值。过去在 Gensim 中对此做了一些小工作,但尚未与 Phrases 功能集成。

这给您留下了短期内唯一可行的解​​决方法:将 max_vocab_size 参数更改为更大的值。

您可以尝试将其设置为 math.inf(由于 int-vs-float 比较可能会降低性能)或 sys.maxsize – 基本上完全关闭 p运行ing,查看您的调查是否可以在不耗尽 RAM 的情况下完成。但是,您可能 运行 内存不足。

您也可以尝试一个 larger-but-not-essentially-infinite 上限——任何适合您的 RAM 的上限——这样就可以大大减少 p运行ing 的完成。但是您仍然会看到 non-intuitive 总计数减少,有时,如果实际上曾经强制执行阈值的话。根据文档,非常粗略(可能已过时)估计默认 max_vocab_size=40000000 在峰值饱和时消耗约 3.6GB。因此,如果您有一台 64GB 的机器,您可以尝试 max_vocab_size 比默认值大 10-14 倍等