一、概述
word2vector 是google开源的一个生成词向量的工具,以语言模型为优化目标,迭代更新训练文本中的词向量,最终收敛获得词向量。词向量可以作为文本分析中重要的特征,在分类问题、标注问题等场景都有着重要的应用价值。本文总结下了spark word2vector使用过程中遇到的问题,以及给出word2vector使用所需的参数配置,希望能够减少新手在使用过程中遇到的坑,希望有所帮助。
二、实战应用
1. 举个栗子
import org.apache.spark.SparkContext
import org.apache.spark.SparkContext._
import org.apache.spark.SparkConf
import org.apache.spark.mllib.feature.{Word2Vec,Word2VecModel}
object Word2Vec {
def main(args: Array[String]) {
val conf = new SparkConf().setAppName("Word2vec Application")
val sc = new SparkContext(conf)
val input = sc.textFile("yourfilepath").map(line => line.split(" ").toSeq)
val word2vec = new Word2Vec()
val model = word2vec.fit(input)
val synonyms = sameModel.findSynonyms("喜欢", 40)
for((synonym, cosineSimilarity) <- synonyms) {
println(s"$synonym $cosineSimilarity")
}
}
}```
按照官网的例子,word2vec采用默认的参数进行训练,会遇到下面一些问题:
问题1: driver maxResultSize(1024m),由于word2vector源码中有collect操作,目的是获取训练文本中的词和词频,而统计训练文本中的词和词频的数据量大于这个数值。因此,需要设置大些maxResultSize.
问题2: driver 端内存不足,可以在启动参数配置中,设置到6G-8G之间。
问题3:解决上述问题后,发现作业可以运行但发现,卡在mapPartitionsWithIndex这一步骤,如下图:
![](http://upload-images.jianshu.io/upload_images/1477700-49a94ea140f215a3.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240)
![](http://upload-images.jianshu.io/upload_images/1477700-4ff12231bf1c5ae3.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240)
分析发现,stage 3仅仅有一个task,灰常之诡异,并且一直卡在此步骤,于是点击mapPartitionsWithIndex at Word2Vec进去发现,只有7在运行,申请的其他executor都处于闲置状态,并且很明显7的GC time时间越来越长;此外,点击网页顶端Executors那一栏,看到确实只有7有一个active task。定位问题就出在mapPartitionsWithIndex这一步,因此,下一步会从word2vector的实现源码中寻找问题的根源在哪里。
#####2.Word2vector源码
虽然spark提供了ml和mllib两套机器学习库,对于word2vector而言,底层都是基于mllib/feature/Word2Vec.scala 里面的Word2Vec 类,直接分析此类的参数和fit实现方法,发现:
![](http://upload-images.jianshu.io/upload_images/1477700-56512bbedcf02509.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240)
如果按照官网中给出的例子,word2vector训练采用的参数使用上述参数。其中迭代次数 和 numPartitions有可能会影响到训练过程中的耗时。迭代次数设置为1,已经是最小训练迭代次数,排除此原因。继续分析numPartitions在fit中何处使用过,发现:
![](http://upload-images.jianshu.io/upload_images/1477700-c76b557816e55171.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240)
fit训练过程中包括:获得训练文本中所有词汇及词频->按照词频建立霍夫曼树->广播词汇hash表、广播词汇->将句子使用词汇hashid表示出来->val newSentences = sentences.repartition(numPartitions).cache()->训练更新词向量,而mapPartitionsWithIndex出现在newSentences的调用中,也就是说,如果采用默认参数,相当于在单机训练词向量,表示很无语。所以,根据实际情况,需要调整参数配置,重新启动词向量训练。
以下是调整后的代码word2vector_training.py:
from pyspark.ml.feature import Word2Vec
from pyspark.sql import SQLContext
from pyspark import SparkConf, SparkContext
from pyspark.sql import Row
conf = (SparkConf().set(“spark.driver.maxResultSize”,”2g”))
sc = SparkContext(conf=conf)
sqlContext = SQLContext(sc)
text = sc.textFile(“yourfilepath”)
documentDF = text.map(lambda x : Row(text=x.split(” “))).toDF()
word2Vec = Word2Vec(vectorSize=200, minCount=5, numPartitions=100,inputCol=”text”, outputCol=”result”)
model = word2Vec.fit(documentDF)
vector_model = model.getVectors()
vector_model.saveAsParquetFile(“modelpath”)
作业配置:
!/bin/bash
spark-submit
–master yarn-client
–executor-cores 2
–executor-memory 14g
–queue your-queue
–num-executors 100
–driver-memory 10g
–conf spark.ui.port=$RANDOM
–conf spark.shuffle.manager=SORT
–conf spark.shuffle.memoryFraction=0.2
–conf spark.yarn.executor.memoryOverhead=2048
–conf spark.core.connection.ack.wait.timeout=300
–conf spark.akka.frameSize=600 ./word2vector_training.py
备注:笔者当时采用的训练集大小453,707,007,vcoab 大小4,338,362,此外,spark word2vector 默认 vocab * vector_size < Integer.Max_Value/8,否则无法训练,请合理设置minCount和vector_size的值。