Was ist der Unterschied zwischen einem Hashing-Vektorisierer und einem tfidf-Vektorisierer?

11

Ich konvertiere für jedes Dokument einen Korpus von Textdokumenten in Wortvektoren. Ich habe dies mit einem TfidfVectorizer und einem HashingVectorizer versucht

Ich verstehe, dass a HashingVectorizerdie IDFPunktzahlen nicht wie a TfidfVectorizerberücksichtigt. Der Grund, warum ich immer noch mit a arbeite, HashingVectorizerist die Flexibilität, die es beim Umgang mit riesigen Datensätzen bietet, wie hier und hier erläutert . (Mein ursprünglicher Datensatz enthält 30 Millionen Dokumente.)

Derzeit arbeite ich mit einem Beispiel von 45339 Dokumenten, sodass ich auch mit einem arbeiten kann TfidfVectorizer. Wenn ich diese beiden Vektorisierer für dieselben 45339-Dokumente verwende, sind die Matrizen, die ich erhalte, unterschiedlich.

hashing = HashingVectorizer()
with LSM('corpus.db')) as corpus:
    hashing_matrix = hashing.fit_transform(corpus)
print(hashing_matrix.shape) 

Hashing-Matrixform (45339, 1048576)

tfidf = TfidfVectorizer()
with LSM('corpus.db')) as corpus:
    tfidf_matrix = tfidf.fit_transform(corpus)
print(tfidf_matrix.shape) 

tfidf-Matrixform (45339, 663307)

Ich möchte die Unterschiede zwischen a HashingVectorizerund a besser verstehen TfidfVectorizerund den Grund, warum diese Matrizen unterschiedlich groß sind - insbesondere in Bezug auf die Anzahl der Wörter / Begriffe.

Minu
quelle
Können Sie mir bitte den Datensatz mitteilen? (Antwort entfernt werden)
nKarza

Antworten:

7

Der Hauptunterschied besteht darin, dass HashingVectorizereine Hashing-Funktion auf die Häufigkeit TfidfVectorizervon Begriffen in jedem Dokument angewendet wird , wobei diese Häufigkeit von Begriffen in jedem Dokument skaliert wird, indem Begriffe bestraft werden, die im gesamten Korpus häufiger vorkommen. Hier finden Sie eine großartige Zusammenfassung: https://spark.apache.org/docs/latest/mllib-feature-extraction.html

  • Hash-Funktionen sind eine effiziente Methode zum Zuordnen von Begriffen zu Features. es muss nicht unbedingt nur auf Termfrequenzen angewendet werden, aber so HashingVectorizerwird es hier verwendet. Ich vermute, dass der Merkmalsvektor zusammen mit den 45339-Dokumenten die Länge 1048576 hat, da dies die Standardeinstellung 2 ^ 20 ist n_features. Sie könnten dies reduzieren und die Verarbeitung kostengünstiger gestalten, jedoch mit einem erhöhten Kollisionsrisiko, wenn die Funktion unterschiedliche Begriffe derselben Funktion zuordnet : http://preshing.com/20110504/hash-collision-probabilities/

  • Abhängig vom Anwendungsfall für die Wortvektoren kann es möglich sein, die Länge des Hash-Merkmalsvektors (und damit die Komplexität) signifikant zu reduzieren, wobei ein akzeptabler Verlust an Genauigkeit / Effektivität (aufgrund einer erhöhten Kollision) auftritt. Scikit-learn verfügt über einige Hashing-Parameter, die beispielsweise hilfreich sein können alternate_sign.

  • Wenn die Hashing-Matrix breiter als das Wörterbuch ist, bedeutet dies, dass viele der Spalteneinträge in der Hashing-Matrix leer sind, und zwar nicht nur, weil ein bestimmtes Dokument keinen bestimmten Begriff enthält, sondern weil sie insgesamt leer sind Matrix. Wenn dies nicht der Fall ist, werden möglicherweise mehrere Begriffe an denselben Feature-Hash gesendet - dies ist die "Kollision", über die wir gesprochen haben. HashingVectorizerhat eine Einstellung, die dies mildert und alternate_signstandardmäßig aktiviert ist. Diese wird hier beschrieben: en.wikipedia.org/wiki/Feature_hashing#Properties

  • 'Termhäufigkeit - inverse Dokumenthäufigkeit' verwendet Termhäufigkeiten in jedem Dokument und gewichtet sie, indem Wörter bestraft werden, die im gesamten Korpus häufiger vorkommen. Die Intuition ist, dass situativ gefundene Begriffe eher repräsentativ für das Thema eines bestimmten Dokuments sind. Dies unterscheidet sich von einer Hashing-Funktion darin, dass ein vollständiges Wörterbuch der Wörter im Korpus vorhanden sein muss, um die inverse Dokumenthäufigkeit zu berechnen. Ich gehe davon aus, dass Ihre tf.idf-Matrixdimensionen 45339 Dokumente mit 663307 Wörtern im Korpus sind. Manning et al. Geben weitere Details und Berechnungsbeispiele an: https://nlp.stanford.edu/IR-book/html/htmledition/term-frequency-and-weighting-1.html

