在LDA模型中规定“好”/“坏” - 在Python中使用gensim

时间:2016-08-09 13:43:39

标签: python python-2.7 lda gensim

我正在尝试分析新闻片段以识别危机时期。 为此,我已经在过去7年中下载了新闻文章,并提供了这些文章。 现在,我在此数据集上应用LDA(潜在Dirichlet分配)模型,以确定那些显示出经济危机迹象的国家。

我的代码基于Jordan Barber的博客文章(https://rstudio-pubs-static.s3.amazonaws.com/79360_850b2a69980c4488b1db95987a24867a.html) - 这是我目前的代码:

import os, csv

#create list with text blocks in rows, based on csv file
list=[]

with open('Testfile.csv', 'r') as csvfile:
    emails = csv.reader(csvfile)
    for row in emails:
         list.append(row)

#create doc_set
doc_set=[]

for row in list:
    doc_set.append(row[0])

#import plugins - need to install gensim and stop_words manually for fresh python install
from nltk.tokenize import RegexpTokenizer
from stop_words import get_stop_words
from nltk.stem.porter import PorterStemmer
from gensim import corpora, models
import gensim

tokenizer = RegexpTokenizer(r'\w+')

# create English stop words list
en_stop = get_stop_words('en')

# Create p_stemmer of class PorterStemmer
p_stemmer = PorterStemmer()


# list for tokenized documents in loop
texts = []

# loop through document list
for i in doc_set:

    # clean and tokenize document string
    raw = i.lower()
    tokens = tokenizer.tokenize(raw)

    # remove stop words from tokens
    stopped_tokens = [i for i in tokens if not i in en_stop]

    # stem tokens
    stemmed_tokens = [p_stemmer.stem(i) for i in stopped_tokens]

    # add tokens to list
    texts.append(stemmed_tokens)


# turn our tokenized documents into a id <-> term dictionary
dictionary = corpora.Dictionary(texts)

# convert tokenized documents into a document-term matrix
corpus = [dictionary.doc2bow(text) for text in texts]

# generate LDA model
ldamodel = gensim.models.ldamodel.LdaModel(corpus, num_topics=5, id2word = dictionary, passes=10)

print(ldamodel.print_topics(num_topics=5, num_words=5))

# map topics to documents
doc_lda=ldamodel[corpus]

with open('doc_lda.csv', 'w') as outfile:
    writer = csv.writer(outfile)
    for row in doc_lda:
        writer.writerow(row)

基本上,我确定了许多主题(上面的代码中有5个 - 要检查),并且使用最后一行我为每个新闻文章分配一个分数,这表示文章与其中一个主题相关的概率。 现在,我只能手动对某个特定主题是否与危机相关进行定性评估,这有点不幸。 我更愿意做的是告诉算法在危机期间是否发表了一篇文章,并使用这些额外的信息来确定我的“危机年”以及我的“非危机年”这两个主题。简单地将我的数据集拆分为只考虑我的“坏事”(即危机年代)的主题在我看来是行不通的,因为我仍然需要手动选择哪些主题实际上与危机有关,以及哪些主题会显示无论如何(体育新闻,...)。

那么,是否有一种方法可以使代码适应a)包含“危机”与“非危机”的信息,以及b)自动选择最佳数量的主题/单词以优化模型的预测能力?

提前多多感谢!

1 个答案:

答案 0 :(得分:0)

首先就您的具体问题提出一些建议:

  

a)纳入“危机”与“非危机”的信息

要使用标准的LDA模型,我可能会在doc主题比例和文档是否处于危机/非危机时期之间寻求相互信息。

  

b)自动选择最佳数量的主题/单词以优化模型的预测能力?

如果您想要正确执行此操作,请尝试使用多个主题设置,并尝试使用主题模型预测保留文档的冲突/非冲突(主题模型中未包含的文档)。

有许多主题模型变体可以有效地选择主题数量(“非参数”模型)。事实证明,具有超参数优化的Mallet实现有效地做了同样的事情,因此我建议使用它(提供大量主题 - 超参数优化将导致许多主题,分配的字很少,这些主题只是噪声)。

以及一些一般性评论:

有许多主题模型变体,特别是一些包含时间的变体。这些对您来说可能是一个不错的选择(因为它们会比标准LDA更好地解决主题变化 - 尽管标准LDA是一个很好的起点)。

我特别喜欢的一个模型使用了pitman-yor word priors(比dirichlet更好地匹配zipf分布式单词),解释了主题的突发性并提供了垃圾主题的线索:https://github.com/wbuntine/topic-models