2015-08-29 24 views
9

Ho creato Term Frequency utilizzando HashingTF in Spark. Ho ottenuto il termine frequenze usando tf.transform per ogni parola.Come ottenere i dettagli delle parole da TF Vector RDD in Spark ML Lib?

Ma i risultati sono visualizzati in questo formato.

[<hashIndexofHashBucketofWord1>,<hashIndexofHashBucketofWord2> ...] 
,[termFrequencyofWord1, termFrequencyOfWord2 ....] 

esempio:

(1048576,[105,3116],[1.0,2.0]) 

sono in grado di ottenere l'indice nel secchio di hash, utilizzando tf.indexOf("word").

Ma come posso ottenere la parola utilizzando l'indice?

risposta

20

Beh, non è possibile. Poiché l'hashing non è iniettivo, non esiste una funzione inversa. In altre parole, il numero infinito di token può essere mappato su un singolo bucket, quindi è impossibile stabilire quale sia effettivamente lì.

Se si utilizza un hash di grandi dimensioni e il numero di token unici è relativamente basso, è possibile provare a creare una tabella di ricerca da bucket a possibili token dal set di dati. È una mappatura uno-a-molti, ma se le condizioni di cui sopra sono soddisfatte, il numero di conflitti dovrebbe essere relativamente basso.

Se è necessaria una trasformazione reversibile è possibile utilizzare Combina Tokenizer e StringIndexer e creare manualmente un vettore di funzionalità sparse.

Consulta anche: What hashing function does Spark use for HashingTF and how do I duplicate it?

Edit:

In Spark 1.5 + (PySpark 1.6+) è possibile utilizzare CountVectorizer che si applica trasformazione reversibile e memorizza il vocabolario.

Python:

from pyspark.ml.feature import CountVectorizer 

df = sc.parallelize([ 
    (1, ["foo", "bar"]), (2, ["foo", "foobar", "baz"]) 
]).toDF(["id", "tokens"]) 

vectorizer = CountVectorizer(inputCol="tokens", outputCol="features").fit(df) 
vectorizer.vocabulary 
## ('foo', 'baz', 'bar', 'foobar') 

Scala:

import org.apache.spark.ml.feature.{CountVectorizer, CountVectorizerModel} 

val df = sc.parallelize(Seq(
    (1, Seq("foo", "bar")), (2, Seq("foo", "foobar", "baz")) 
)).toDF("id", "tokens") 

val model: CountVectorizerModel = new CountVectorizer() 
    .setInputCol("tokens") 
    .setOutputCol("features") 
    .fit(df) 

model.vocabulary 
// Array[String] = Array(foo, baz, bar, foobar) 

dove elemento nella posizione 0th corrisponde all'indice 0, elemento alla 1a posizione di indice 1 e così via.

+1

Vorrei solo aggiungere che come si può vedere nella [documenti] (https://spark.apache.org/docs/1.6.0/api/python/pyspark.mllib.html) dalla versione 1.2.0 , puoi chiamare indexOf (term) – Matt