2015-12-09 12 views
11

stavo guardando la example del sito Spark per Word2Vec:Spark Word2vec matematica vettoriale

val input = sc.textFile("text8").map(line => line.split(" ").toSeq) 

val word2vec = new Word2Vec() 

val model = word2vec.fit(input) 

val synonyms = model.findSynonyms("country name here", 40) 

come faccio a fare il vettore interessanti, come re - uomo + donna = regina. Posso usare model.getVectors, ma non sono sicuro di come procedere ulteriormente.

+0

Potrebbe gentilmente accettare la risposta, anche adesso? Grazie ... – desertnaut

risposta

-2

Ecco lo pseudo codice. Per la piena attuazione, leggere la documentazione: https://spark.apache.org/docs/1.4.0/api/java/org/apache/spark/mllib/feature/Word2VecModel.html

  1. w2v_map = model.getVectors() # this gives u a map {word:vec}
  2. my_vector = w2v_map.get('king') - w2v_map.get('man') + w2v_map.get('queen') # do vector algebra here
  3. most_similar_word_to_vector = model.findSynonyms(my_vector, 10) # they have an api to get synonyms for word, and one for vector

edit: https://spark.apache.org/docs/1.4.0/api/java/org/apache/spark/mllib/feature/Word2VecModel.html#findSynonyms(org.apache.spark.mllib.linalg.Vector,%20int)

+2

Non è chiaro come fare la corrispondenza vettoriale. Vettori di Breeze o Spark? Questo è un componente chiave della domanda .... – user3803714

+2

public scala.Tuple2 findSynonyms (Vector vector, int num) Si fa corrispondere vettore con questo metodo che ho elencato: https: // spark. apache.org/docs/1.4.0/api/java/org/apache/spark/mllib/feature/Word2VecModel.html#findSynonyms(org.apache.spark.mllib.linalg.Vector,%20int) – jxieeducation

13

Ecco un esempio in pyspark, che immagino è semplice per portarlo su Scala - la chiave è l'uso di model.transform.

In primo luogo, ci alleniamo il modello come nell'esempio:

from pyspark import SparkContext 
from pyspark.mllib.feature import Word2Vec 

sc = SparkContext() 
inp = sc.textFile("text8_lines").map(lambda row: row.split(" ")) 

k = 220   # vector dimensionality 
word2vec = Word2Vec().setVectorSize(k) 
model = word2vec.fit(inp) 

k è la dimensionalità dei vettori di parole - più alto è il migliore (valore di default è 100), ma è necessario la memoria, e il numero più alto possibile con la mia macchina era 220. (MODIFICA: I valori tipici nelle pubblicazioni pertinenti sono compresi tra 300 e 1000)

Dopo aver addestrato il modello, è possibile definire una funzione semplice come segue:

def getAnalogy(s, model): 
    qry = model.transform(s[0]) - model.transform(s[1]) - model.transform(s[2]) 
    res = model.findSynonyms((-1)*qry,5) # return 5 "synonyms" 
    res = [x[0] for x in res] 
    for k in range(0,3): 
     if s[k] in res: 
      res.remove(s[k]) 
    return res[0] 

Ora, ecco alcuni esempi con i paesi e le loro capitali:

s = ('france', 'paris', 'portugal') 
getAnalogy(s, model) 
# u'lisbon' 

s = ('china', 'beijing', 'russia') 
getAnalogy(s, model) 
# u'moscow' 

s = ('spain', 'madrid', 'greece') 
getAnalogy(s, model) 
# u'athens' 

s = ('germany', 'berlin', 'portugal') 
getAnalogy(s, model) 
# u'lisbon' 

s = ('japan', 'tokyo', 'sweden') 
getAnalogy(s, model)  
# u'stockholm' 

s = ('finland', 'helsinki', 'iran') 
getAnalogy(s, model) 
# u'tehran' 

s = ('egypt', 'cairo', 'finland') 
getAnalogy(s, model) 
# u'helsinki' 

I risultati non sono sempre corrette - Lascio a voi di sperimentare, ma ottengono meglio con più formazione dati e aumento della dimensionalità vettoriale k.

Il ciclo for nella funzione rimuove le voci che appartengono alla query di input stessa, come ho notato che spesso la risposta corretta era la seconda nell'elenco restituito, con il primo di solito è uno dei termini di input.

+2

Potete per favore specificare perché stai moltiplicando per -1 qui: res = model.findSynonyms ((- 1) * qry, 5) # return 5 "sinonimi" Inoltre, puoi scrivere alcuni commenti sul ciclo for nella tua funzione getAnalogy. – user3803714

+2

L'esempio con lo stesso set di dati non ha funzionato come previsto. res = getAnalogy (s, model) print "Il risultato è:" + res o/p è: Il risultato è: montpellier – user3803714

+3

1) '' -1'' è solo per mantenere l'ordine '' qry'' intuitivo; puoi cambiare questo ordine e rimuoverlo 2) Ho già fornito commenti riguardo al ciclo '' for''; prova a rimuoverlo e restituire tutto '' res'' (invece di solo '' res [0] '' per vedere perché è necessario 3) Già detto che i risultati non sono sempre corretti, ma migliorano con l'aumentare di '' k'' (le carte usano almeno '' k = 300''); inoltre, i risultati esatti dipendono dal seme casuale. ** Tutto sommato **, la risposta è esattamente sulla matematica word2vec, che è la domanda. – desertnaut

1

val w2v_map = sameModel.getVectors // questo dà ua mappa {parola: vec}

val (king, man, woman) = (w2v_map.get("king").get, w2v_map.get("man").get, w2v_map.get("women").get) 

    val n = king.length 

    //daxpy(n: Int, da: Double, dx: Array[Double], incx: Int, dy: Array[Double], incy: Int); 
    blas.saxpy(n,-1,man,1,king,1) 

    blas.saxpy(n,1,woman,1,king,1) 

    val vec = new DenseVector(king.map(_.toDouble)) 

    val most_similar_word_to_vector = sameModel.findSynonyms(vec, 10) //they have an api to get synonyms for word, and one for vector 
    for((synonym, cosineSimilarity) <- most_similar_word_to_vector) { 
    println(s"$synonym $cosineSimilarity") 
    } 

e il risultato in esecuzione come colpo:

donne 0,628454885964967 Philip 0,5539534290356802 henry 0,5520055707837214 vii ,5455116413024774 elizabeth 0.5290994886254643 regina 0.5162519562606844 uomini 0.5133851770249461 wenceslaus 0.5127030522678778 viii 0.5104392579985102 più vecchio 0.510425791249559