【问题标题】:Spark Word2vec vector mathematicsSpark Word2vec 向量数学
【发布时间】:2016-03-14 08:07:22
【问题描述】:

我正在查看用于 Word2Vec 的 Spark 网站的 example

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)

国王-男人+女人=王后这样有趣的向量怎么办。我可以使用 model.getVectors,但不确定如何继续。

【问题讨论】:

    标签: apache-spark machine-learning apache-spark-mllib word2vec


    【解决方案1】:

    这是伪代码。如需完整实现,请阅读文档: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

    编辑: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】:

    这是pyspark 中的一个示例,我想它可以直接移植到 Scala - 关键是model.transform 的使用。

    首先,我们按照示例训练模型:

    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 是词向量的维数 - 越高越好(默认值为 100),但您需要内存,我的机器可以使用的最高数字是 220。(编辑: 相关出版物中的典型值在 300 到 1000 之间)

    在我们训练好模型之后,我们可以定义一个简单的函数如下:

    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]
    

    现在,这里有一些国家和首都的例子:

    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'
    

    结果并不总是正确的 - 我将留给您进行实验,但随着更多的训练数据和增加的向量维度k,它们会变得更好。

    函数中的for 循环删除属于输入查询本身的条目,因为我注意到通常正确答案是返回列表中的第二个,而第一个通常是输入项之一。

    【讨论】:

    • 你能说明为什么你在这里乘以-1: res = model.findSynonyms((-1)*qry,5) # return 5 "synonyms" 另外,你能写一些关于getAnalogy 函数中的 for 循环。
    • 具有相同数据集的示例未按预期工作。 res = getAnalogy(s, model) print "结果是:" + res o/p is: 结果是:蒙彼利埃
    • 1) -1 只是为了保持qry 的顺序直观;您可以更改此顺序并将其删除 2) 已提供有关 for 循环的 cmets;尝试删除它并返回所有res(而不仅仅是res[0],看看为什么有必要3)已经说过结果并不总是正确的,但随着k的增加它们会变得更好(论文至少使用@ 987654335@);此外,确切的结果取决于随机种子。 总而言之,答案正是关于 word2vec 数学,这就是问题所在。
    • @user3803714 还要记住,出版物和演示中显示的结果总是经过精心挑选的,即错误的结果根本不会显示(尽管它们确实存在)。
    【解决方案3】:
      val w2v_map = sameModel.getVectors//this gives u a map {word: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")
      }
    

    运行结果如下:

    women 0.628454885964967
    philip 0.5539534290356802
    henry 0.5520055707837214
    vii 0.5455116413024774
    elizabeth 0.5290994886254643
    **queen 0.5162519562606844**
    men 0.5133851770249461
    wenceslaus 0.5127030522678778
    viii 0.5104392579985102
    eldest 0.510425791249559
    

    【讨论】:

      猜你喜欢
      • 2018-09-19
      • 2019-04-15
      • 2017-07-05
      • 2016-09-05
      • 2019-02-12
      • 1970-01-01
      • 2018-07-15
      • 2018-06-13
      • 1970-01-01
      相关资源
      最近更新 更多