web-dev-qa-db-ja.com

Spark Word2vecベクトル数学

example of Spark 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)

キング-男性+女性=クイーンなどの興味深いベクトルをどのように実行しますか。 model.getVectorsを使用できますが、さらに先に進む方法がわかりません。

17
user3803714

これは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はWordベクトルの次元です-高いほど良いです(デフォルト値は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ループは、入力クエリ自体に属するエントリを削除します。これは、返されるリストの2番目が正解であり、通常は最初の回答が入力用語の1つであることが多いためです。

21
desertnaut
  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")
  }

そして、打撃としての実行結果:

女性0.628454885964967フィリップ0.5539534290356802ヘンリー0.5520055707837214vii0.5455116413024774エリザベス0.5290994886254643 クイーン0.5162519562606844男性0.5133851770249461ヴァーツラフ0.5127030522678778 viii0.5104392579985102長老0.510425791249

1
jay liu