使用 sklearn 如何计算文档和查询之间的 tf-idf 余弦相似度?
Using sklearn how do I calculate the tf-idf cosine similarity between documents and a query?
我的目标是输入 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
个文档,我对查询执行什么操作才能找到与文档的余弦相似度?
余弦相似度是表示文档的向量之间夹角的余弦值。
K(X, Y) = <X, Y> / (||X||*||Y||)
您的 tf-idf 矩阵将是维度为 no 的稀疏矩阵。文件数量 * 没有。不同的词。
要打印整个矩阵,您可以使用 todense()
print(tfidf.todense())
每一行代表一个文档对应的向量表示。同样,每列对应于语料库中唯一单词的 tf-idf 分数。
向量和任何其他向量之间的成对相似性可以从 tf-idf 矩阵计算为:
from sklearn.metrics.pairwise import cosine_similarity
cosine_similarity(reference_vector, tfidf_matrix)
输出将是一个长度为 no 的数组。文档表示您的参考向量和对应于每个文档的向量之间的相似性得分。当然参考向量和它自己的相似度会是1。总的来说它会是0到1之间的一个值。
要找到第一个和第二个文档之间的相似性,
print(cosine_similarity(tfidf_matrix[0], tfidf_matrix[1]))
array([[0.36651513]])
你可以按照 Nihal 在他的回复中写的那样做,或者你可以使用 sklearn 中的最近邻算法。您必须 select 正确的度量(余弦)
from sklearn.neighbors import NearestNeighbors
neigh = NearestNeighbors(n_neighbors=5, metric='cosine')
其他答案非常有帮助,但并不完全是我想要的,因为它们没有帮助我转换查询,因此我无法将其与文档进行比较。
为了转换查询,我首先将其拟合到文档矩阵:
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
这是我的建议:
- 我们不必两次拟合模型。我们可以重用相同的矢量器
- 文本清理功能可以直接使用
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
我的目标是输入 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
个文档,我对查询执行什么操作才能找到与文档的余弦相似度?
余弦相似度是表示文档的向量之间夹角的余弦值。
K(X, Y) = <X, Y> / (||X||*||Y||)
您的 tf-idf 矩阵将是维度为 no 的稀疏矩阵。文件数量 * 没有。不同的词。
要打印整个矩阵,您可以使用 todense()
print(tfidf.todense())
每一行代表一个文档对应的向量表示。同样,每列对应于语料库中唯一单词的 tf-idf 分数。
向量和任何其他向量之间的成对相似性可以从 tf-idf 矩阵计算为:
from sklearn.metrics.pairwise import cosine_similarity
cosine_similarity(reference_vector, tfidf_matrix)
输出将是一个长度为 no 的数组。文档表示您的参考向量和对应于每个文档的向量之间的相似性得分。当然参考向量和它自己的相似度会是1。总的来说它会是0到1之间的一个值。
要找到第一个和第二个文档之间的相似性,
print(cosine_similarity(tfidf_matrix[0], tfidf_matrix[1]))
array([[0.36651513]])
你可以按照 Nihal 在他的回复中写的那样做,或者你可以使用 sklearn 中的最近邻算法。您必须 select 正确的度量(余弦)
from sklearn.neighbors import NearestNeighbors
neigh = NearestNeighbors(n_neighbors=5, metric='cosine')
其他答案非常有帮助,但并不完全是我想要的,因为它们没有帮助我转换查询,因此我无法将其与文档进行比较。
为了转换查询,我首先将其拟合到文档矩阵:
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
这是我的建议:
- 我们不必两次拟合模型。我们可以重用相同的矢量器
- 文本清理功能可以直接使用
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