2017-02-13 15 views
3

У меня есть набор данных из нескольких тысяч строк текста, моя цель - рассчитать оценку tfidf, а затем подобрать косинус между документами, это то, что я сделал с помощью gensim в Python следовал учебник:Python tf-idf: быстрый способ обновить матрицу tf-idf

dictionary = corpora.Dictionary(dat) 
corpus = [dictionary.doc2bow(text) for text in dat] 

tfidf = models.TfidfModel(corpus) 
corpus_tfidf = tfidf[corpus] 
index = similarities.MatrixSimilarity(corpus_tfidf) 

Допустим, у нас есть матрица tfidf и подобие построены, когда у нас есть новый документ, заходите, я хочу запросить его наиболее аналогичный документ в нашем существующем наборе данных.

Вопрос: можно ли каким-либо образом обновить матрицу tf-idf, чтобы мне не пришлось добавлять новый текстовый документ к исходному набору данных и пересчитывать все это снова?

ответ

2

Я выложу свое решение, так как нет других ответов. Скажем, мы в следующем сценарии:

import gensim 
from gensim import models 
from gensim import corpora 
from gensim import similarities 
from nltk.tokenize import word_tokenize 
import pandas as pd 

# routines: 
text = "I work on natural language processing and I want to figure out how does gensim work" 
text2 = "I love computer science and I code in Python" 
dat = pd.Series([text,text2]) 
dat = dat.apply(lambda x: str(x).lower()) 
dat = dat.apply(lambda x: word_tokenize(x)) 


dictionary = corpora.Dictionary(dat) 
corpus = [dictionary.doc2bow(doc) for doc in dat] 
tfidf = models.TfidfModel(corpus) 
corpus_tfidf = tfidf[corpus] 


#Query: 
query_text = "I love icecream and gensim" 
query_text = query_text.lower() 
query_text = word_tokenize(query_text) 
vec_bow = dictionary.doc2bow(query_text) 
vec_tfidf = tfidf[vec_bow] 

, если мы посмотрим на:

print(vec_bow) 
[(0, 1), (7, 1), (12, 1), (15, 1)] 

и:

print(tfidf[vec_bow]) 
[(12, 0.7071067811865475), (15, 0.7071067811865475)] 

FYI Идентификация и РОУ:

print(dictionary.items()) 

[(0, u'and'), 
(1, u'on'), 
(8, u'processing'), 
(3, u'natural'), 
(4, u'figure'), 
(5, u'language'), 
(9, u'how'), 
(7, u'i'), 
(14, u'code'), 
(19, u'in'), 
(2, u'work'), 
(16, u'python'), 
(6, u'to'), 
(10, u'does'), 
(11, u'want'), 
(17, u'science'), 
(15, u'love'), 
(18, u'computer'), 
(12, u'gensim'), 
(13, u'out')] 

ВЫГЛЯДИТ как запрос только взял существующие термины и использовал предварительно рассчитанные веса, чтобы дать вам оценку tfidf. Поэтому мой способ - восстановить модель еженедельно или ежедневно, так как это быстро сделать.

+1

Действительно ли это работает? Я бы подумал, что из-за характера tfidf, по сути, вы не можете постепенно обновлять модель (обновлять матрицу tfidf), потому что каждый раз, когда приходит новый документ, вам придется обновлять значения IDF всех соответствующих функций слова, содержащихся в новый документ по всему корпусу. Кроме того, что происходит, когда документ приходит с новым словом - не будет ли у вас несоответствие длины функции? Пожалуйста, дайте мне знать, так как я также активно изучаю эту проблему. – killerT2333

+0

Работает, но я считаю, что это только запрос вашего нового документа с использованием существующей модели. Я отредактирую свой ответ, чтобы показать работу. – snowneji

+0

Вау! Это действительно здорово - спасибо за это. Итак, если я правильно понимаю, когда приходит новый документ запроса, gensim вычисляет счет tfidf из предварительно вычисленной матрицы tfidf _and_ нового документа запроса? Или он рассчитывает только его из предварительно рассчитанной матрицы tfidf? Обновление модели периодически имеет смысл, если в нее поступают постоянно новые запросы, особенно если это дорого для обновления модели. – killerT2333