LSI с использованием gensim в python

#python #latent-semantic-indexing #gensim

#python #скрытая семантическая индексация #gensim

Вопрос:

Я использую библиотеку gensim Python для выполнения скрытой семантической индексации. Я следил за руководствами на веб-сайте, и это работает довольно хорошо. Теперь я пытаюсь его немного модифицировать; Я хочу запускать модель 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
  

Обычно ошибка появляется во втором документе. Я думаю, что понимаю, о чем это говорит мне (индексы словаря плохие), я просто не могу понять, ПОЧЕМУ. Я пробовал много разных вещей, и, похоже, ничего не работает. Кто-нибудь знает, что происходит?

Спасибо!

Комментарии:

1. привет, Джефф, я использую gensim для создания моей собственной модели LSA. Сначала я хочу спросить, является ли модель LSA такой же, как модель LSI? во-вторых, я пытаюсь использовать пакет gensim, но я не понимаю, как действовать дальше. Я случайно запускаю test_similarities.py и lsimodel.py . но я не вижу никаких выходных данных lsimodel.

2. Да, LSA — это то же самое, что и LSI. Извините, я не могу сильно помочь, я не прикасался к gensim несколько лет, похоже, что там начинаются некоторые руководства по Google id.

Ответ №1:

Это была ошибка в gensim, из-за которой кэшируется обратное сопоставление id-> word, но кэш после этого не обновлялся addDocuments() .

Это было исправлено в этом коммите в 2011 году: https://github.com/piskvorky/gensim/commit/b88225cfda8570557d3c72b0820fefb48064a049 .

Ответ №2:

Хорошо, итак, я нашел решение, хотя и не оптимальное.

Если вы создаете словарь с помощью corpora.Dictionary , а затем сразу добавляете документы с помощью dictionary.addDocuments , все работает нормально.

Но, если вы используете словарь между этими двумя вызовами (вызывая dictionary.doc2bow или подключая свой словарь к модели lsi с помощью id2word ), то ваш словарь «заморожен» и не может быть обновлен. Вы можете вызвать, dictionary.addDocuments и он сообщит вам, что он обновлен, и даже сообщит вам, насколько велик новый словарь, например:

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

Но когда вы ссылаетесь на любой из новых индексов, вы получаете ошибку. Я не уверен, является ли это ошибкой или так было задумано (по какой-либо причине), но, по крайней мере, тот факт, что gensim сообщает об успешном добавлении документа в словарь, безусловно, является ошибкой.

Сначала я попытался поместить любые вызовы словаря в отдельные функции, где должна быть изменена только локальная копия словаря. Ну, это все еще ломается. Для меня это странно, и я понятия не имею, почему.

Моим следующим шагом было попробовать передать копию dictionary, используя copy.copy . Это работает, но, очевидно, потребует немного больше накладных расходов. Однако это позволит вам поддерживать рабочую копию вашего корпуса и словаря. Однако для меня самым большим недостатком здесь было то, что это решение не позволяет мне удалять слова, которые появлялись в корпусе только один раз, используя filterTokens , потому что это повлекло бы за собой изменение словаря.

Мое другое решение — просто перестраивать все (корпус, словарь, модели lsi и tfidf) на каждой итерации. С моим небольшим набором данных выборки это дает мне немного лучшие результаты, но не масштабируется до очень больших наборов данных без возникновения проблем с памятью. Тем не менее, на данный момент это то, что я делаю.

Если у кого-либо из опытных пользователей gensim есть лучшее (и более удобное для памяти) решение, чтобы у меня не возникало проблем с большими наборами данных, пожалуйста, дайте мне знать!

Ответ №3:

В doc2bow вы можете установить allow_update = True, и он будет автоматически обновлять ваш словарь с каждой итерацией doc2bow

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