Prima di tutto, se desideri estrarre le funzionalità di conteggio e applicare la normalizzazione TF-IDF e la normalizzazione euclidea per riga, puoi farlo in un'unica operazione con 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>
Ora per trovare le distanze del coseno di un documento (ad es. Il primo nel set di dati) e di tutti gli altri è sufficiente calcolare i prodotti puntiformi del primo vettore con tutti gli altri poiché i vettori tfidf sono già normalizzati per riga.
Come spiegato da Chris Clark nei commenti e qui, la somiglianza del coseno non tiene conto della grandezza dei vettori. Le righe normalizzate hanno magnitudo 1 e quindi il kernel lineare è sufficiente per calcolare i valori di similarità.
L'API scipy sparse matrix è un po 'strana (non flessibile come gli array numpy N-dimensionali densi). Per ottenere il primo vettore devi tagliare la matrice per riga per ottenere una sottomatrice con una singola riga:
>>> tfidf[0:1]
<1x130088 sparse matrix of type '<type 'numpy.float64'>'
with 89 stored elements in Compressed Sparse Row format>
scikit-learn fornisce già metriche a coppie (note anche come kernel nel linguaggio del machine learning) che funzionano per rappresentazioni sia dense che sparse di raccolte di vettori. In questo caso abbiamo bisogno di un prodotto puntuale noto anche come kernel lineare:
>>> 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])
Quindi, per trovare i primi 5 documenti correlati, possiamo usare argsort
e alcune sezioni di array negative (la maggior parte dei documenti correlati ha valori di somiglianza del coseno più alti, quindi alla fine dell'array degli indici ordinati):
>>> 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 ])
Il primo risultato è un controllo di integrità: troviamo il documento di query come il documento più simile con un punteggio di somiglianza del coseno di 1 che ha il seguente testo:
>>> 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 ----
Il secondo documento più simile è una risposta che cita il messaggio originale, quindi ha molte parole comuni:
>>> 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