web-dev-qa-db-fra.com

Spark Mathématiques vectorielles Word2vec

Je regardais le exemple du site Spark pour Word2Vec:

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)

Comment puis-je faire le vecteur intéressant tel que roi - homme + femme = reine. Je peux utiliser model.getVectors, mais je ne sais pas comment procéder.

16
user3803714

Voici un exemple dans pyspark, que je suppose facile à porter à Scala - la clé est l’utilisation de model.transform.

Tout d'abord, nous formons le modèle comme dans l'exemple:

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 est la dimensionnalité des vecteurs Word - le plus haut étant le mieux (la valeur par défaut est 100), mais vous aurez besoin de mémoire et le nombre le plus élevé que j’aurais pu utiliser avec ma machine était 220. ( EDIT: Valeurs typiques dans le publications pertinentes sont entre 300 et 1000)

Après avoir formé le modèle, nous pouvons définir une fonction simple comme suit:

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]

Maintenant, voici quelques exemples avec les pays et leurs capitales:

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'

Les résultats ne sont pas toujours corrects. Je vous laisse le soin d'expérimenter, mais ils s'améliorent avec davantage de données d'apprentissage et une dimensionnalité vectorielle accrue k.

La boucle for de la fonction supprime les entrées appartenant à la requête d'entrée elle-même, car j'ai remarqué que la réponse correcte était souvent la deuxième réponse dans la liste renvoyée, le premier correspondant généralement à l'un des termes d'entrée.

21
desertnaut