在 spark 上递归构建决策树时,是否需要保存中间数据子集?

Do I need to I save intermediate subsets of data while building decision tree on spark recursively?

我正在 Scala/Spark(50 节点集群)上构建决策树。由于我的数据集有点大(~ 2TB),我想将其并行化。 我的代码看起来像这样

def buildTree(data: RDD[Array[Double]], numInstances: Int): Node = {

    // Base case
    if (numInstances < minInstances) {
        return new Node(isLeaf = true)
    }

    /*
    * Find best split for all columns in data
    */

    val leftRDD = data.filter(leftSplitCriteria)
    val rightRDD = data.filter(rightSplitCriteria)
    val subset = Seq(leftRDD, rightRDD)
    val counts = Seq(numLeft, numRight)

    val children = (0 until 2).map(i =>
                    (i,subset(i),counts(i)))
                    .par.map(x => {buildTree(x._2,x._3)})

    return new Node(children(0), children(1), Split)
}

我的问题是

  1. Scala 是一种惰性语言,不会立即计算 map/filter 操作的输出。那么在构建一个新节点时,是否将父节点的所有过滤器以及父节点的父节点堆叠起来(并递归应用)?
  2. 并行构建树的最佳方法是什么?我应该 cache/save 中间步骤中的数据集吗?
  3. 虽然 运行 这段代码,仅提供 num-executors 是否足够,或者如果我提供 executor- 是否会有所不同?核心数驱动核心数等?
  1. 我假设 numLeft 是使用 leftRDD.count() 计算的,计数是一个动作,将强制计算所有依赖的 RDD。

  2. 在这种情况下,您实际上会进行不止一次过滤,一次用于计数,另一次用于每个子项依赖。你应该缓存你的 RDD 以避免重复计算,你只需要最后一个,这样你就可以在每个阶段 unpersist 前一个。

有关更多说明,请参阅

旁注:Spark 使用惰性求值模型,我认为我们不会说 scala 是一种惰性语言。

我最终按特征在每个级别并行化拆分查找。

参考