繁体   English   中英

如何设置时间片 - 动态主题模型

[英]How to set time slices - Dynamic Topic Model

介绍

目前我正在结合使用 Gensim 和 pandas 和 numpy 来运行文档 NLP 计算。 我想构建一个 LDA 序列模型来跟踪我们的主题如何随时间变化,但遇到了语料库格式的错误。

我想弄清楚如何为动态主题模型设置时间片。 我正在使用需要整数时间片的LdaSeqModel

数据

这是一个csv:

 data = pd.read_csv('CGA Jan17 - Mar19 Time Slice.csv', encoding = "ISO-8859-1"); documents = data[['TextForTopics']] documents['index'] = documents.index

 Month Year Begin Date TextForTopics time_slice 0 march 2017 3/23/2017 request: the caller is requesting an appointme... 1

然后将其转换为称为 bow_corpus 的元组数组:

 [[(12, 2), (25, 1), (30, 1)], [(33, 1), (136, 1), (159, 1), (161, 1)], [(165, 1), (247, 2)], (326, 1), (354, 1), (755, 1), (821, 1)]]

期望输出

它应该为每个时间片打印一个主题分配。 如果我输入 3 个主题和两个时间片,我应该会打印两次显示这些主题如何随时间演变的三个主题。

 [(0, '0.165*"enrol" + 0.108*"medicar" + 0.051*"form"), (1, '0.303*"caller" + 0.290*"inform" + 0.031*"abl"), (2, '0.208*"date" + 0.140*"effect" + 0.060*"medicaid"')] [(0, '0.165*"enrol" + 0.108*"cats" + 0.051*"form"), (1, '0.303*"caller" + 0.290*"puppies" + 0.031*"abl"), (2, '0.208*"date" + 0.140*"elephants" + 0.060*"medicaid"')]

我试过的

这是函数 - 弓语料库是一个元组数组

 ldaseq = LdaSeqModel(corpus=bow_corpus, time_slice=[], num_topics=15, chunksize=1)

我已经为那些 time_slices 尝试了每个版本的整数输入,它们都产生了错误。 前提是 time_slice 将表示每个时间片中的索引/行/文档数。 例如,我的数据有 180 万行,如果我想要两个时间片,我会按时间排序我的数据并输入一个整数截止值,如 time_slice = [489234, 1310766]。 所有输入都会产生此错误:

错误

 --------------------------------------------------------------------------- IndexError Traceback (most recent call last) <ipython-input-5-e58059a7fb6f> in <module> ----> 1 ldaseq = LdaSeqModel(corpus=bow_corpus, time_slice=[], num_topics=15, chunksize=1) ~\\AppData\\Local\\Continuum\\anaconda3\\lib\\site-packages\\gensim\\models\\ldaseqmodel.py in __init__(self, corpus, time_slice, id2word, alphas, num_topics, initialize, sstats, lda_model, obs_variance, chain_variance, passes, random_state, lda_inference_max_iter, em_min_iter, em_max_iter, chunksize) 186 187 # fit DTM --> 188 self.fit_lda_seq(corpus, lda_inference_max_iter, em_min_iter, em_max_iter, chunksize) 189 190 def init_ldaseq_ss(self, topic_chain_variance, topic_obs_variance, alpha, init_suffstats): ~\\AppData\\Local\\Continuum\\anaconda3\\lib\\site-packages\\gensim\\models\\ldaseqmodel.py in fit_lda_seq(self, corpus, lda_inference_max_iter, em_min_iter, em_max_iter, chunksize) 275 # seq model and find the evidence lower bound. This is the E - Step 276 bound, gammas = \\ --> 277 self.lda_seq_infer(corpus, topic_suffstats, gammas, lhoods, iter_, lda_inference_max_iter, chunksize) 278 self.gammas = gammas 279 ~\\AppData\\Local\\Continuum\\anaconda3\\lib\\site-packages\\gensim\\models\\ldaseqmodel.py in lda_seq_infer(self, corpus, topic_suffstats, gammas, lhoods, iter_, lda_inference_max_iter, chunksize) 351 bound, gammas = self.inferDTMseq( 352 corpus, topic_suffstats, gammas, lhoods, lda, --> 353 ldapost, iter_, bound, lda_inference_max_iter, chunksize 354 ) 355 elif model == "DIM": ~\\AppData\\Local\\Continuum\\anaconda3\\lib\\site-packages\\gensim\\models\\ldaseqmodel.py in inferDTMseq(self, corpus, topic_suffstats, gammas, lhoods, lda, ldapost, iter_, bound, lda_inference_max_iter, chunksize) 401 time = 0 # current time-slice 402 doc_num = 0 # doc-index in current time-slice --> 403 lda = self.make_lda_seq_slice(lda, time) # create lda_seq slice 404 405 time_slice = np.cumsum(np.array(self.time_slice)) ~\\AppData\\Local\\Continuum\\anaconda3\\lib\\site-packages\\gensim\\models\\ldaseqmodel.py in make_lda_seq_slice(self, lda, time) 459 """ 460 for k in range(self.num_topics): --> 461 lda.topics[:, k] = self.topic_chains[k].e_log_prob[:, time] 462 463 lda.alpha = np.copy(self.alphas) IndexError: index 0 is out of bounds for axis 1 with size 0

