如何设置时间片 - 动态主题模型
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"')]
我试过的
这是函数 - bow 语料库是一个元组数组
ldaseq = LdaSeqModel(corpus=bow_corpus, time_slice=[], num_topics=15, chunksize=1)
我已经为那些 time_slices 尝试了每个版本的整数输入,但它们都会产生错误。前提是time_slice代表每个时间片中indicies/rows/documents的个数。例如,如果我想要两个时间片,我的数据有 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 的格式是相同的。我还尝试了 运行ning 文档中的代码以查看它是如何工作的,但它也产生了同样的错误。我不确定问题是否出在我的代码上,但我希望是。
我还尝试通过手动将我的 csv 分成 9 个包含我的 time_slices 的 csvs 并从中创建一个迭代语料库来搞乱文件格式,但这没有用。我考虑过将我的 csv 的每一行转换成 txt 文件,然后像 David Beil 那样从中创建一个语料库,但这听起来毫无意义,因为我已经有了一个迭代的语料库。
time_slice (list of int, optional) – Number of documents in each time-slice. Each time slice could for example represent a year’s
published papers, in case the corpus comes from a journal publishing
over multiple years. It is assumed that sum(time_slice) ==
num_documents.
gensimdocs
在您的代码中,时间片参数作为空列表输入
time_slice=[]
哪个抛出了您问题中列出的回溯。
我不是很熟悉你的数据,所以我不能告诉你应该为时间片参数输入什么。
然而,这是来自文档的示例。
假设你的语料库有 30 个文档,第一个有 5 个 time-slice,第二个有 10 个,第三个有 15 个。
你的time_slice参数是time_slice=[5,10,15]
根据您的数据,您可能希望直接从您的数据生成 time_slice 列表。
这一切都清楚了吗?
我假设您在单个数据框中工作。假设您想使用年作为时间单位。
- 要使
time_slice
与 ldaseqmodel
正常工作,您需要
首先按升序排列您的数据帧,即从最旧到最新。
- 创建一个 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
returns(使用示例数据)
[[1992 28]
[1993 18]
[1994 25]
[1995 18]
[1996 44]
[1997 38]
[1998 30]]
这多年来一直有效,如果你想更细粒度,你可以采用相同的概念,只要你有正确的文档顺序(这是 gensim 将它们连接到时间片的方式)。因此,例如,如果您想要每月切片,您可以将 2017 年 3 月的日期重写为 20173,2014 年 4 月的日期重写为 20174。实际上,只要您可以将文档识别为属于同一切片,任何粒度都可以。
简介
目前我将 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"')]
我试过的
这是函数 - bow 语料库是一个元组数组
ldaseq = LdaSeqModel(corpus=bow_corpus, time_slice=[], num_topics=15, chunksize=1)
我已经为那些 time_slices 尝试了每个版本的整数输入,但它们都会产生错误。前提是time_slice代表每个时间片中indicies/rows/documents的个数。例如,如果我想要两个时间片,我的数据有 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 的格式是相同的。我还尝试了 运行ning 文档中的代码以查看它是如何工作的,但它也产生了同样的错误。我不确定问题是否出在我的代码上,但我希望是。
我还尝试通过手动将我的 csv 分成 9 个包含我的 time_slices 的 csvs 并从中创建一个迭代语料库来搞乱文件格式,但这没有用。我考虑过将我的 csv 的每一行转换成 txt 文件,然后像 David Beil 那样从中创建一个语料库,但这听起来毫无意义,因为我已经有了一个迭代的语料库。
time_slice (list of int, optional) – Number of documents in each time-slice. Each time slice could for example represent a year’s published papers, in case the corpus comes from a journal publishing over multiple years. It is assumed that sum(time_slice) == num_documents. gensimdocs
在您的代码中,时间片参数作为空列表输入
time_slice=[]
哪个抛出了您问题中列出的回溯。
我不是很熟悉你的数据,所以我不能告诉你应该为时间片参数输入什么。
然而,这是来自文档的示例。
假设你的语料库有 30 个文档,第一个有 5 个 time-slice,第二个有 10 个,第三个有 15 个。
你的time_slice参数是time_slice=[5,10,15]
根据您的数据,您可能希望直接从您的数据生成 time_slice 列表。
这一切都清楚了吗?
我假设您在单个数据框中工作。假设您想使用年作为时间单位。
- 要使
time_slice
与ldaseqmodel
正常工作,您需要 首先按升序排列您的数据帧,即从最旧到最新。 - 创建一个 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
returns(使用示例数据)
[[1992 28]
[1993 18]
[1994 25]
[1995 18]
[1996 44]
[1997 38]
[1998 30]]
这多年来一直有效,如果你想更细粒度,你可以采用相同的概念,只要你有正确的文档顺序(这是 gensim 将它们连接到时间片的方式)。因此,例如,如果您想要每月切片,您可以将 2017 年 3 月的日期重写为 20173,2014 年 4 月的日期重写为 20174。实际上,只要您可以将文档识别为属于同一切片,任何粒度都可以。