使用Apache Spark 2.0.0和mllib

时间:2016-09-28 18:44:09

标签: java apache-spark apache-spark-mllib word2vec

我一直在尝试使用spark和mllib来训练word2vec模型,但我似乎没有在大型数据集上获得分布式机器学习的性能优势。我的理解是,如果我有w工作者,那么,如果我创建一个具有n个分区的RDD,其中n> w并且我尝试通过调用Word2Vec的拟合函数以RDD作为参数来创建Word2Vec模型,那么spark将分发数据统一地训练这些w工人的单独的word2vec模型,并在最后使用某种减速器功能从这些w模型创建单个输出模型。这将减少计算时间,而不是1块,同时处理数据块。权衡取决于最终使用的减速器功能,可能会发生一些精度损失。 Spark中的Word2Vec实际上是否以这种方式工作?如果情况确实如此,我可能需要使用可配置的参数。

修改

添加问这个问题背后的原因。我在10台工作机器上运行了java spark word2vec代码,并在通过文档之后为执行器内存,驱动程序内存和num-executors设置了合适的值,用于2.5gb输入文本文件,该文件被映射到rdd分区,然后用作rdd分区训练mllib word2vec模型的数据。培训部分花了几个小时。工作节点的数量似乎对训练时间没有太大影响。相同的代码在较小的数据文件(大约10 MB的数量级)上成功运行

代码

SparkConf conf = new SparkConf().setAppName("SampleWord2Vec");
conf.set("spark.serializer", "org.apache.spark.serializer.KryoSerializer");
conf.registerKryoClasses(new Class[]{String.class, List.class});
JavaSparkContext jsc = new JavaSparkContext(conf);
JavaRDD<List<String>> jrdd = jsc.textFile(inputFile, 3).map(new Function<String, List<String>>(){            
        @Override
        public List<String> call(String s) throws Exception {
            return Arrays.asList(s.split(","));
        }        
});
jrdd.persist(StorageLevel.MEMORY_AND_DISK());
Word2Vec word2Vec = new Word2Vec()
      .setWindowSize(20)
      .setMinCount(20);

Word2VecModel model = word2Vec.fit(jrdd);
jrdd.unpersist(false);
model.save(jsc.sc(), outputfile);
jsc.stop();
jsc.close();

2 个答案:

答案 0 :(得分:1)

从评论,答案和downvotes来看,我想我无法正确构建我的问题。但是我想知道的答案是肯定的,可以在spark上并行训练你的word2vec模型。很久以前就创建了此功能的拉取请求:

https://github.com/apache/spark/pull/1719

在java中,spark mllib中的Word2Vec对象有一个setter方法(setNumPartitions)。这允许您并行地在多个执行程序上训练word2vec模型。 根据上面提到的拉取请求的评论:

&#34; 为了使我们的实现更具可伸缩性,我们分别训练每个分区,并在每次迭代后合并每个分区的模型。为了使模型更准确,可能需要多次迭代。&#34;

希望这有助于某人。

答案 1 :(得分:0)

我没有看到您的代码本身存在任何错误。但我强烈建议您考虑数据帧API。举个例子,这是一个经常被抛出的小图表:

enter image description here

另外,我不知道你是怎么回事过的。在数据框的元素(这不是他们的工作方式)。以下是Spark online docs

中的一个示例

enter image description here

您有一般的想法......但您必须先将数据并行化为数据框。将javardd转换为DataFrame非常简单。

(2, 0)

Spark运行有向无环图(DAG)代替MR,但概念是相同的。对数据运行DataFrame fileDF = sqlContext.createDataFrame(jrdd, Model.class); 确实会在工作人员的数据上运行,然后缩减为单个模型。但是这个模型本身会分配到内存中,直到你决定把它写下来。

但是,作为一个试验,通过说NLTK或Word2Vec的原生C ++二进制文件运行同一个文件需要多长时间?

最后一个想法......是否有理由坚持记忆和磁盘? Spark具有本机'fit(),默认情况下会持久存储到内存中。 Spark的强大功能是对内存中保存的数据进行机器学习...内存中的大数据。如果你坚持使用磁盘,即使使用kryo,你也会在磁盘I / O上造成瓶颈。恕我直言,首先要尝试的是摆脱这种情况并坚持到记忆中。如果性能提高,那么很好,但通过DataFrames依靠Catalyst的强大功能,您将发现性能的突飞猛进。

我们没有讨论的一件事是你的集群。考虑每个节点每个节点有多少内存......每个节点有多少个核心......你的集群是否正在与其他需要资源的应用程序进行虚拟化(超过像大多数vHosts那样配置)会很有帮助...是您的群集在云端?共享还是专用?

您是否看过Spark的UI来分析代码的运行时操作?当模型适合时,你对工人运行.cache()时会看到什么?你能看到完整的CPU利用率吗?您是否尝试过指定top以确保充分利用CPU?

我已经多次看到所有工作都在一个工作节点上的一个核心上完成。获得此信息会很有帮助。

在排查性能时,有很多地方需要查看,包括Spark配置文件本身!