解决方案

我尝试返回文档并查看用作示例的 common_corpus 的格式,而我的 bow_corpus 的格式是相同的。 我还尝试运行文档中的代码以查看它是如何工作的,但它也产生了相同的错误。 我不确定问题是否是我的代码,但我希望是。

我还尝试通过手动将我的 csv 分成 9 个包含我的 time_slices 的 csvs 并从中创建一个迭代语料库来弄乱文件格式,但这没有用。 我已经考虑将我的 csv 的每一行转换为 txt 文件,然后像 David Beil 那样从中创建一个语料库,但这听起来毫无意义,因为我已经有了一个迭代语料库。

我将假设您在单个数据帧中工作。 假设您想使用年作为时间单位。

  1. 为了使time_sliceldaseqmodel正常工作,您需要首先对数据帧进行升序排序,即从最旧到最新。
  2. 创建一个 time_slice 变量,以便稍后将其反馈回模型
import numpy as np
uniqueyears, time_slices = np.unique(data.Year, return_counts=True) 
#takes all unique values in data.Year as well as how often they occur and returns them as an array.

print(np.asarray((uniqueyears, time_slices)).T) 
#see what youve made, technically you dont need this

返回(使用示例数据)

[[1992   28]
 [1993   18]
 [1994   25]
 [1995   18]
 [1996   44]
 [1997   38]
 [1998   30]]

这适用多年,如果你想更细粒度,你可以采用相同的概念,只要你有正确的文档排序(这是 gensim 将它们连接到时间片的方式)。 因此,例如,如果您想获取每月切片,则可以将 2017 年 3 月的日期重写为 20173,将 2014 年 4 月的日期重写为 20174。实际上,只要您能将文档识别为属于同一切片,任何粒度都可以。

time_slice (int 列表,可选) – 每个时间片中的文档数。 例如,每个时间片可以代表一年发表的论文,以防语料库来自多年出版的期刊。 假设 sum(time_slice) == num_documents。 gensimdocs

在您的代码中,时间片参数作为空列表输入

time_slice=[]

这是抛出您的问题中列出的回溯。

我对您的数据并不完全熟悉,因此我无法告诉您要为时间片参数输入什么内容。

但是,这是文档中的一个示例。

假设您的语料库有 30 个文档,第一个时间片中有 5 个,第二个中有 10 个,第三个中有 15 个。

你的 time_slice 参数是time_slice=[5,10,15]

根据您的数据,您可能希望直接从您的数据生成 time_slice 列表。

这能把事情弄清楚吗?

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM