Ich folgte einem Tutorial, das in Teil 1 und Teil 2 verfügbar war . Leider hatte der Autor nicht die Zeit für den letzten Abschnitt, in dem die Kosinusähnlichkeit verwendet wurde, um den Abstand zwischen zwei Dokumenten tatsächlich zu ermitteln. Ich habe die Beispiele im Artikel mit Hilfe des folgenden Links von stackoverflow befolgt , einschließlich des im obigen Link erwähnten Codes (nur um das Leben einfacher zu machen).
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()
Aufgrund des obigen Codes habe ich die folgende Matrix
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]]
Ich bin nicht sicher, wie ich diese Ausgabe verwenden soll, um die Kosinusähnlichkeit zu berechnen. Ich weiß, wie man die Kosinusähnlichkeit in Bezug auf zwei Vektoren ähnlicher Länge implementiert, aber hier bin ich nicht sicher, wie ich die beiden Vektoren identifizieren soll.
quelle
Antworten:
Wenn Sie zunächst Zählfunktionen extrahieren und die TF-IDF-Normalisierung und die zeilenweise euklidische Normalisierung anwenden möchten, können Sie dies in einem Arbeitsgang tun mit
TfidfVectorizer
:Um nun die Kosinusabstände eines Dokuments (z. B. des ersten im Datensatz) und aller anderen Dokumente zu ermitteln, müssen Sie nur die Punktprodukte des ersten Vektors mit allen anderen berechnen, da die tfidf-Vektoren bereits zeilennormalisiert sind.
Wie von Chris Clark in den Kommentaren und hier erklärt erklärt, berücksichtigt die Cosinus-Ähnlichkeit nicht die Größe der Vektoren. Zeilennormalisierte haben eine Größe von 1 und daher reicht der lineare Kernel aus, um die Ähnlichkeitswerte zu berechnen.
Die Scipy-Sparse-Matrix-API ist etwas seltsam (nicht so flexibel wie dichte N-dimensionale Numpy-Arrays). Um den ersten Vektor zu erhalten, müssen Sie die Matrix zeilenweise aufteilen, um eine Submatrix mit einer einzelnen Zeile zu erhalten:
scikit-learn bietet bereits paarweise Metriken (auch bekannt als Kernel in der Sprache des maschinellen Lernens), die sowohl für dichte als auch für spärliche Darstellungen von Vektorsammlungen funktionieren. In diesem Fall benötigen wir ein Punktprodukt, das auch als linearer Kernel bezeichnet wird:
Um die Top 5 verwandten Dokumente zu finden, können wir daher
argsort
ein negatives Array-Slicing verwenden (die meisten verwandten Dokumente haben die höchsten Kosinus-Ähnlichkeitswerte, daher am Ende des Arrays mit sortierten Indizes):Das erste Ergebnis ist eine Überprüfung der Integrität: Wir finden das Abfragedokument als das ähnlichste Dokument mit einer Kosinus-Ähnlichkeitsbewertung von 1, die den folgenden Text enthält:
Das zweitähnlichste Dokument ist eine Antwort, die die ursprüngliche Nachricht zitiert und daher viele gebräuchliche Wörter enthält:
quelle
cosine_similarities = linear_kernel(tfidf, tfidf)
?Mit Hilfe des Kommentars von @ excray gelingt es mir, die Antwort herauszufinden: Wir müssen tatsächlich eine einfache for-Schleife schreiben, um über die beiden Arrays zu iterieren, die die Zugdaten und Testdaten darstellen.
Implementieren Sie zunächst eine einfache Lambda-Funktion, um die Formel für die Kosinusberechnung zu speichern:
Und dann schreiben Sie einfach eine einfache for-Schleife, um über den to-Vektor zu iterieren. Die Logik gilt für jeden "Für jeden Vektor in trainVectorizerArray müssen Sie die Cosinus-Ähnlichkeit mit dem Vektor in testVectorizerArray finden."
Hier ist die Ausgabe:
quelle
transformer.fit
Operationen undtfidf.todense()
? Sie haben Ihre Ähnlichkeitswerte aus der Schleife erhalten und fahren dann mit tfidf fort? Wo wird Ihr berechneter Kosinuswert verwendet? Ihr Beispiel ist verwirrend.0.408
und0.816
, was sind diese Werte?Ich weiß, es ist ein alter Beitrag. Ich habe jedoch das Paket http://scikit-learn.sourceforge.net/stable/ ausprobiert . Hier ist mein Code, um die Kosinusähnlichkeit zu finden. Die Frage war, wie Sie die Kosinusähnlichkeit mit diesem Paket berechnen und hier ist mein Code dafür
Angenommen, die Abfrage ist das erste Element von train_set und doc1, doc2 und doc3 sind die Dokumente, die ich mithilfe der Kosinusähnlichkeit bewerten möchte. dann kann ich diesen Code verwenden.
Auch die in der Frage bereitgestellten Tutorials waren sehr nützlich. Hier sind alle Teile dafür Teil I , Teil II , Teil III
Die Ausgabe wird wie folgt sein:
Hier stellt 1 dar, dass die Abfrage mit sich selbst übereinstimmt, und die anderen drei sind die Bewertungen für die Zuordnung der Abfrage zu den jeweiligen Dokumenten.
quelle
ValueError: Incompatible dimension for X and Y matrices: X.shape[1] == 1664 while Y.shape[1] == 2
Lassen Sie mich Ihnen ein weiteres von mir geschriebenes Tutorial geben. Es beantwortet Ihre Frage, erklärt aber auch, warum wir einige der Dinge tun. Ich habe auch versucht, es kurz zu machen.
Sie haben also eine,
list_of_documents
die nur ein Array von Zeichenfolgen ist, und eine andere,document
die nur eine Zeichenfolge ist. Sie müssen ein solches Dokument aus dem Dokument findenlist_of_documents
, das dem am ähnlichsten istdocument
.Kombinieren wir sie miteinander:
documents = list_of_documents + [document]
Beginnen wir mit Abhängigkeiten. Es wird klar, warum wir jeden von ihnen verwenden.
Einer der Ansätze, die verwendet werden können, ist eine Tüte mit Wörtern Word Ansatz, bei dem wir jedes Wort im Dokument unabhängig von anderen behandeln und alle zusammen in die große Tasche werfen. Unter einem Gesichtspunkt verliert es viele Informationen (wie zum Beispiel, wie die Wörter verbunden sind), aber unter einem anderen Gesichtspunkt macht es das Modell einfach.
Im Englischen und in jeder anderen menschlichen Sprache gibt es viele "nutzlose" Wörter wie "a", "the", "in", die so häufig vorkommen, dass sie nicht viel Bedeutung haben. Sie werden Stoppwörter genannt und es ist eine gute Idee, sie zu entfernen. Eine andere Sache, die man bemerken kann, ist, dass Wörter wie "analysieren", "Analysator", "Analyse" wirklich ähnlich sind. Sie haben eine gemeinsame Wurzel und alle können in nur ein Wort umgewandelt werden. Dieser Prozess wird als Stemming bezeichnet und es gibt verschiedene Stemmers, die sich in Geschwindigkeit, Aggressivität usw. unterscheiden. Also transformieren wir jedes der Dokumente in eine Liste von Wortstämmen ohne Stoppwörter. Außerdem verwerfen wir alle Satzzeichen.
Wie hilft uns diese Wortsammlung? Stellen Sie sich vor wir 3 Taschen haben:
[a, b, c]
,[a, c, a]
und[b, c, d]
. Wir können sie in der Basis in Vektoren umwandeln[a, b, c, d]
. Also haben wir mit Vektoren am Ende:[1, 1, 1, 0]
,[2, 0, 1, 0]
und[0, 1, 1, 1]
. Ähnliches gilt für unsere Dokumente (nur die Vektoren werden viel zu lang sein). Jetzt sehen wir, dass wir viele Wörter entfernt und andere gestemmt haben, um auch die Dimensionen der Vektoren zu verringern. Hier gibt es nur interessante Beobachtungen. Längere Dokumente enthalten weitaus mehr positive Elemente als kürzere. Deshalb ist es hilfreich, den Vektor zu normalisieren. Dies wird als Häufigkeit TF bezeichnet. Die Benutzer verwendeten auch zusätzliche Informationen darüber, wie oft das Wort in anderen Dokumenten verwendet wird - inverse Dokumenthäufigkeit IDF. Zusammen haben wir eine metrische TF-IDF, die einige Geschmacksrichtungen hat. Dies kann mit einer Zeile in sklearn erreicht werden :-)Tatsächlich ermöglicht der Vektorisierer viele Dinge wie das Entfernen von Stoppwörtern und das Verkleinern. Ich habe sie nur in einem separaten Schritt ausgeführt, da sklearn keine nicht englischen Stoppwörter hat, nltk jedoch.
Wir haben also alle Vektoren berechnet. Der letzte Schritt besteht darin, herauszufinden, welcher dem letzten am ähnlichsten ist. Es gibt verschiedene Möglichkeiten, dies zu erreichen. Eine davon ist die euklidische Distanz, die aus dem hier diskutierten Grund nicht so groß ist . Ein anderer Ansatz ist die Kosinusähnlichkeit . Wir iterieren alle Dokumente und berechnen die Kosinusähnlichkeit zwischen dem Dokument und dem letzten:
Jetzt enthält Minimum Informationen über das beste Dokument und seine Punktzahl.
quelle
Dies sollte Ihnen helfen.
und Ausgabe wird sein:
quelle
Hier ist eine Funktion, die Ihre Testdaten mit den Trainingsdaten vergleicht, wobei der Tf-Idf-Transformator mit den Trainingsdaten ausgestattet ist. Der Vorteil ist, dass Sie schnell schwenken oder gruppieren können, um die n nächstgelegenen Elemente zu finden, und dass die Berechnungen in Bezug auf die Matrix nach unten erfolgen.
quelle