我想在我的 Spark 集群上训练有关 10G 新闻语料库的 word2vec 模型。 以下是我的spark集群的配置:
但是我发现使用 Spark Mllib 训练 Word2vec 并没有充分利用集群的资源。 例如: ubuntu中top命令的图片
如上图所示,一个worker只使用了100%的cpu,其他三个worker没有使用(所以不贴他们的图片),刚才我如何训练一个关于2G新闻语料库的word2vec模型,大约需要6h,所以我想知道如何更有效地训练模型?提前谢谢大家:)
更新1:以下命令是我在spark-shell中使用的命令
spark-shell \
--master spark://ip:7077 \
--executor-memory 70G \
--driver-memory 70G \
--conf spark.akka.frameSize=2000 \
--conf spark.driver.maxResultSize=0 \
--conf spark.default.parallelism=180
//import related packages
import org.apache.spark._
import org.apache.spark.mllib.linalg.{Vector, Vectors}
import org.apache.spark.mllib.feature.{Word2Vec, Word2VecModel}
//read about 10G newsdata corpus
val newsdata = sc.textFile("hdfs://ip:9000/user/bd/newsdata/*",600).map(line => line.split(" ").toSeq)
//Configure word2vec parameters
val word2vec = new Word2Vec()
word2vec.setMinCount(10)
word2vec.setNumIterations(10)
word2vec.setVectorSize(200)
//train the model
val model = word2vec.fit(newsdata)
更新2:
我已经训练了模型大约 24 小时,但没有完成。集群运行起来是这样的: 一个worker中只有100%的cpu被使用,其他三个worker没有像以前一样使用。
我在训练 Word2Vec 模型时在 Python 中遇到了类似的问题。查看 word2vec 的 PySpark 文档here,它显示:
setNumIterations(numIterations)
设置迭代次数(默认:1),该次数应小于 或等于分区数。
setNumPartitions(numPartitions)
设置分区数量(默认:1)。
我的 word2vec 模型停止挂起,当我增加模型使用的分区数量时,Spark 不再出现内存不足的情况,以便
numIterations <= numPartitions
我建议您设置
word2vec.setNumIterations(1)
或word2vec.setNumPartitions(10)
。
由于您的模型训练时间太长,我认为您应该首先尝试了解 Spark 对模型训练部分有何实际好处。根据本文,
许多常见的机器学习算法将函数重复应用于同一数据集以优化参数(例如,通过梯度下降)。虽然每次迭代都可以表示为 MapReduce/Dryad 作业,但每个作业都必须从磁盘重新加载数据,从而导致显着的性能损失
Spark mllib 的库通过在第一次迭代期间将数据缓存在内存中来消除这种性能损失。因此,与第一次迭代相比,后续迭代非常快,因此模型训练时间显着减少。我认为,在您的情况下,执行器内存可能不足以加载内存中的数据分区。因此,内容将溢出到磁盘,并且需要在每次迭代中再次从磁盘获取,从而消除了 Spark 的任何性能优势。为了确保情况确实如此,您应该尝试查看执行程序日志,其中包含一些诸如“无法在内存中存储 rdd_x_y”之类的行。 如果确实如此,您需要调整 --num-executors、--executor-memory 和 numPartitions 以查看这些参数的哪些值能够将整个数据加载到内存中。您可以在本地计算机上尝试使用小型数据集、单个执行器和少量执行器内存,并分析日志,同时逐渐增加执行器内存,以查看数据在哪个配置下完全缓存在内存中。一旦你有了小数据集的配置,你就可以通过数学计算来计算出需要多少个执行器和多少内存,以及所需分区大小的分区数应该是多少。
我也遇到过类似的问题,并按照上述步骤成功地将模型训练时间从大约 4 小时缩短到 20 分钟。