2014-11-12 10 views
9

Provo ad utilizzare il nuovo algorithem TFIDF che offre scintilla 1.1.0. Sto scrivendo il mio lavoro per MLLib in Java, ma non riesco a capire come far funzionare l'implementazione di TFIDF. Per qualche motivo, IDFModel accetta solo un JavaRDD come input per il metodo transform e non Vector semplice. Come posso utilizzare le classi date per modellare un vettore TFIDF per i miei LabledPoints?Implementazione Spider MLLib TFIDF per LogisticRegression

Nota: le righe del documento sono nel formato [Etichetta; Testo]


Ecco il mio codice finora:

 // 1.) Load the documents 
     JavaRDD<String> data = sc.textFile("/home/johnny/data.data.new"); 

     // 2.) Hash all documents 
     HashingTF tf = new HashingTF(); 
     JavaRDD<Tuple2<Double, Vector>> tupleData = data.map(new Function<String, Tuple2<Double, Vector>>() { 
      @Override 
      public Tuple2<Double, Vector> call(String v1) throws Exception { 
       String[] data = v1.split(";"); 
       List<String> myList = Arrays.asList(data[1].split(" ")); 
       return new Tuple2<Double, Vector>(Double.parseDouble(data[0]), tf.transform(myList)); 
      } 
     }); 

     tupleData.cache(); 

     // 3.) Create a flat RDD with all vectors 
     JavaRDD<Vector> hashedData = tupleData.map(new Function<Tuple2<Double,Vector>, Vector>() { 
      @Override 
      public Vector call(Tuple2<Double, Vector> v1) throws Exception { 
       return v1._2; 
      } 
     }); 

     // 4.) Create a IDFModel out of our flat vector RDD 
     IDFModel idfModel = new IDF().fit(hashedData); 

     // 5.) Create Labledpoint RDD with TFIDF 
     ??? 

Soluzioneda Sean Owen:

 // 1.) Load the documents 
     JavaRDD<String> data = sc.textFile("/home/johnny/data.data.new"); 

     // 2.) Hash all documents 
     HashingTF tf = new HashingTF(); 
     JavaRDD<LabeledPoint> tupleData = data.map(v1 -> { 
       String[] datas = v1.split(";"); 
       List<String> myList = Arrays.asList(datas[1].split(" ")); 
       return new LabeledPoint(Double.parseDouble(datas[0]), tf.transform(myList)); 
     }); 
     // 3.) Create a flat RDD with all vectors 
     JavaRDD<Vector> hashedData = tupleData.map(label -> label.features()); 
     // 4.) Create a IDFModel out of our flat vector RDD 
     IDFModel idfModel = new IDF().fit(hashedData); 
     // 5.) Create tfidf RDD 
     JavaRDD<Vector> idf = idfModel.transform(hashedData); 
     // 6.) Create Labledpoint RDD 
     JavaRDD<LabeledPoint> idfTransformed = idf.zip(tupleData).map(t -> { 
      return new LabeledPoint(t._2.label(), t._1); 
     }); 

risposta

11

IDFModel.transform() accetta un JavaRDD o RDD di Vector, come si vedere. Non ha senso calcolare un modello su un singolo Vector, quindi non è quello che stai cercando giusto?

Suppongo che tu stia lavorando in Java, quindi vuoi dire che vuoi applicarlo a JavaRDD<LabeledPoint>. LabeledPoint contiene un Vector e un'etichetta. IDF non è un classificatore o un regressore, quindi non ha bisogno di etichette. È possibile map un gruppo di LabeledPoint per estrarre solo il loro Vector.

Ma si dispone già di uno JavaRDD<Vector> precedente. TF-IDF è semplicemente un modo di mappare parole a caratteristiche di valore reale basate sulle frequenze di parola nel corpus. Inoltre non emette un'etichetta. Forse vuoi dire che vuoi sviluppare un classificatore dai vettori di feature derivati ​​da TF-IDF e alcune altre etichette che hai già?

Forse questo chiarisce le cose, ma altrimenti dovresti chiarire molto bene cosa stai cercando di ottenere con TF-IDF.

+1

Supponiamo di avere un set di dati con (etichetta, id, vettore). Non vedo alcun modo per calcolarlo su un modello TF-IDF e in qualche modo rimappare ogni vettore sul suo id e/o etichetta dopo aver ottenuto il JavaRDD da IDFModel.transform(). Spero che chiarisca un po 'il problema che sto affrontando .. – Johnny000

+3

Ah ho fatto un po' di errore qui. È 'IDF' che calcola le frequenze. Sì, avrebbe più senso se "IDFModel" funzionasse anche su un singolo 'Vector'. Puoi fare una richiesta di pull per questo. Nel frattempo questo può funzionare: 1. Persist input RDD. 2. Trasformalo in soli vettori e applica 'IDFModel' 3.' zip' con RDD originale 4. Trasforma l'etichetta e il nuovo vettore in 'LabeledPoint' –

+0

Sì, anche questo è stato il mio pensiero, effettuerà una richiesta di pull .. grazie comunque – Johnny000