Qual è la differenza tra un vettore di hashing e un vettore di tfidf


11

Sto convertendo un corpus di documenti di testo in vettori di parole per ogni documento. Ho provato questo usando un TfidfVectorizer e un HashingVectorizer

Capisco che a HashingVectorizernon prende in considerazione i IDFpunteggi come TfidfVectorizerfa. Il motivo per cui sto ancora lavorando con a HashingVectorizerè la flessibilità che offre durante la gestione di enormi set di dati, come spiegato qui e qui . (Il mio set di dati originale ha 30 milioni di documenti)

Attualmente sto lavorando con un campione di 45339 documenti, quindi ho la possibilità di lavorare anche con un TfidfVectorizer. Quando uso questi due vettorizzatori sugli stessi 45339 documenti, le matrici che ottengo sono diverse.

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

forma della matrice di hashing (45339, 1048576)

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

tfidf matrix shape (45339, 663307)

Voglio capire meglio le differenze tra a HashingVectorizere a TfidfVectorizere il motivo per cui queste matrici sono di dimensioni diverse, in particolare nel numero di parole / termini.


Potete per favore condividere il set di dati con me? (risposta da rimuovere)
nKarza,

Risposte:


7

La differenza principale è che HashingVectorizerapplica una funzione di hashing ai conteggi di frequenza dei termini in ciascun documento, dove TfidfVectorizerscala quei conteggi di frequenza dei termini in ciascun documento penalizzando i termini che appaiono più ampiamente in tutto il corpus. C'è un ottimo riassunto qui: https://spark.apache.org/docs/latest/mllib-feature-extraction.html

  • Le funzioni hash sono un modo efficiente di mappare i termini alle caratteristiche; non deve necessariamente essere applicato solo alle frequenze dei termini, ma è così che HashingVectorizerviene impiegato qui. Insieme ai documenti 45339, ho il sospetto che il vettore delle caratteristiche sia di lunghezza 1048576 perché è il valore predefinito 2 ^ 20 n_features; potresti ridurlo e renderlo meno costoso da elaborare ma con un rischio maggiore di collisione, in cui la funzione associa termini diversi alla stessa funzionalità: http://preshing.com/20110504/hash-collision-probabilities/

  • A seconda del caso d'uso per i vettori di parole, potrebbe essere possibile ridurre significativamente la lunghezza del vettore della caratteristica hash (e quindi la complessità) con una perdita accettabile di accuratezza / efficacia (a causa di una maggiore collisione). Scikit-learn ha alcuni parametri di hashing che possono aiutare, ad esempio alternate_sign.

  • Se la matrice di hashing è più ampia del dizionario, significa che molte delle voci di colonna nella matrice di hashing saranno vuote, e non solo perché un determinato documento non contiene un termine specifico, ma perché sono vuoti nell'intero matrice. In caso contrario, potrebbe inviare più termini allo stesso hash di funzionalità: questa è la "collisione" di cui abbiamo parlato. HashingVectorizerha un'impostazione che funziona per mitigare questa chiamata attivata alternate_signper impostazione predefinita, descritta qui: en.wikipedia.org/wiki/Feature_hashing#Properties

  • La "frequenza dei termini - frequenza inversa dei documenti" prende le frequenze dei termini in ciascun documento e le pondera penalizzando le parole che compaiono più frequentemente in tutto il corpus. L'intuizione è che i termini trovati localmente hanno maggiori probabilità di essere rappresentativi dell'argomento di un documento specifico. Ciò è diverso da una funzione di hashing in quanto è necessario disporre di un dizionario completo di parole nel corpus per calcolare la frequenza inversa del documento. Mi aspetto che le dimensioni della tua matrice tf.idf siano 45339 documenti di 663307 parole nel corpus; Manning et al forniscono maggiori dettagli ed esempi di calcolo: https://nlp.stanford.edu/IR-book/html/htmledition/term-frequency-and-weighting-1.html

"Mining of Massive Dataset" di Leskovec et al. Ha molti dettagli su entrambi gli hash e tf.idf, gli autori hanno reso disponibile il pdf qui: http://www.mmds.org/


1
Se è tfidf vectorizernecessario un dizionario completo di parole per i calcoli idf, i termini nella matrice tfidf non dovrebbero essere più dei termini nella matrice hashing?
Minu,

2
Se la matrice di hashing è più ampia del dizionario, significa che molte delle voci di colonna nella matrice di hashing saranno vuote, e non solo perché un determinato documento non contiene un termine specifico, ma perché sono vuoti nell'intero matrice. Leggermente fuori tema, ma stai elaborando le parole nei tuoi documenti prima di vettorializzare? Stopwords, stemming, ecc?
redhq

Sì, sto elaborando. Sto usando spacy.
Minu,

1
Conferma: Quindi, 1048576 è la lunghezza predefinita di qualsiasi matrice di hashing se n_features non è menzionato? Se nel corpus sono presenti solo 663307 parole, le restanti 385269 funzioni sono vuote. Come può rendere questa matrice di hashing comoda senza tutte le funzioni vuote?
Minu,

1
Esatto: puoi ridimensionare il numero di funzioni modificando il parametro n_features=1048576, se hai tempo prova 640k, 320k e vedi se ha un impatto notevole sulla tua precisione. Dovrebbe accelerare almeno il tempo di allenamento. Vedi la risposta di @ Nathan per n_features=5!
redhq

5

Il HashingVectorizerha un parametro n_featuresche è 1048576di default. Durante l'hashing, in realtà non calcolano i termini di mappatura di un dizionario in un indice univoco da utilizzare per ognuno. Invece, basta hash ogni termine e di utilizzare una grande dimensione abbastanza che non ti aspetti lì per essere troppe collisioni: hash(term) mod table_size. È possibile impostare la matrice restituita con qualsiasi dimensione desiderata n_features. Dovresti regolarlo in modo che sia nel campo giusto per il tuo corpus se non ritieni che il valore predefinito sia ragionevole (averlo più grande causerà meno collisioni anche se richiede più memoria).

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)

0

HashingVectorizer e CountVectorizer (nota non Tfidfvectorizer) sono pensati per fare la stessa cosa. Quale è convertire una raccolta di documenti di testo in una matrice di occorrenze di token.

Se stai cercando di ottenere frequenze di termine ponderate per la loro importanza relativa (IDF), Tfidfvectorizer è quello che dovresti usare. Se hai bisogno dei conteggi grezzi o dei conteggi normalizzati (frequenza dei termini), devi usare CountVectorizer o HashingVectorizer.

Per ulteriori informazioni su HashingVectorizer, consulta questo articolo su HashingVectorizer e CountVectorizer .

Per ulteriori informazioni su Tfidfvectorizer, consultare questo articolo su Come utilizzare Tfidftransformer e Tfidfvectorizer .

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.