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

Я использую библиотеку 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

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

Спасибо!


person Jeff    schedule 09.06.2011    source источник
comment
привет, Джефф, я использую gensim для создания собственной модели LSA. Во-первых, я хочу спросить, модель LSA такая же, как модель LSI? во-вторых, я пытаюсь использовать пакет gensim, но не понимаю, как действовать дальше. Я случайным образом запускаю test_similarities.py и lsimodel.py. но я не вижу никакого вывода lsimodel.   -  person Jana    schedule 06.01.2017
comment
Да, LSA — это то же самое, что и LSI. Извините, я не могу помочь, я не касался gensim несколько лет, похоже, там есть несколько руководств по Google id.   -  person Jeff    schedule 06.01.2017


Ответы (3)


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

Это было исправлено в этом коммите в 2011 году: b88225cfda8570557d3c72b0820fefb48064a049 .

person Radim    schedule 14.06.2011

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

Если сделать словарь с 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 сообщает об успешном добавлении документа в словарь, безусловно, является ошибкой.

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

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

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

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

person Jeff    schedule 09.06.2011

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

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

person dmil    schedule 12.08.2013