Je suivais un tutoriel qui était disponible dans les parties 1 et 2 . Malheureusement, l'auteur n'a pas eu le temps pour la dernière section qui impliquait d'utiliser la similitude cosinus pour trouver réellement la distance entre deux documents. J'ai suivi les exemples de l'article à l'aide du lien suivant de stackoverflow , inclus le code mentionné dans le lien ci-dessus (juste pour vous faciliter la vie)
from sklearn.feature_extraction.text import CountVectorizer
from sklearn.feature_extraction.text import TfidfTransformer
from nltk.corpus import stopwords
import numpy as np
import numpy.linalg as LA
train_set = ["The sky is blue.", "The sun is bright."] # Documents
test_set = ["The sun in the sky is bright."] # Query
stopWords = stopwords.words('english')
vectorizer = CountVectorizer(stop_words = stopWords)
#print vectorizer
transformer = TfidfTransformer()
#print transformer
trainVectorizerArray = vectorizer.fit_transform(train_set).toarray()
testVectorizerArray = vectorizer.transform(test_set).toarray()
print 'Fit Vectorizer to train set', trainVectorizerArray
print 'Transform Vectorizer to test set', testVectorizerArray
transformer.fit(trainVectorizerArray)
print
print transformer.transform(trainVectorizerArray).toarray()
transformer.fit(testVectorizerArray)
print
tfidf = transformer.transform(testVectorizerArray)
print tfidf.todense()
à la suite du code ci-dessus, j'ai la matrice suivante
Fit Vectorizer to train set [[1 0 1 0]
[0 1 0 1]]
Transform Vectorizer to test set [[0 1 1 1]]
[[ 0.70710678 0. 0.70710678 0. ]
[ 0. 0.70710678 0. 0.70710678]]
[[ 0. 0.57735027 0.57735027 0.57735027]]
Je ne sais pas comment utiliser cette sortie pour calculer la similitude cosinus, je sais comment implémenter la similitude cosinus par rapport à deux vecteurs de longueur similaire mais ici je ne sais pas comment identifier les deux vecteurs.
python
machine-learning
nltk
information-retrieval
tf-idf
ajouter des points-virgules
la source
la source
Réponses:
Tout d'abord, si vous souhaitez extraire des fonctionnalités de comptage et appliquer la normalisation TF-IDF et la normalisation euclidienne par ligne, vous pouvez le faire en une seule opération avec
TfidfVectorizer
:Maintenant, pour trouver les distances cosinus d'un document (par exemple le premier du jeu de données) et de tous les autres, il vous suffit de calculer les produits scalaires du premier vecteur avec tous les autres car les vecteurs tfidf sont déjà normalisés en ligne.
Comme l'explique Chris Clark dans les commentaires et ici , la similarité cosinus ne prend pas en compte l'ampleur des vecteurs. Les lignes normalisées ont une magnitude de 1 et le noyau linéaire est donc suffisant pour calculer les valeurs de similarité.
L'API de matrice clairsemée scipy est un peu bizarre (pas aussi flexible que les tableaux numpy denses à N dimensions). Pour obtenir le premier vecteur, vous devez découper la matrice par ligne pour obtenir une sous-matrice avec une seule ligne:
scikit-learn fournit déjà des métriques par paires (alias noyaux dans le langage de l'apprentissage automatique) qui fonctionnent à la fois pour les représentations denses et éparses des collections vectorielles. Dans ce cas, nous avons besoin d'un produit scalaire également connu sous le nom de noyau linéaire:
Par conséquent, pour trouver les 5 principaux documents connexes, nous pouvons utiliser
argsort
un découpage de tableau négatif (la plupart des documents associés ont les valeurs de similitude cosinus les plus élevées, donc à la fin du tableau d'indices triés):Le premier résultat est un contrôle de cohérence: nous trouvons le document de requête comme le document le plus similaire avec un score de similarité cosinus de 1 qui contient le texte suivant:
Le deuxième document le plus similaire est une réponse qui cite le message d'origine et contient donc de nombreux mots communs:
la source
cosine_similarities = linear_kernel(tfidf, tfidf)
:?Avec l'aide du commentaire de @ excray, je parviens à trouver la réponse, ce que nous devons faire est en fait d'écrire une simple boucle for pour itérer sur les deux tableaux qui représentent les données de train et les données de test.
Commencez par implémenter une fonction lambda simple pour contenir la formule du calcul du cosinus:
Et puis il suffit d'écrire une simple boucle for à itérer sur le vecteur to, la logique est pour chaque "Pour chaque vecteur dans trainVectorizerArray, vous devez trouver la similitude cosinus avec le vecteur dans testVectorizerArray."
Voici la sortie:
la source
transformer.fit
opérations ettfidf.todense()
? Vous avez obtenu vos valeurs de similarité de la boucle et continuez à faire tfidf? Où votre valeur cosinus calculée est-elle utilisée? Votre exemple est déroutant.0.408
et0.816
quelles sont ces valeurs?Je sais que c'est un vieux post. mais j'ai essayé le package http://scikit-learn.sourceforge.net/stable/ . voici mon code pour trouver la similitude cosinus. La question était de savoir comment calculerez-vous la similitude cosinus avec ce package et voici mon code pour cela
Supposons ici que la requête soit le premier élément de train_set et doc1, doc2 et doc3 sont les documents que je souhaite classer à l'aide de la similarité cosinus. alors je peux utiliser ce code.
Les didacticiels fournis dans la question ont également été très utiles. Voici toutes les pièces pour cela partie-I , partie-II , partie-III
la sortie sera la suivante:
ici 1 représente que la requête est mise en correspondance avec elle-même et les trois autres sont les scores de correspondance de la requête avec les documents respectifs.
la source
ValueError: Incompatible dimension for X and Y matrices: X.shape[1] == 1664 while Y.shape[1] == 2
Laissez-moi vous donner un autre tutoriel écrit par moi. Cela répond à votre question, mais explique également pourquoi nous faisons certaines choses. J'ai également essayé de le rendre concis.
Donc, vous avez un
list_of_documents
qui est juste un tableau de chaînes et un autredocument
qui n'est qu'une chaîne. Vous devez trouver un tel document à partir dulist_of_documents
qui est le plus similaire àdocument
.Combinons-les ensemble:
documents = list_of_documents + [document]
Commençons par les dépendances. Il deviendra clair pourquoi nous utilisons chacun d'eux.
L'une des approches qui peuvent être utilisées est une approche du sac de mots , où nous traitons chaque mot du document indépendamment des autres et les jetons tous ensemble dans le grand sac. D'un certain point de vue, cela perd beaucoup d'informations (comme la façon dont les mots sont connectés), mais d'un autre point de vue, cela simplifie le modèle.
En anglais et dans n'importe quelle autre langue humaine, il y a beaucoup de mots "inutiles" comme "a", "le", "dans" qui sont si courants qu'ils n'ont pas beaucoup de sens. Ils sont appelés mots vides et c'est une bonne idée de les supprimer. Une autre chose que l'on peut remarquer est que des mots comme «analyser», «analyseur», «analyse» sont vraiment similaires. Ils ont une racine commune et tous peuvent être convertis en un seul mot. Ce processus s'appelle la tige et il existe différents types de tige qui diffèrent par leur vitesse, leur agressivité, etc. Nous transformons donc chacun des documents en liste de tiges de mots sans mots vides. Nous supprimons également toute la ponctuation.
Alors, comment ce sac de mots nous aidera-t-il? Imaginez que nous avons 3 sacs:
[a, b, c]
,[a, c, a]
et[b, c, d]
. Nous pouvons les convertir en vecteurs dans la base[a, b, c, d]
. Donc , nous nous retrouvons avec des vecteurs:[1, 1, 1, 0]
,[2, 0, 1, 0]
et[0, 1, 1, 1]
. La même chose est avec nos documents (seuls les vecteurs seront beaucoup plus longs). Maintenant, nous voyons que nous avons supprimé beaucoup de mots et en a extrait d'autres également pour diminuer les dimensions des vecteurs. Ici, il y a juste une observation intéressante. Les documents plus longs auront beaucoup plus d'éléments positifs que les plus courts, c'est pourquoi il est agréable de normaliser le vecteur. C'est ce qu'on appelle le terme fréquence TF, les gens ont également utilisé des informations supplémentaires sur la fréquence à laquelle le mot est utilisé dans d'autres documents - fréquence IDF inverse du document. Ensemble, nous avons une métrique TF-IDF qui a quelques saveurs. Ceci peut être réalisé avec une ligne dans sklearn :-)En fait, vectorizer permet de faire beaucoup de choses comme supprimer les mots vides et les minuscules. Je les ai fait dans une étape séparée seulement parce que sklearn n'a pas de mots vides non anglais, mais nltk a.
Nous avons donc tous les vecteurs calculés. La dernière étape consiste à trouver lequel est le plus similaire au dernier. Il existe différentes manières d'y parvenir, l'une d'entre elles est la distance euclidienne qui n'est pas si grande pour la raison évoquée ici . Une autre approche est la similitude cosinus . Nous itérons tous les documents et calculons la similitude cosinus entre le document et le dernier:
Maintenant, minimum aura des informations sur le meilleur document et son score.
la source
Cela devrait vous aider.
et la sortie sera:
la source
Voici une fonction qui compare vos données de test aux données de formation, avec le transformateur Tf-Idf équipé des données de formation. L'avantage est que vous pouvez rapidement pivoter ou regrouper pour trouver les n éléments les plus proches, et que les calculs sont descendants par matrice.
la source