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
:
>>> from sklearn.feature_extraction.text import TfidfVectorizer
>>> from sklearn.datasets import fetch_20newsgroups
>>> twenty = fetch_20newsgroups()
>>> tfidf = TfidfVectorizer().fit_transform(twenty.data)
>>> tfidf
<11314x130088 sparse matrix of type '<type 'numpy.float64'>'
with 1787553 stored elements in Compressed Sparse Row format>
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:
>>> tfidf[0:1]
<1x130088 sparse matrix of type '<type 'numpy.float64'>'
with 89 stored elements in Compressed Sparse Row format>
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:
>>> from sklearn.metrics.pairwise import linear_kernel
>>> cosine_similarities = linear_kernel(tfidf[0:1], tfidf).flatten()
>>> cosine_similarities
array([ 1. , 0.04405952, 0.11016969, ..., 0.04433602,
0.04457106, 0.03293218])
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):
>>> related_docs_indices = cosine_similarities.argsort()[:-5:-1]
>>> related_docs_indices
array([ 0, 958, 10576, 3277])
>>> cosine_similarities[related_docs_indices]
array([ 1. , 0.54967926, 0.32902194, 0.2825788 ])
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:
>>> print twenty.data[0]
From: lerxst@wam.umd.edu (where's my thing)
Subject: WHAT car is this!?
Nntp-Posting-Host: rac3.wam.umd.edu
Organization: University of Maryland, College Park
Lines: 15
I was wondering if anyone out there could enlighten me on this car I saw
the other day. It was a 2-door sports car, looked to be from the late 60s/
early 70s. It was called a Bricklin. The doors were really small. In addition,
the front bumper was separate from the rest of the body. This is
all I know. If anyone can tellme a model name, engine specs, years
of production, where this car is made, history, or whatever info you
have on this funky looking car, please e-mail.
Thanks,
- IL
---- brought to you by your neighborhood Lerxst ----
Le deuxième document le plus similaire est une réponse qui cite le message d'origine et contient donc de nombreux mots communs:
>>> print twenty.data[958]
From: rseymour@reed.edu (Robert Seymour)
Subject: Re: WHAT car is this!?
Article-I.D.: reed.1993Apr21.032905.29286
Reply-To: rseymour@reed.edu
Organization: Reed College, Portland, OR
Lines: 26
In article <1993Apr20.174246.14375@wam.umd.edu> lerxst@wam.umd.edu (where's my
thing) writes:
>
> I was wondering if anyone out there could enlighten me on this car I saw
> the other day. It was a 2-door sports car, looked to be from the late 60s/
> early 70s. It was called a Bricklin. The doors were really small. In
addition,
> the front bumper was separate from the rest of the body. This is
> all I know. If anyone can tellme a model name, engine specs, years
> of production, where this car is made, history, or whatever info you
> have on this funky looking car, please e-mail.
Bricklins were manufactured in the 70s with engines from Ford. They are rather
odd looking with the encased front bumper. There aren't a lot of them around,
but Hemmings (Motor News) ususally has ten or so listed. Basically, they are a
performance Ford with new styling slapped on top.
> ---- brought to you by your neighborhood Lerxst ----
Rush fan?
--
Robert Seymour rseymour@reed.edu
Physics and Philosophy, Reed College (NeXTmail accepted)
Artificial Life Project Reed College
Reed Solar Energy Project (SolTrain) Portland, OR