遵循Spark MLlib Guide我们可以看到 Spark 有两个机器学习库:
spark.mllib
,构建在 RDD 之上。spark.ml
,构建在 Dataframe 之上。
根据this和 this关于 StackOverflow 的问题,Dataframe 比 RDD 更好(也更新),应该尽可能使用。
问题是我想使用常见的机器学习算法(例如: Frequent Pattern Mining 、 Naive Bayes 等),而 spark.ml
(对于数据帧)不提供此类方法,只有 spark.mllib
(对于 RDD)提供此算法。
如果 Dataframe 比 RDD 更好,并且引用的指南建议使用 spark.ml
,那么为什么常见的机器学习方法没有在该库中实现?
这里遗漏了什么?
最佳答案
Spark 2.0.0
目前,Spark 大力转向 DataFrame
API,并持续弃用 RDD API。虽然原生“ML”算法的数量不断增长,但下面突出显示的要点仍然有效,并且内部许多阶段都是直接使用 RDD 实现的。
另请参阅:Switch RDD-based MLlib APIs to maintenance mode in Spark 2.0
Spark <2.0.0
我认为主要的缺失点是 spark.ml
算法通常不适用于 DataFrame。因此,在实践中,拥有一个 ml
包装器比其他任何事情都更重要。甚至 native ML 实现(如 ml.recommendation.ALS
在内部使用 RDD
)。
为什么不在 DataFrames 之上从头开始实现一切?很可能是因为只有一小部分机器学习算法实际上可以从 Catalyst 中当前实现的优化中受益,更不用说使用 DataFrame API/SQL 高效且自然地实现了。
- 大多数机器学习算法需要高效的线性代数库而不是表格处理。对线性代数使用基于成本的优化器可能是一个有趣的补充(我认为 flink 已经有了一个),但目前看来这里没有任何收获。
- DataFrames API 使您对数据的控制非常有限。
你不能使用分区器*,你不能同时访问多条记录(例如,我的意思是整个分区),你仅限于相对较小的一组类型和操作,你不能使用可变数据结构等。 - Catalyst 应用局部优化。如果您传递 SQL 查询/DSL 表达式,它可以对其进行分析、重新排序、应用早期预测。所有这些都是伟大但典型的可扩展算法需要迭代处理。因此,您真正想要优化的是整个工作流程,并且单独的 DataFrame 并不比普通 RDD 更快,而且依赖于操作实际上可能会更慢。
- Spark 中的迭代处理(尤其是连接)需要对分区数量进行精分割级控制,否则weird things happen 。 DataFrame 无法让您控制分区。此外,
DataFrame
/Dataset
不提供 native 检查点功能(在 Spark 2.1 中修复),这使得迭代处理几乎不可能在没有丑陋的黑客攻击的情况下进行 - 忽略低级实现细节,某些算法组(例如 FPM)不太适合机器学习管道定义的模型。
- 许多优化仅限于 native 类型,而不是像
VectorUDT
这样的 UDT 扩展。
DataFrames 还有一个问题,它与机器学习并没有真正的关系。当您决定在代码中使用 DataFrame 时,您就放弃了静态类型和类型推断的几乎所有好处。如果你认为它是一个问题或不是一个问题,这是非常主观的,但可以肯定的是,它在 Scala 世界中感觉不自然。
关于更好、更新和更快,我会看看 Deep Dive into Spark SQL’s Catalyst Optimizer ,特别是与准引号相关的部分:
<小时/>The following figure shows that quasiquotes let us generate code with performance similar to hand-tuned programs.
* 这在 Spark 1.6 中已更改,但仍仅限于默认的 HashPartitioning
关于machine-learning - 为什么spark.ml不实现任何spark.mllib算法?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/33237096/