web-dev-qa-db-fra.com

En utilisant sklearn, comment puis-je calculer la similitude cosinus tf-idf entre des documents et une requête?

Mon objectif est de saisir 3 requêtes et de découvrir quelle requête est la plus similaire à un ensemble de 5 documents.

Jusqu'à présent, j'ai calculé le tf-idf des documents faisant ce qui suit:

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)

Le problème que j'ai, c'est maintenant que j'ai tf-idf des documents quelles opérations dois-je effectuer sur la requête afin de trouver la similitude cosinus avec les documents?

6
OultimoCoder

La similitude en cosinus est le cosinus de l'angle entre les vecteurs qui représentent les documents.

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

Votre matrice tf-idf sera une matrice clairsemée avec des dimensions = non. de documents * no. de mots distincts.

Pour imprimer la matrice entière, vous pouvez utiliser todense()

print(tfidf.todense())

Chaque ligne représente la représentation vectorielle correspondant à un document. De la même manière, chaque colonne correspond au score tf-idf d'un mot unique dans le corpus.

Entre un vecteur et tout autre vecteur, la similitude par paire peut être calculée à partir de votre matrice tf-idf comme:

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

La sortie sera un tableau de longueur = non. de documents indiquant le score de similitude entre votre vecteur de référence et le vecteur correspondant à chaque document. Bien sûr, la similitude entre le vecteur de référence et lui-même sera de 1. Globalement, ce sera une valeur entre 0 et 1.

Pour trouver la similitude entre les premier et deuxième documents,

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

array([[0.36651513]])
1
Nihal Sangeeth

Les autres réponses étaient très utiles mais pas tout à fait ce que je cherchais car elles ne m'ont pas aidé à transformer ma requête afin que je puisse la comparer avec les documents.

Pour transformer la requête, je l'adapte d'abord à la matrice du document:

queryTFIDF = TfidfVectorizer().fit(allDocs)

Je le transforme ensuite en forme matricielle:

queryTFIDF = queryTFIDF.transform([query])

Et puis il suffit de calculer la similitude cosinus entre tous les documents et ma requête en utilisant la fonction sklearn.metrics.pairwise.cosine_similarity

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

Bien que je réalise qu'en utilisant la solution de Nihal, j'ai pu saisir ma requête comme l'un des documents et ensuite calculer la similitude entre celle-ci et les autres documents, mais c'est ce qui a le mieux fonctionné pour moi.

Le code complet finit par ressembler à:

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
1
OultimoCoder

Vous pouvez faire comme Nihal l'a écrit dans sa réponse ou vous pouvez utiliser les voisins les plus proches algo de sklearn. Vous devez sélectionner la métrique appropriée (cosinus)

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