理解LDA/主题建模--主题重叠太多

11

我对主题建模/潜在狄利克雷分配还不太了解,不知道如何将其应用到我的数据集中(或者这是否是正确的方法)。

我有一些文学作品(小说),希望使用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模型找到更具有区别性的主题并减少重叠?是先过滤掉更常见的词汇吗?我该如何调整模型运行的次数?原始文本的数量是否太少?

1个回答

33
LDA非常依赖语料库中使用的单词及其出现频率。您看到的所有单词都是停用词——在语言中最常见但没有意义的单词,例如“the”、“I”、“a”、“if”、“for”、“said”等。由于这些单词最常见,它们会对模型产生负面影响。我建议使用nltk停用词语料库来过滤掉这些单词:
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),并为每个主题分配一个单词分布。非常具有洞察力的高水平视频在这里解释了这一点。如果您想看到更多的数学内容,但仍在可接受的水平上,请查看此视频。文档越多越好,通常使用LDA也更适合较长的文档(具有更多单词) - 本论文表明LDA在短文本(少于约20个单词)中表现不佳。选择K取决于您的文档集(其大小,涵盖的不同主题等),通常K的好值在100-300之间,但这真的取决于您的语料库。
LDA有两个超参数,alpha和beta(在gemsim中为alpha和eta)-较高的alpha意味着每个文本将由更多主题表示(因此自然地,较低的alpha意味着每个文本将由较少主题表示)。高eta意味着每个主题由更多单词表示,而低eta意味着每个主题由较少单词表示-因此,使用低eta,您将获得更少的主题“重叠”。使用LDA可以获得许多见解:
1. 语料库中有哪些主题(对于您的应用程序来说,命名主题可能并不重要,但如果需要,可以通过检查主题中的单词来完成,就像您上面所做的那样) 2. 哪些单词对主题做出了最大贡献 3. 语料库中哪些文档最相似(使用相似性度量
希望这有所帮助。几个月前我还不熟悉LDA,但是通过使用stackoverflow和youtube,我很快就掌握了它!

1
如果您觉得这个回答解决了您的问题,请毫不犹豫地点击绿色勾号,将其标记为正确答案 :) 如果不是,请让我知道是否有任何地方需要我进行扩展/更好地解释。 - PyRsquared

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接