为什么spark.ml没有实现任何spark.mllib算法?

16
根据Spark MLlib Guide,Spark有两个机器学习库:spark.mllib(基于RDD)和spark.ml(基于DataFrames)。根据StackOverflow上的这个这个问题,DataFrames比RDDs更好(也是较新的),应该尽可能使用它。
但问题在于我想使用常见的机器学习算法(例如:Frequent Pattern MiningNaive Bayes等),而spark.ml(基于DataFrames)并未提供此类方法,只有spark.mllib(基于RDDs)提供了这些算法。
如果DataFrames比RDDs更好,而推荐使用spark.ml,为什么不在该库中实现常用的机器学习方法呢?
这里缺少什么要点?

3
与在StackOverflow上的“保存模型”相关的内容。 - Alberto Bonsanto
2
这个问题实际上很有趣,事实上,它与Alberto提到的问题有关。您可以在@zero323的答案中找到答案。 - eliasah
晚来一步,只是想补充一下,虽然主要的Spark ML在线文档没有提到,但你可以在API文档中找到NaiveBayes,并且你肯定可以使用它。我正在使用它。 - tadamhicks
1个回答

15

Spark 2.0.0

目前,Spark 在不断废弃 RDD API 的同时,大力推进 DataFrame API。虽然原生的“ML”算法数量正在增加,但下面强调的主要点仍然有效,并且内部许多阶段直接使用 RDD 实现。

另请参见:将基于 RDD 的 MLlib API 切换到 Spark 2.0 维护模式

Spark < 2.0.0

我想主要缺失的是 spark.ml 算法通常不在 DataFrames 上运行。因此,实际上更多的是拥有一个 ml 包装器而不是其他任何东西。即使是本机的 ML 实现(如 ml.recommendation.ALS)也在内部使用 RDDs

为什么不在DataFrames的基础上从头开始实现所有内容呢?很可能是因为目前在Catalyst中实现的优化只有非常小的机器学习算法子集能够受益,更不用说使用DataFrame API / SQL高效自然地实现了。
  • 大多数机器学习算法需要高效的线性代数库,而不是表格处理。使用基于成本的优化器进行线性代数计算可能是一个有趣的补充(我认为 已经有了这个功能),但目前看来在这方面没有什么可获得的。
  • DataFrames API 对数据的控制非常有限。您无法使用分区器*,无法同时访问多条记录(例如整个分区),受限于相对较小的类型和操作集,无法使用可变数据结构等。
  • Catalyst 应用本地优化。如果您传递 SQL 查询 / DSL 表达式,它可以分析、重新排序、应用早期投影。所有这些都很好,但典型的可扩展算法需要迭代处理。所以您真正想要优化的是整个工作流程,而 DataFrames 单独并不比普通的 RDD 更快,并且根据操作的不同,实际上可能更慢。
  • Spark 中的迭代处理,特别是与连接相关的处理,需要对分区数量进行细粒度控制,否则会发生 奇怪的事情。DataFrames 无法控制分区。此外,DataFrame / Dataset 不提供本地检查点功能(在 Spark 2.1 中已经修复),这使得迭代处理几乎不可能,除非使用丑陋的 hack。
  • 忽略底层实现细节,有些算法组,如 FPM,不太适合 ML 管道定义的模型。
  • 许多优化仅限于原生类型,而不是 UDT 扩展,如 VectorUDT
使用DataFrame时,存在一个问题,与机器学习无关。当您在代码中决定使用DataFrame时,几乎放弃了所有静态类型和类型推断的好处。这是否是问题高度主观,但有一件事确定,它在Scala世界中并不自然。
关于更好、更新、更快的问题,建议查看深入了解Spark SQL的Catalyst优化器,特别是与quasiquotes相关的部分:
以下图表显示,quasiquotes使我们能够生成性能类似于手动调整的程序的代码。

* 这在Spark 1.6中已经改变,但仍然限制于默认的HashPartitioning


1
请纠正我如果我错了,但是我认为即使 ml 仅被用作 mllib 的包装器,它对于 Python 用户也提供了巨大的好处,因为 ml 会使用 Scala 版本的 mllib 而不是通过 pyspark.mllib API 可用的 Python 版本。这可以消除在 JVM 和 Python 解释器之间移动数据的巨大开销。 - max
@Max 如果你开始使用加载到Java对象中的数据,并且从未将其移回,则是的。否则,它不会有任何区别。还有不同类型的VM之间的“移动数据”。因此,我不确定我是否理解问题。 - zero323
是的,我是指如果您的输入/输出将在磁盘上,并且您使用DataFrame API进行磁盘I/O。至于在虚拟机之间移动数据,我刚刚意识到在pyspark.mllib场景中不需要对数据进行序列化/反序列化(因为大部分数据将永远保留在Python VM中,例如numpy数组等,并且不需要在JVM中操作)。所以我想,使用Python RDD与Scala RDD相比的开销仅限于您在这里描述的问题-但我认为这仍然不是完全微不足道的。 - max
@max 嗯...当然,把所有东西放在一个地方肯定有好处。但一切都取决于上下文。通常,分布式模型训练比任何serde活动都要昂贵得多。但是,通过加速代码的一小部分来进行优化并不明智。所以,在这里要合理。 - zero323

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接