'Mining of Massive Datasets' von Leskovec et al. Enthält eine Menge Details zu Feature-Hashing und tf.idf. Die Autoren haben das PDF hier verfügbar gemacht: http://www.mmds.org/

redhqs
quelle
1
Wenn tfidf vectorizerein vollständiges Wörterbuch mit Wörtern für IDF-Berechnungen benötigt wird, sollten die Begriffe in der tfidf-Matrix nicht mehr sein als die Begriffe in der Hashing-Matrix?
Minu
2
Wenn die Hashing-Matrix breiter als das Wörterbuch ist, bedeutet dies, dass viele der Spalteneinträge in der Hashing-Matrix leer sind, und zwar nicht nur, weil ein bestimmtes Dokument keinen bestimmten Begriff enthält, sondern weil sie insgesamt leer sind Matrix. Etwas abseits des Themas, aber bearbeiten Sie die Wörter in Ihren Dokumenten vor dem Vektorisieren? Stoppwörter, Stemming usw.?
Redhqs
Ja, ich verarbeite. Ich benutze Spacy.
Minu
1
Bestätigung: 1048576 ist also die Standardlänge einer Hashing-Matrix, wenn n_features nicht erwähnt wird? Wenn der Korpus wirklich nur 663307 Wörter enthält, sind die verbleibenden 385269 Funktionen leer. Wie kann diese Hashing-Matrix ohne alle leeren Features eng anliegen?
Minu
1
Das ist richtig - Sie können die Anzahl der Features ändern, indem Sie den Parameter ändern. n_features=1048576Wenn Sie Zeit haben, versuchen Sie es mit 640k, 320k und prüfen Sie, ob dies einen großen Einfluss auf Ihre Genauigkeit hat. Es sollte zumindest Ihre Trainingszeit beschleunigen. Siehe @ Nathans Antwort für n_features=5!
Redhqs
5

Das HashingVectorizerhat einen Parameter, n_featuresder 1048576standardmäßig ist. Beim Hashing berechnen sie kein Wörterbuch, das Begriffe einem eindeutigen Index zuordnet, der für jeden Index verwendet werden soll. Stattdessen hashen Sie einfach jeden Begriff und verwenden eine Größe, die groß genug ist, um nicht zu viele Kollisionen zu erwarten : hash(term) mod table_size. Sie können die zurückgegebene Matrix durch Festlegen einer beliebigen Größe anpassen n_features. Sie sollten dies so einstellen, dass es sich im richtigen Bereich für Ihren Korpus befindet, wenn Sie der Meinung sind, dass die Standardeinstellung nicht angemessen ist (wenn sie größer ist, werden weniger Kollisionen verursacht, obwohl mehr Speicher benötigt wird).

from sklearn.feature_extraction.text import HashingVectorizer
vectorizer = HashingVectorizer()
print(vectorizer.transform(['a very small document']).shape)
(1, 1048576)

small_vectorizer = HashingVectorizer(n_features=5)
print(small_vectorizer.transform(['a very small document']).shape)    
(1, 5)
Nathan
quelle