我是主题建模/潜在Dirichlet分配的新手,并且无法理解如何将概念应用于我的数据集(或者它是否是正确的方法)。
我有少量文学作品(小说),并希望使用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模型找到更具特色的主题,减少重叠?是先过滤掉更多常用词吗?如何调整模型运行的次数?原始文本的数量是否太小?
答案 0 :(得分:9)
LDA极其依赖于语料库中使用的单词以及它们出现的频率。你所看到的单词都是禁言 - 无意义的单词是一种语言中最常用的单词,例如“the”,“I”,“a”,“if”,“for”,“say”等等,由于这些词是最常见的,它会对模型产生负面影响。
我会使用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的)主题分布,并为每个主题分配单词分发。一个非常有见地的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了!