LSI在python中使用gensim

时间:2011-06-09 02:20:59

标签: python latent-semantic-indexing gensim

我正在使用Python的gensim库来进行潜在的语义索引。我按照网站上的教程进行操作,效果非常好。现在我想尝试修改一下;我想在每次添加文档时运行lsi模型。

这是我的代码:

stoplist = set('for a of the and to in'.split())
num_factors=3
corpus = []

for i in range(len(urls)):
 print "Importing", urls[i]
 doc = getwords(urls[i])
 cleandoc = [word for word in doc.lower().split() if word not in stoplist]
 if i == 0:
  dictionary = corpora.Dictionary([cleandoc])
 else:
  dictionary.addDocuments([cleandoc])
 newVec = dictionary.doc2bow(cleandoc)
 corpus.append(newVec)
 tfidf = models.TfidfModel(corpus)
 corpus_tfidf = tfidf[corpus]
 lsi = models.LsiModel(corpus_tfidf, numTopics=num_factors, id2word=dictionary)
 corpus_lsi = lsi[corpus_tfidf]

geturls是我编写的函数,它将网站的内容作为字符串返回。同样,如果我等到我在执行tfidf和lsi之前处理所有文档,它仍然有效,但这不是我想要的。我想在每次迭代时都这样做。不幸的是,我收到了这个错误:

    Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "streamlsa.py", line 51, in <module>
    lsi = models.LsiModel(corpus_tfidf, numTopics=num_factors, id2word=dictionary)
  File "/Library/Python/2.6/site-packages/gensim-0.7.8-py2.6.egg/gensim/models/lsimodel.py", line 303, in __init__
    self.addDocuments(corpus)
  File "/Library/Python/2.6/site-packages/gensim-0.7.8-py2.6.egg/gensim/models/lsimodel.py", line 365, in addDocuments
    self.printTopics(5) # TODO see if printDebug works and remove one of these..
  File "/Library/Python/2.6/site-packages/gensim-0.7.8-py2.6.egg/gensim/models/lsimodel.py", line 441, in printTopics
    self.printTopic(i, topN = numWords)))
  File "/Library/Python/2.6/site-packages/gensim-0.7.8-py2.6.egg/gensim/models/lsimodel.py", line 433, in printTopic
    return ' + '.join(['%.3f*"%s"' % (1.0 * c[val] / norm, self.id2word[val]) for val in most])
  File "/Library/Python/2.6/site-packages/gensim-0.7.8-py2.6.egg/gensim/corpora/dictionary.py", line 52, in __getitem__
    return self.id2token[tokenid] # will throw for non-existent ids
KeyError: 1248

通常在第二个文档上弹出错误。我想我明白它告诉我的是什么(字典索引很糟糕),我只是无法弄清楚为什么。我尝试过很多不同的东西,似乎没什么用。有谁知道发生了什么事?

谢谢!

3 个答案:

答案 0 :(得分:4)

这是gensim中的一个错误,其中反向id-&gt;字映射被缓存,但缓存在addDocuments()之后没有更新。

2011年在此提交中得到修复:https://github.com/piskvorky/gensim/commit/b88225cfda8570557d3c72b0820fefb48064a049

答案 1 :(得分:1)

好的,所以我找到了一个解决方案,尽管不是最佳解决方案。

如果您使用corpora.Dictionary创建字典,然后立即添加dictionary.addDocuments的文档,那么一切正常。

但是,如果您在这两个调用之间使用字典(通过调用dictionary.doc2bow或将字典附加到带有id2word的lsi模型),那么您的字典就是'冻结',无法更新。您可以致电dictionary.addDocuments,它会告诉您已更新,它甚至会告诉您新词典有多大,例如:

INFO:dictionary:built Dictionary(6627 unique tokens) from 8 documents (total 24054 corpus positions)

但是当你引用任何新索引时,你会收到一个错误。我不确定这是一个错误还是这个错误(无论出于何种原因),但至少gensim 报告成功地将文档添加到字典这一事实肯定是一个错误。< / p>

首先,我尝试将任何字典调用放在单独的函数中,其中只应修改字典的本地副本。好吧,它仍然打破。这对我来说很奇怪,我不明白为什么。

我的下一步是尝试使用copy.copy传递字典的副本。这可行,但显然会使用更多的开销。但是,它将允许您维护语料库和词典的工作副本。对我来说,最大的缺点是,这个解决方案不允许我删除使用filterTokens在语料库中只出现一次的单词,因为这需要修改字典。

我的另一个解决方案是在每次迭代时重建所有内容(语料库,字典,lsi和tfidf模型)。使用我的小样本数据集,这给了我稍微好一些的结果,但是不能在不引起内存问题的情况下扩展到非常大的数据集。不过,现在这就是我在做的事情。

如果任何有经验的gensim用户有更好的(更友好的内存)解决方案,以便我不会遇到更大的数据集问题,请告诉我!

答案 2 :(得分:0)

在doc2bow中,您可以设置allow_update = True,它会在每次迭代doc2bow时自动更新您的字典

http://radimrehurek.com/gensim/corpora/dictionary.html