我有一个数千行文本的数据集,我的目标是计算tfidf得分,然后计算文档之间的余弦相似度,这就是我在Python中使用gensim所做的跟随教程:
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矩阵,这样我就不必将新文本doc附加到原始数据集并重新计算整个事物了?
答案 0 :(得分: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 id和doc:
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 :(得分:0)
让我分享我的想法。
一件事是 Corpus ,另一件事是 Model ,而另一件事是 Query 。我会说有时候混合起来很容易。
1)语料库和模型
语料库是一组文档,即您的库,其中每个文档都以某种格式表示。例如,Corpus_BOW将您的文档表示为单词袋。 Corpus_TFIDF用他们的TFIDF表示您的文档。
模型是一种将语料库表示形式转换为另一种形式的东西。例如, Model_TFIDF 转换 Corpus_BOW-> Corpus_TFIDF 。您可以具有其他模型,例如Corpus_TFIDF-> Corpus_LSI或Corpus_BOW-> Corpus_LSI的模型。
我想说的是,这是出色的 Gensim 的主要性质,成为 Corpus转化器。目的是要找到能更好地代表您的应用程序文档之间相似性的语料库表示形式。
一些重要的想法:
因此,我们首先使用入口语料库构建模型,然后将模型应用于相同的入口语料库,以获得输出语料库。也许可以合并一些步骤,但这只是概念上的步骤。
2)查询和更新
给定的模型可以应用于新文档,以获得新文档TFIDF。例如, New_Corpus_TFIDF = Model_TFIDF [ New_Corpus_BOW ]。但这只是查询。未使用新的语料库/文档更新模型。也就是说,该模型是使用原始语料库建模的,并与新文档一样使用。
当新文档只是一个简短的用户查询并且我们想在原始语料库中找到最相似的文档时,这很有用。或者,当我们只有一个新文档时,我们想在我们的语料库中找到最相似的文档。在这种情况下,如果您的语料库足够大,则无需更新模型。
但是,可以说您的图书馆,您的语料库是鲜活的东西。而且您想用新文档来更新模型,就像它们从一开始就一样。仅提供新文档即可更新某些模型。例如, models.LsiModel具有用于在LSI模型中包括新语料库的“ add_documents” 方法(因此,如果您是用Corpus_BOW构建的,则只需更新即可提供New_Corpus_BOW)。
但是 TFIDF模型还没有这种“ add_documents”方法。我不知道是否有复杂且智能的数学方法可以克服这一问题,但事实是,TFIDF的“ IDF”部分取决于完整的语料库(先前的和新的)。因此,如果添加新文档,则每个先前文档的IDF都会更改。更新TFIDF模型的唯一方法是重新计算它。
无论如何,请考虑即使您可以更新模型,也需要再次将其应用于输入语料库以具有输出语料库,并重建相似性。
正如之前所说,如果您的库足够大,则可以使用原始的TFIDF模型并按原样应用于新文档,而无需更新模型。结果可能足够好。然后,不时地,当新文档的数量很大时,您需要重新构建TFIDF模型。