为语料库(LDA)中的每个文档分配一个主题
Assigning a topic to each document in a corpus (LDA)
我正在尝试计算文档属于 LDA 模型找到的每个主题的概率。我已经成功地生成了 LDA,但现在我被卡住了。我的代码如下:
## Libraries to download
from nltk.tokenize import RegexpTokenizer
from nltk.corpus import stopwords
from nltk.stem.porter import PorterStemmer
from gensim import corpora, models
import gensim
## Tokenizing
tokenizer = RegexpTokenizer(r'\w+')
# create English stop words list
en_stop = stopwords.words('english')
# Create p_stemmer of class PorterStemmer
p_stemmer = PorterStemmer()
import json
import nltk
import re
import pandas
appended_data = []
for i in range(2005,2016):
if i > 2013:
df0 = pandas.DataFrame([json.loads(l) for l in open('SDM_%d.json' % i)])
appended_data.append(df0)
df1 = pandas.DataFrame([json.loads(l) for l in open('Scot_%d.json' % i)])
df2 = pandas.DataFrame([json.loads(l) for l in open('APJ_%d.json' % i)])
df3 = pandas.DataFrame([json.loads(l) for l in open('TH500_%d.json' % i)])
df4 = pandas.DataFrame([json.loads(l) for l in open('DRSM_%d.json' % i)])
appended_data.append(df1)
appended_data.append(df2)
appended_data.append(df3)
appended_data.append(df4)
appended_data = pandas.concat(appended_data)
doc_set = appended_data.body
# 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]
# add tokens to list
texts.append(stopped_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=15, id2word = dictionary, passes=50)
我正在尝试遵循 here 方法,但我发现它很混乱。例如,当我尝试以下代码时:
# Assinging the topics to the document in corpus
lda_corpus = ldamodel[corpus]
# Find the threshold, let's set the threshold to be 1/#clusters,
# To prove that the threshold is sane, we average the sum of all probabilities:
scores = list(chain(*[[score for topic_id,score in topic] \
for topic in [doc for doc in lda_corpus]]))
threshold = sum(scores)/len(scores)
print(threshold)
cluster1 = [j for i,j in zip(lda_corpus,doc_set) if i[0][1] > threshold]
print(cluster1)
它似乎有效,因为它检索了属于主题 1 的文章。不过,有人可以解释背后的直觉是什么以及是否还有其他选择。例如,这里的阈值水平背后的直觉是什么?谢谢
正如我希望您在其他地方读到的那样,阈值是一个特定于应用程序的设置,具体取决于您希望分类模型的范围。 1/k(对于 k 个集群)的基本原理是经验性的:它作为大多数分类任务的起点(即它产生可识别的有用结果)。
直觉层面的理由很简单:如果文档与主题的匹配强度足以超过随机 集群 放置的机会,则它可能是一个肯定的识别。当然,您必须在获得第一个结果后调整 "likely"。
最值得注意的是,您想要观察一两个 "noisy" 集群,其中的主题只是松散相关:该集群的标准偏差大于大多数集群。一些应用程序计算主题的 Z 分数,并为每个主题设置一个基于 Z 的阈值。其他人对给定集群中的所有主题都有一个通用阈值。
您的最终解决方案取决于您所需的匹配强度(较低的阈值)、主题变化(特定主题的阈值)、所需的准确性(误报和漏报的成本是多少?)以及所需的训练和评分速度.
这是否足以帮助您继续前进?
我正在尝试计算文档属于 LDA 模型找到的每个主题的概率。我已经成功地生成了 LDA,但现在我被卡住了。我的代码如下:
## Libraries to download
from nltk.tokenize import RegexpTokenizer
from nltk.corpus import stopwords
from nltk.stem.porter import PorterStemmer
from gensim import corpora, models
import gensim
## Tokenizing
tokenizer = RegexpTokenizer(r'\w+')
# create English stop words list
en_stop = stopwords.words('english')
# Create p_stemmer of class PorterStemmer
p_stemmer = PorterStemmer()
import json
import nltk
import re
import pandas
appended_data = []
for i in range(2005,2016):
if i > 2013:
df0 = pandas.DataFrame([json.loads(l) for l in open('SDM_%d.json' % i)])
appended_data.append(df0)
df1 = pandas.DataFrame([json.loads(l) for l in open('Scot_%d.json' % i)])
df2 = pandas.DataFrame([json.loads(l) for l in open('APJ_%d.json' % i)])
df3 = pandas.DataFrame([json.loads(l) for l in open('TH500_%d.json' % i)])
df4 = pandas.DataFrame([json.loads(l) for l in open('DRSM_%d.json' % i)])
appended_data.append(df1)
appended_data.append(df2)
appended_data.append(df3)
appended_data.append(df4)
appended_data = pandas.concat(appended_data)
doc_set = appended_data.body
# 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]
# add tokens to list
texts.append(stopped_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=15, id2word = dictionary, passes=50)
我正在尝试遵循 here 方法,但我发现它很混乱。例如,当我尝试以下代码时:
# Assinging the topics to the document in corpus
lda_corpus = ldamodel[corpus]
# Find the threshold, let's set the threshold to be 1/#clusters,
# To prove that the threshold is sane, we average the sum of all probabilities:
scores = list(chain(*[[score for topic_id,score in topic] \
for topic in [doc for doc in lda_corpus]]))
threshold = sum(scores)/len(scores)
print(threshold)
cluster1 = [j for i,j in zip(lda_corpus,doc_set) if i[0][1] > threshold]
print(cluster1)
它似乎有效,因为它检索了属于主题 1 的文章。不过,有人可以解释背后的直觉是什么以及是否还有其他选择。例如,这里的阈值水平背后的直觉是什么?谢谢
正如我希望您在其他地方读到的那样,阈值是一个特定于应用程序的设置,具体取决于您希望分类模型的范围。 1/k(对于 k 个集群)的基本原理是经验性的:它作为大多数分类任务的起点(即它产生可识别的有用结果)。
直觉层面的理由很简单:如果文档与主题的匹配强度足以超过随机 集群 放置的机会,则它可能是一个肯定的识别。当然,您必须在获得第一个结果后调整 "likely"。
最值得注意的是,您想要观察一两个 "noisy" 集群,其中的主题只是松散相关:该集群的标准偏差大于大多数集群。一些应用程序计算主题的 Z 分数,并为每个主题设置一个基于 Z 的阈值。其他人对给定集群中的所有主题都有一个通用阈值。
您的最终解决方案取决于您所需的匹配强度(较低的阈值)、主题变化(特定主题的阈值)、所需的准确性(误报和漏报的成本是多少?)以及所需的训练和评分速度.
这是否足以帮助您继续前进?