火花 2.0.0
DataFrame
目前,随着 RDD API 的不断弃用,Spark 向 API 迈进了一大步。虽然原生“ML”算法的数量正在增长,但下面强调的要点仍然有效,并且在内部许多阶段是直接使用 RDD 实现的。
另请参阅:在 Spark 2.0 中将基于 RDD 的 MLlib API 切换到维护模式
火花 < 2.0.0
我想主要的缺失点是spark.ml
算法通常不在 DataFrames 上运行。所以在实践中,拥有一个ml
包装器比其他任何事情都重要。甚至本机 ML 实现(如内部ml.recommendation.ALS
使用RDDs
)。
为什么不在 DataFrames 之上从头开始实现一切?很可能是因为只有很小一部分机器学习算法实际上可以从目前在 Catalyst 中实现的优化中受益,更不用说使用 DataFrame API / SQL 高效自然地实现了。
- 大多数 ML 算法需要高效的线性代数库而不是表格处理。对线性代数使用基于成本的优化器可能是一个有趣的补充(我认为flink已经有一个),但现在看起来这里没有什么可收获的。
- DataFrames API 使您几乎无法控制数据。
你不能使用 partitioner *,你不能同时访问多条记录(我的意思是整个分区),你被限制在一组相对较小的类型和操作中,你不能使用可变数据结构等等。
- Catalyst 应用局部优化。如果您传递 SQL 查询/DSL 表达式,它可以对其进行分析、重新排序、应用早期预测。所有这一切都是伟大但典型的可扩展算法需要迭代处理。所以你真正想要优化的是整个工作流程,单独的 DataFrame 并不比普通的 RDD 快,并且取决于操作实际上可能更慢。
- Spark 中的迭代处理,尤其是连接,需要对分区数量进行精细分级控制,否则会发生奇怪的事情。DataFrames 让您无法控制分区。此外,
DataFrame
/Dataset
不提供本机检查点功能(在 Spark 2.1 中修复),这使得迭代处理几乎不可能没有丑陋的 hack
- 忽略低级实现细节,某些算法组(如 FPM)不太适合 ML 管道定义的模型。
- 许多优化仅限于本机类型,而不是像
VectorUDT
.
DataFrames 还有一个问题,它与机器学习没有真正的关系。当您决定在代码中使用 DataFrame 时,您几乎放弃了静态类型和类型推断的所有好处。如果您认为这是一个问题,这是非常主观的,但可以肯定的是,在 Scala 世界中感觉并不自然。
关于更好、更新和更快的我会看看Deep Dive into Spark SQL's Catalyst Optimizer,特别是与 quasiquotes 相关的部分:
下图显示了准引号让我们生成性能类似于手动调优程序的代码。
* 这在 Spark 1.6 中已更改,但仍仅限于默认值HashPartitioning