每次我在同一语料库上训练时,LDA模型会生成不同的主题

时间:2013-02-25 13:08:29

标签: python nlp lda topic-modeling gensim

我正在使用python gensim从231个句子的小型语料库中训练潜在Dirichlet分配(LDA)模型。但是,每次重复该过程时,它都会生成不同的主题。

为什么每次都会使用相同的LDA参数和语料库生成不同的主题?

我如何稳定主题生成?

我正在使用此语料库(http://pastebin.com/WptkKVF0)和此停用词列表(http://pastebin.com/LL7dqLcj),这是我的代码:

from gensim import corpora, models, similarities
from gensim.models import hdpmodel, ldamodel
from itertools import izip
from collections import defaultdict
import codecs, os, glob, math

stopwords = [i.strip() for i in codecs.open('stopmild','r','utf8').readlines() if i[0] != "#" and i != ""]

def generateTopics(corpus, dictionary):
    # Build LDA model using the above corpus
    lda = ldamodel.LdaModel(corpus, id2word=dictionary, num_topics=50)
    corpus_lda = lda[corpus]

    # Group topics with similar words together.
    tops = set(lda.show_topics(50))
    top_clusters = []
    for l in tops:
        top = []
        for t in l.split(" + "):
            top.append((t.split("*")[0], t.split("*")[1]))
        top_clusters.append(top)

    # Generate word only topics
    top_wordonly = []
    for i in top_clusters:
        top_wordonly.append(":".join([j[1] for j in i]))

    return lda, corpus_lda, top_clusters, top_wordonly

####################################################################### 

# Read textfile, build dictionary and bag-of-words corpus
documents = []
for line in codecs.open("./europarl-mini2/map/coach.en-es.all","r","utf8"):
    lemma = line.split("\t")[3]
    documents.append(lemma)
texts = [[word for word in document.lower().split() if word not in stopwords]
             for document in documents]
dictionary = corpora.Dictionary(texts)
corpus = [dictionary.doc2bow(text) for text in texts]

lda, corpus_lda, topic_clusters, topic_wordonly = generateTopics(corpus, dictionary)

for i in topic_wordonly:
    print i

4 个答案:

答案 0 :(得分:29)

  

为什么每次都有相同的LDA参数和语料库生成不同的主题?

因为LDA在训练和推理步骤中都使用随机性。

  

我如何稳定主题生成?

每次使用numpy.random进行模型训练或推理时,将numpy.random.seed种子重置为相同的值:

SOME_FIXED_SEED = 42

# before training/inference:
np.random.seed(SOME_FIXED_SEED)

(这很丑陋,这让Gensim的结果难以复制;考虑提交一个补丁。我已经打开了issue。)

答案 1 :(得分:4)

在LdaModel()方法的初始化中设置lda_model = gensim.models.ldamodel.LdaModel(corpus=corpus, id2word=id2word, num_topics=num_topics, random_state=1, passes=num_passes, alpha='auto') 参数。

CREATE TABLE `post_likes` (
  `id` int(11) NOT NULL,
  `title` varchar(255) DEFAULT NULL,
  `post_id` int(11) NOT NULL,
  `type` enum('FB_LIKES','LINKEDIN_LIKES') NOT NULL,
  `user_hash` varchar(30) NOT NULL,
  `like_count` int(11) NOT NULL,
  `created_date` timestamp NULL DEFAULT CURRENT_TIMESTAMP
) ENGINE=InnoDB DEFAULT CHARSET=latin1;  

答案 2 :(得分:1)

这是由于LDA的概率性质,正如其他人所指出的那样。但是,我不认为将random_seed参数设置为固定数字是正确的解决方案。

绝对先尝试增加迭代次数,以确保您的算法正在收敛。即使这样,每个起点也可能使您处于不同的局部最小值。因此,您可以在不设置random_seed的情况下多次运行LDA,然后使用每个模型的一致性得分来比较结果。这可以帮助您避免局部最优值不足。

Gensim的CoherenceModel已经为您实现了最常见的一致性度量标准,例如c_vu_massc_npmi

您可能意识到这些将使结果更加稳定,但实际上并不能保证每次运行都得到相同的结果。但是,最好是尽可能达到全局最优值,而不要因为固定的random_seed IMO而停留在相同的局部最小值上。

答案 3 :(得分:0)

即使有大约50,000条评论,我也遇到了同样的问题。但是,通过增加LDA运行的迭代次数,您可以获得更加一致的主题。它最初设置为50,当我将其提高到300时,它通常会给我相同的结果,可能是因为它更接近收敛。

具体来说,您只需添加以下选项:

ldamodel.LdaModel(corpus, ..., iterations = <your desired iterations>):