使用 sklearn 如何计算文档和查询之间的 tf-idf 余弦相似度?

Posted

技术标签:

【中文标题】使用 sklearn 如何计算文档和查询之间的 tf-idf 余弦相似度?【英文标题】:Using sklearn how do I calculate the tf-idf cosine similarity between documents and a query? 【发布时间】:2019-09-04 17:38:29 【问题描述】:

我的目标是输入 3 个查询并找出哪个查询与一组 5 个文档最相似。

到目前为止,我已经计算了文档的tf-idf,执行以下操作:

from sklearn.feature_extraction.text import TfidfVectorizer

def get_term_frequency_inverse_data_frequency(documents):
    allDocs = []
    for document in documents:
        allDocs.append(nlp.clean_tf_idf_text(document))
    vectorizer = TfidfVectorizer()
    matrix = vectorizer.fit_transform(allDocs)
    return matrix

def get_tf_idf_query_similarity(documents, query):
    tfidf = get_term_frequency_inverse_data_frequency(documents)

我现在遇到的问题是我有tf-idf 的文档,我对查询执行什么操作,以便找到与文档的余弦相似度?

【问题讨论】:

【参考方案1】:

这是我的建议:

我们不必两次拟合模型。我们可以重复使用相同的矢量化器 文本清理功能可以直接使用preprocessing属性插入TfidfVectorizer
from sklearn.feature_extraction.text import TfidfVectorizer
from sklearn.metrics.pairwise import cosine_similarity

vectorizer = TfidfVectorizer(preprocessor=nlp.clean_tf_idf_text)
docs_tfidf = vectorizer.fit_transform(allDocs)

def get_tf_idf_query_similarity(vectorizer, docs_tfidf, query):
    """
    vectorizer: TfIdfVectorizer model
    docs_tfidf: tfidf vectors for all docs
    query: query doc

    return: cosine similarity between query and all docs
    """
    query_tfidf = vectorizer.transform([query])
    cosineSimilarities = cosine_similarity(query_tfidf, docs_tfidf).flatten()
    return cosineSimilarities

【讨论】:

感谢您的回答。这让我睡了一夜好觉!【参考方案2】:

其他答案非常有帮助,但并不完全是我想要的,因为它们没有帮助我转换我的查询,因此我可以将它与文档进行比较。

为了转换查询,我首先将其拟合到文档矩阵:

queryTFIDF = TfidfVectorizer().fit(allDocs)

然后我把它转换成矩阵形状:

queryTFIDF = queryTFIDF.transform([query])

然后使用 sklearn.metrics.pairwise.cosine_similarity 函数计算所有文档和我的查询之间的余弦相似度

cosineSimilarities = cosine_similarity(queryTFIDF, docTFIDF).flatten()

虽然我意识到使用 Nihal 的解决方案,我可以将我的查询作为文档之一输入,然后计算它与其他文档之间的相似度,但这对我来说最有效。

完整的代码最终看起来像:

from sklearn.feature_extraction.text import TfidfVectorizer
from sklearn.metrics.pairwise import cosine_similarity

def get_tf_idf_query_similarity(documents, query):
    allDocs = []
    for document in documents:
        allDocs.append(nlp.clean_tf_idf_text(document))
    docTFIDF = TfidfVectorizer().fit_transform(allDocs)
    queryTFIDF = TfidfVectorizer().fit(allDocs)
    queryTFIDF = queryTFIDF.transform([query])

    cosineSimilarities = cosine_similarity(queryTFIDF, docTFIDF).flatten()
    return cosineSimilarities

【讨论】:

我必须在一个列表上做余弦相似度并找出哪些元素与查询的相似度最大。我的解决方案在普通 python 中工作,但@OultimoCoder 的基于 sklearn 的解决方案工作得很好 如果我将此与@Venkatachalam 的答案进行比较,则 queryTFIDF = TfidfVectorizer().fit(allDocs) 步骤的区别。这一步的目的是什么? 这里的 nlp 是什么,我收到错误,因为 - name 'nlp' is not defined【参考方案3】:

余弦相似度是表示文档的向量之间夹角的余弦。

K(X, Y) = <X, Y> / (||X||*||Y||)

您的 tf-idf 矩阵将是一个稀疏矩阵,其维度 = 否。文件 * 没有。不同的词。

要打印整个矩阵,您可以使用todense()

print(tfidf.todense())

每一行代表一个文档对应的向量表示。同样,每一列对应于语料库中唯一词的 tf-idf 分数。

在一个向量和任何其他向量之间,成对相似度可以从您的 tf-idf 矩阵计算为:

from sklearn.metrics.pairwise import cosine_similarity
cosine_similarity(reference_vector, tfidf_matrix) 

输出将是一个长度 = 否的数组。表示您的参考向量和每个文档对应的向量之间的相似度分数的文档。当然,参考向量与自身的相似度为 1。总体而言,它将是一个介于 0 和 1 之间的值。

要查找第一个和第二个文档之间的相似性,

print(cosine_similarity(tfidf_matrix[0], tfidf_matrix[1]))

array([[0.36651513]])

【讨论】:

【参考方案4】:

你可以按照 Nihal 在他的回复中写的那样做,或者你可以使用 sklearn 的最近邻算法。您必须选择适当的度量(余弦)

from sklearn.neighbors import NearestNeighbors
neigh = NearestNeighbors(n_neighbors=5, metric='cosine')

【讨论】:

以上是关于使用 sklearn 如何计算文档和查询之间的 tf-idf 余弦相似度?的主要内容,如果未能解决你的问题,请参考以下文章

sklearn : TFIDF Transformer : 如何获取文档中给定单词的 tf-idf 值

python:使用sklearn在文档聚类中面临内存问题

如何使用 sklearn.metrics 计算多标签分类任务的微观/宏观度量?

python如何配对样本

在 python 中的 sklearn 中绘制 DBSCAN 中的特定点

如何分析sklearn中tfidf矩阵的值?