Python Gensim:如何使用 LDA 模型计算文档相似度?

Posted

技术标签:

【中文标题】Python Gensim:如何使用 LDA 模型计算文档相似度?【英文标题】:Python Gensim: how to calculate document similarity using the LDA model? 【发布时间】:2014-04-21 10:46:56 【问题描述】:

我有一个经过训练的 LDA 模型,我想从我训练模型的语料库中计算两个文档之间的相似度得分。 在学习了所有 Gensim 教程和功能之后,我仍然无法理解它。有人可以给我一个提示吗?谢谢!

【问题讨论】:

【参考方案1】:

不知道这是否有帮助,但是当使用实际文档作为查询时,我设法在文档匹配和相似性方面取得了成功的结果。

dictionary = corpora.Dictionary.load('dictionary.dict')
corpus = corpora.MmCorpus("corpus.mm")
lda = models.LdaModel.load("model.lda") #result from running online lda (training)

index = similarities.MatrixSimilarity(lda[corpus])
index.save("simIndex.index")

docname = "docs/the_doc.txt"
doc = open(docname, 'r').read()
vec_bow = dictionary.doc2bow(doc.lower().split())
vec_lda = lda[vec_bow]

sims = index[vec_lda]
sims = sorted(enumerate(sims), key=lambda item: -item[1])
print sims

您在语料库中的所有文档与用作查询的文档之间的相似度得分将是每个模拟人生的第二个索引。

【讨论】:

感谢您的回答,如果我们想根据多个查询找到类似的文档,那么我们必须如何进行? 我正在使用这种方法来计算相似度,我得到了许多相似度分数为 1。可能是什么问题? 在我看来,这种方法可能不正确,因为文档是 LDA 中维度上的概率分布。你可能不会每次都得到预期的结果。如果您当时使用 LSI,那么这种方法是正确的,因为它表示 LSI 空间中的文档,并且不会像 LDA 那样产生概率分布。可以查看 Jasson-Shanon 和 Kullback-divergence 距离来比较概率分布。【参考方案2】:

取决于您要使用的相似度指标。

Cosine similarity 普遍有用 & built-in:

sim = gensim.matutils.cossim(vec_lda1, vec_lda2)

Hellinger distance 对概率分布(例如 LDA 主题)之间的相似性很有用:

import numpy as np
dense1 = gensim.matutils.sparse2full(lda_vec1, lda.num_topics)
dense2 = gensim.matutils.sparse2full(lda_vec2, lda.num_topics)
sim = np.sqrt(0.5 * ((np.sqrt(dense1) - np.sqrt(dense2))**2).sum())

【讨论】:

您指定为lda_vec1 的变量是什么?当我使用lda[corpus[i]] 时,我只会得到对文档i 有贡献的前 3 或 4 个主题,其余主题权重为 0.0。但是我知道 LDA 应该为每个文档的 all 主题生成主题分布。是否有一些有效的方法(可能使用 gensim index)将查询文档与语料库中的所有其他文档进行比较使用 hellinger 距离 这也是让我困惑的事情。 Radim,您的回答将非常感谢 lda_vec1 是 lda[corpus[i]]。如果是这样,我们如何为整个语料库与新文档构建相似度矩阵 我认为你需要通过将 minimum_probaility 阈值设置为“0”来计算每个主题的所有概率值。之后就可以开始建索引了。 Gensim 有一个用于计算 Hellinger 距离的内置函数:radimrehurek.com/gensim/matutils.html#gensim.matutils.hellinger 我知道这已经很晚了,但我在chat 中找到了lda_vec1 的Radim 含义的示例。【参考方案3】:

提供的答案很好,但对初学者不太友好。我想从训练 LDA 模型开始,计算余弦相似度。

训练模型部分:

docs = ["latent Dirichlet allocation (LDA) is a generative statistical model", 
        "each document is a mixture of a small number of topics",
        "each document may be viewed as a mixture of various topics"]

# Convert document to tokens
docs = [doc.split() for doc in docs]

# A mapping from token to id in each document
from gensim.corpora import Dictionary
dictionary = Dictionary(docs)

# Representing the corpus as a bag of words
corpus = [dictionary.doc2bow(doc) for doc in docs]

# Training the model
model = LdaModel(corpus=corpus, id2word=dictionary, num_topics=10)

为了提取分配给文档每个主题的概率,通常有两种方法。我在这里提供两者:

# Some preprocessing for documents like the training the model
test_doc = ["LDA is an example of a topic model",
            "topic modelling refers to the task of identifying topics"]
test_doc = [doc.split() for doc in test_doc]
test_corpus = [dictionary.doc2bow(doc) for doc in test_doc]

# Method 1
from gensim.matutils import cossim
doc1 = model.get_document_topics(test_corpus[0], minimum_probability=0)
doc2 = model.get_document_topics(test_corpus[1], minimum_probability=0)
print(cossim(doc1, doc2))

# Method 2
doc1 = model[test_corpus[0]]
doc2 = model[test_corpus[1]]
print(cossim(doc1, doc2))

输出:

#Method 1
0.8279631530869963

#Method 2
0.828066885140262

正如您所看到的,这两种方法通常是相同的,不同之处在于第二种方法中返回的概率有时不会像here 中讨论的那样加起来为 1。 对于大型语料库,通过整个语料库可以给出可能性向量:

#Method 1
possibility_vector = model.get_document_topics(test_corpus, minimum_probability=0)
#Method 2
possiblity_vector = model[test_corpus]

注意:分配给文档中每个主题的概率总和可能会略高于 1 或在某些情况下略小于 1。这是因为浮点算术舍入错误。

【讨论】:

这对我很有帮助。也许您可以就我的问题提供一些建议:***.com/questions/63306812/gensim-for-similarities。具体来说,我想在数据帧的行上迭代你的余弦相似度方法(而整个语料库由整个数据帧组成) 好答案。解决了我的问题。

以上是关于Python Gensim:如何使用 LDA 模型计算文档相似度?的主要内容,如果未能解决你的问题,请参考以下文章

初试主题模型LDA-基于python的gensim包

如何保存 Gensim LDA 模型列表?

使用 Gensim 获得 LDA 模型的最佳主题数量的最佳方法是啥?

使用 gensim 了解 LDA 实现

python 使用GenSim的LDA和sklearn的示例

在 Gensim LDA 中记录主题分布