我有一个非常大的数据集,本质上是文档 - 搜索查询对,我想计算每对的相似性。我已经计算了每个文档和查询的 TF-IDF。我意识到给定两个向量,您可以使用linear_kernel计算相似性。但是,我不确定如何在非常大的数据集上执行此操作(即没有 for 循环(。
这是我到目前为止所拥有的:
import numpy as np
import pandas as pd
from sklearn.feature_extraction.text import TfidfVectorizer
from sklearn.metrics.pairwise import linear_kernel
df_train = pd.read_csv('train.csv')
vectorizer = TfidfVectorizer()
doc_tfidf = vectorizer.fit_transform(df_train["document"])
query_tfidf = vectorizer.transform(df_train["query"])
linear_kernel(doc_tfidf, query_tfidf)
现在这给了我一个 NxN 矩阵,其中 N 是我拥有的文档查询对的数量。我正在寻找的是 N 大小的向量,每个文档查询对都有一个值。
我意识到我可以用 for 循环来做到这一点,但对于大约 500K 对的数据集,这是行不通的。有什么方法可以矢量化这个计算吗?
更新:所以我认为我有一个有效的解决方案,而且似乎很快。在上面的代码中,我替换了:
linear_kernel(doc_tfidf, query_tfidf)
跟
df_train['similarity'] = desc_tfidf.multiply(query_tfidf).sum(axis=1)
这似乎是一种理智的方法吗?有没有更好的方法可以做到这一点?
余弦相似性通常用于计算文本文档之间的相似性,这在scikit-learn中是在sklearn.metrics.pairwise.cosine_similarity
中实现的。
但是,由于默认情况下TfidfVectorizer
还对结果执行 L2 规范化(即 norm='l2'
(,在这种情况下,计算点积以获得余弦相似性就足够了。
因此,在您的示例中,您应该使用
similarity = doc_tfidf.dot(query_tfidf.T).T
而不是逐元素乘法。