python – 了解LDA /主题建模 – 主题重叠太多

我是主题建模/ Latent Dirichlet Allocation的新手,并且无法理解如何将该概念应用于我的数据集(或者它是否是正确的方法).

我有少量的文学文本(小说),并希望使用LDA提取一些一般性主题.

我正在使用Python中的gensim模块以及一些nltk功能.对于测试,我将原始文本(仅6个)分成30个块,每个块有1000个单词.然后我将块转换为文档项矩阵并运行算法.这是代码(虽然我认为这个问题无关紧要):

# chunks is a 30x1000 words matrix

dictionary = gensim.corpora.dictionary.Dictionary(chunks)
corpus = [ dictionary.doc2bow(chunk) for chunk in chunks ]
lda = gensim.models.ldamodel.LdaModel(corpus = corpus, id2word = dictionary,
    num_topics = 10)
topics = lda.show_topics(5, 5)

然而,结果与我见过的任何一个例子完全不同,主题中充满了无意义的单词,可以在所有源文档中找到,例如“我”,“他”,“说”,“喜欢”……示例:

[(2, '0.009*"I" + 0.007*"\'s" + 0.007*"The" + 0.005*"would" + 0.004*"He"'), 
(8, '0.012*"I" + 0.010*"He" + 0.008*"\'s" + 0.006*"n\'t" + 0.005*"The"'), 
(9, '0.022*"I" + 0.014*"\'s" + 0.009*"``" + 0.007*"\'\'" + 0.007*"like"'), 
(7, '0.010*"\'s" + 0.009*"I" + 0.006*"He" + 0.005*"The" + 0.005*"said"'), 
(1, '0.009*"I" + 0.009*"\'s" + 0.007*"n\'t" + 0.007*"The" + 0.006*"He"')]

我不太明白为什么会发生这种情况,或者为什么不会发生我见过的例子.如何让LDA模型找到更具特色的主题,减少重叠?是先过滤掉更多常用词吗?如何调整模型运行的次数?原始文本的数量是否太小?

最佳答案 LDA非常依赖于语料库中使用的单词以及它们出现的频率.你所看到的单词都是禁言 – 无意义的单词是一种语言中最常用的单词,例如“the”,“I”,“a”,“if”,“for”,“say”等等,因为这些词是最常见的,它会对模型产生负面影响.

我会使用nltk stopword语料库来过滤掉这些单词:

from nltk.corpus import stopwords
stop_words = stopwords.words('english')

然后确保您的文本不包含stop_words列表中的任何单词(通过您正在使用的任何预处理方法) – 下面是一个示例

text = text.split() # split words by space and convert to list
text = [word for word in text if word not in stop_words]
text = ' '.join(text) # join the words in the text to make it a continuous string again

您可能还想删除标点符号和其他字符(“/”,“ – ”)等)然后使用正则表达式:

import re
remove_punctuation_regex = re.compile(r"[^A-Za-z ]") # regex for all characters that are NOT A-Z, a-z and space " "
text = re.sub(remove_punctuation_regex, "", text) # sub all non alphabetical characters with empty string ""

最后,您可能还想过滤语料库中最频繁或最不频繁的单词,您可以使用nltk进行过滤:

from nltk import FreqDist
all_words = text.split() # list of all the words in your corpus
fdist = FreqDist(all_words) # a frequency distribution of words (word count over the corpus)
k = 10000 # say you want to see the top 10,000 words
top_k_words, _ = zip(*fdist.most_common(k)) # unzip the words and word count tuples
print(top_k_words) # print the words and inspect them to see which ones you want to keep and which ones you want to disregard

这应该摆脱停用词和额外的字符,但仍然留下了主题建模的巨大问题(我不会在这里解释,但会留下一些提示和链接).

假设您对主题建模有所了解,那就让我们开始吧. LDA是一个单词模型,意思是单词顺序无关紧要.该模型为每个文档分配(预定数量的主题K的)主题分布,并为每个主题分配单词分发.一个非常有见地的high level video explains this here.如果你想看到更多的数学,但仍然处于可访问的水平,请查看this video.越多文档越好,通常更长的文档(有更多的单词)使用LDA也更好 – this paper显示LDA在短文本(小于约20个单词)中表现不佳. K由您来决定,并且取决于您的文档语料库(它有多大,它涵盖了哪些不同的主题等).通常K的良好值在100-300之间,但这又取决于你的语料库.

LDA有两个超参数,alpha和beta(gemsim中的alpha和eta) – 更高的alpha意味着每个文本将由更多主题表示(因此自然地,较低的alpha意味着每个文本将由较少的主题表示).高eta意味着每个主题由更多单词表示,而低eta意味着每个主题由更少的单词表示 – 因此,使用低eta,您将在主题之间获得更少的“重叠”.

使用LDA可以获得许多见解

>语料库中的主题是什么(命名主题可能与您的应用程序无关,但是如果这样做可以通过检查主题中的单词来完成,如上所述)
>哪些词对主题贡献最大
>语料库中哪些文档最相似(使用similarity metric)

希望这有所帮助.几个月前我是LDA的新手,但我很快就开始使用stackoverflow和youtube了!

点赞