我正在使用gensim的lda implementation来创建文档主题模型分发。我有一个lda
受过培训的模型
dictionary = corpora.Dictionary(data)
corpus = [dictionary.doc2bow(doc) for doc in data]
num_cores = multiprocessing.cpu_count()
num_topics = 150
lda = LdaMulticore(corpus=corpus, num_topics=num_topics, id2word=dictionary, workers=num_cores, alpha=1e-4, eta=5e-1,
minimum_probability=0.0)
我想提取大小为N * M的分布矩阵,其中N是语料库中的文档数,M是主题数。因此,每行代表一个文档,每列代表一个主题。这些分布已在lda
模型变量中提供,例如
lda
>>> [[(0,0.01),(1,0.23),(2,1e-7)],
[(0,0.91),(1,0.067),(2,0.38)]]
如果我们有2个文档和3个主题(0,1,2),上面代表一个简单的例子。所以lda
是一个元组列表的列表,其中每个列表都是一个文档,元组中的第一个元素是主题id,第二个元素是该文档的主题贡献。
到目前为止我做了什么
# approach 1
distributions = np.array( [[tup[1] for tup in lst] for lst in lda[corpus]] )
# approach 2 (about 3X slower than approach 1)
distributions = np.array(lda[corpus])[:,:,1]
问题是,对于包含300k文档和150个主题的数据集,使用方法1创建distributions
矩阵需要10分钟。
最终,我想创建这个矩阵以输入计算文档相似性的函数(将矩阵的第一行/文档与所有其他行/文档进行比较)。如果有一种方法可以将学习的lda
模型值直接输入到函数中,那么这将是很好的,因为它可以节省创建冗余矩阵的时间。如果没有,是否有更有效的方法来创建distributions
矩阵?
作为参考,distributions
矩阵被馈入的文档比较函数是
from sklearn.preprocessing import normalize
from scipy.stats import entropy
def jsd(mat):
mat = normalize(mat, axis=1, norm='l1')
p = mat[0,None].T # just comparing first row to all other rows
q = mat[0:].T
m = 0.5*(p + q)
return 0.5*(entropy(p,m) + entropy(q,m))