Python 重新计算给定新文档的相似度矩阵
我正在运行一个实验,其中包括我需要计算所有文本之间的(余弦)相似性矩阵(用于另一个计算)的文本文档。为此,我使用sklearn的: 问题是,在我的实验的每次迭代中,我都会发现需要添加到相似性矩阵中的新文档,而且考虑到我正在处理的文档数量(数万个或更多),这非常耗时 我希望找到一种方法,只计算新一批文档与现有文档之间的相似性,而不需要对整个数据集进行再次计算 请注意,我使用的是术语频率(tf)表示法,而没有使用反向文档频率(idf),因此理论上我不需要每次都重新计算整个矩阵。好的,我知道了。 正如我所说,这个想法是只计算新批文件和现有文件之间的相似性,它们的相似性是不变的。问题是要用新出现的术语更新TFIDFvectorier的词汇表 该解决方案有两个步骤:Python 重新计算给定新文档的相似度矩阵,python,scikit-learn,cosine-similarity,tfidfvectorizer,Python,Scikit Learn,Cosine Similarity,Tfidfvectorizer,我正在运行一个实验,其中包括我需要计算所有文本之间的(余弦)相似性矩阵(用于另一个计算)的文本文档。为此,我使用sklearn的: 问题是,在我的实验的每次迭代中,我都会发现需要添加到相似性矩阵中的新文档,而且考虑到我正在处理的文档数量(数万个或更多),这非常耗时 我希望找到一种方法,只计算新一批文档与现有文档之间的相似性,而不需要对整个数据集进行再次计算 请注意,我使用的是术语频率(tf)表示法,而没有使用反向文档频率(idf),因此理论上我不需要每次都重新计算整个矩阵。好的,我知道了。 正如
corpus = [doc1, doc2, doc3]
# Build for the first time:
vect = TfidfVectorizer(min_df=1, stop_words="english", use_idf=False)
tf_matrix = vect.fit_transform(corpus)
similarities = tf_matrix * tf_matrix.T
similarities_matrix = similarities.A # just for printing
现在,考虑到新的文件:
new_docs_corpus = [docx, docy, docz] # New documents
# Building new vectorizer to create the parsed vocabulary of the new documents:
new_vect = TfidfVectorizer(min_df=1, stop_words="english", use_idf=False)
new_vect.fit(new_docs_corpus)
# Merging old and new vocabs:
new_terms_count = 0
for k, v in new_vect.vocabulary_.items():
if k in vect.vocabulary_.keys():
continue
vect.vocabulary_[k] = np.int64(len(vect.vocabulary_)) # important not to assign a simple int
new_terms_count = new_terms_count + 1
new_vect.vocabulary_ = vect.vocabulary_
# Build new docs represantation using the merged vocabulary:
new_tf_matrix = new_vect.transform(new_docs_corpus)
new_similarities = new_tf_matrix * new_tf_matrix.T
# Get the old tf-matrix with the same dimentions:
if new_terms_count:
zero_matrix = csr_matrix((tfidf.shape[0],new_terms_count))
tf_matrix = hstack([tf_matrix, zero_matrix])
# tf_matrix = vect.transform(corpus) # Instead, we just append 0's for the new terms and stack the tf_matrix over the new one, to save time
cross_similarities = new_tf_matrix * tf_matrix.T # Calculate cross-similarities
tf_matrix = vstack([tf_matrix, new_tfidf])
# Stack it all together:
similarities = vstack([hstack([similarities, cross_similarities.T]), hstack([cross_similarities, new_similarities])])
similarities_matrix = similarities.A
# Updating the corpus with the new documents:
corpus = corpus + new_docs_corpus
我们可以通过比较计算出的相似度矩阵
与我们在联合语料库上训练tfidf向量器
时得到的矩阵来检查这一点:corpus+new\u docs\u corpus
正如评论中所讨论的,我们之所以能够做到这一切,是因为我们没有使用idf(反向文档频率)元素,这将改变给定新文档的现有文档的表示形式。我认为如果您不在每次发现新文档时重新计算,您会遇到一个问题,那就是您的TfidfVectorizer,有了它,这些文档中的生词就不适合使用词汇表了。这可能意味着,即使您向其中添加了一个新文档,其中的大部分可能都不可用,如果TfidfVectorizer没有使用其中的单词调整其词汇表。@KimTang这是问题的一部分-我希望将新术语添加到相同的termsXdocs矩阵中,然后再将其与自身相乘以获得新的docsXdocs相似性矩阵。@KimTang对于这一部分,我看到了这个问题的答案,并使用了“部分拟合”的相关部分我可以用新出现的术语更新词汇表,但这对我的相似性矩阵部分没有帮助:@KimTang我刚刚发布了一个解决这部分问题的答案-你可以查看它谢谢更新!我现在也删除了我的答案。
new_docs_corpus = [docx, docy, docz] # New documents
# Building new vectorizer to create the parsed vocabulary of the new documents:
new_vect = TfidfVectorizer(min_df=1, stop_words="english", use_idf=False)
new_vect.fit(new_docs_corpus)
# Merging old and new vocabs:
new_terms_count = 0
for k, v in new_vect.vocabulary_.items():
if k in vect.vocabulary_.keys():
continue
vect.vocabulary_[k] = np.int64(len(vect.vocabulary_)) # important not to assign a simple int
new_terms_count = new_terms_count + 1
new_vect.vocabulary_ = vect.vocabulary_
# Build new docs represantation using the merged vocabulary:
new_tf_matrix = new_vect.transform(new_docs_corpus)
new_similarities = new_tf_matrix * new_tf_matrix.T
# Get the old tf-matrix with the same dimentions:
if new_terms_count:
zero_matrix = csr_matrix((tfidf.shape[0],new_terms_count))
tf_matrix = hstack([tf_matrix, zero_matrix])
# tf_matrix = vect.transform(corpus) # Instead, we just append 0's for the new terms and stack the tf_matrix over the new one, to save time
cross_similarities = new_tf_matrix * tf_matrix.T # Calculate cross-similarities
tf_matrix = vstack([tf_matrix, new_tfidf])
# Stack it all together:
similarities = vstack([hstack([similarities, cross_similarities.T]), hstack([cross_similarities, new_similarities])])
similarities_matrix = similarities.A
# Updating the corpus with the new documents:
corpus = corpus + new_docs_corpus