问题描述
我正在从头开始构建主题模型,其中一个步骤使用 TfidfVectorizer 方法从我的文本语料库中获取 unigrams 和 bigrams:
tfidf_vectorizer = TfidfVectorizer(min_df=0.1,max_df=0.9,ngram_range = (1,2))
创建主题后,我使用 gensim 的 Word2Vec 提供的相似度分数来确定主题的连贯性。我通过在同一个语料库上进行训练来做到这一点:
bigram_transformer = Phrases(corpus)
model = Word2Vec(bigram_transformer[corpus],min_count=1)
然而,对于我的主题中的许多二元组,我得到了一个 KeyError 错误,因为在 Word2Vec 的训练中没有选择该二元组,尽管它们是在同一个语料库上训练的。我认为这是因为 Word2Vec 根据统计分析决定选择哪些二元组 (Why aren't all bigrams created in gensim's `Phrases` tool?)
有没有办法让 Word2Vec 包含所有由 TfidfVectorizer 识别的二元组?我看到了诸如“trim_rule”之类的修剪功能,但没有看到其他方面的功能。
解决方法
Gensim 中 Phrases
模型的重点是选择一些二元组,这些二元组经计算具有统计显着性。
如果您随后将该模型的确定应用于您的语料库的预处理步骤,则文本中的某些 unigram 对将被组合的 bigram 彻底替换。 (因此,一些原本存在的 unigram 可能不会再出现一次。)
因此,Gensim 的 Phrases
和 TfidfVectorizer
的 ngram_range
工具使用的二元组概念是不同的。 Phrases
用于破坏性替换,其中推断出特定的二元组比一元组更有趣。 TfidfVectorizer
将添加额外的二元组作为额外的维度特征。
我认为对 Phrases
的正确调整可以使其将每个二元组视为重要的。如果不检查,它看起来像一个超小的值,如 0.0000000001
,可能本质上具有这种效果。 (Phrases
类将拒绝 0
的值,因为它通常使用无意义。)
但到那时,您的后期转换(通过 bigram_transformer[corpus]
)将在 Word2Vec
训练之前组合所有可能的单词对。例如,这句话:
['the','skittish','cat','jumped','over','the','gap',]
...会不分青红皂白地变成...
['the_skittish','cat_jumped','over_the',]
出于多种原因,您似乎不太可能希望这样做:
- 然后可能没有单独使用
'cat'
一元组的训练文本,让您根本没有该词的词向量。 - 很少见或没有什么语法价值的二元词组(如
'the_skittish'
)将接收经过训练的词向量,并占用模型中的空间。 - 大到足以获得良好
Word2Vec
结果的文本语料库的种类可能比可管理的多得多。 (一个足够小的语料库,您可以负担得起跟踪每个二元组的能力,但可能会获得良好的Word2Vec
结果。)
此外,要执行 所有 二元组的贪婪组合,甚至不需要 Phrases
频率调查和计算。 (无需准备/分析即可自动完成。)
因此,您不应该期望 TfidfVectorizer
的每个 bigram 都获得一个词向量,除非您在 Phrases
的正常行为之外采取一些额外的步骤,以确保每个这样的 bigram 都是在培训文本中。
尝试这样做根本不需要 Phrases
,并且可能无法管理,并且涉及其他权衡。 (例如,我可以想象多次重复语料库,每次只组合一小部分二元组——这样每个二元组有时被其他一元组包围,有时被其他二元组包围——以创建一个具有足够有意义的文本的合成语料库来创建所有你想要的向量。但那个模型的逻辑和存储空间会更大更复杂,而且没有突出的先例,所以这将是一个新的实验。)