使用Spark流的迭代算法

时间:2015-03-15 16:51:38

标签: scala iteration apache-spark dstream

所以我理解Spark可以在单个RDD上执行迭代算法,例如Logistic回归。

    val points = spark.textFile(...).map(parsePoint).cache()
    var w = Vector.random(D) // current separating plane
    for (i <- 1 to ITERATIONS) {
      val gradient = points.map(p =>
        (1 / (1 + exp(-p.y*(w dot p.x))) - 1) * p.y * p.x
      ).reduce(_ + _)
      w -= gradient
    }

上面的示例是迭代的,因为它维护一个全局状态w,该状态在每次迭代后更新,并且在下一次迭代中使用其更新值。 Spark流中是否可以使用此功能?考虑相同的示例,除了现在points是DStream。在这种情况下,您可以创建一个使用

计算渐变的新DStream
val gradient = points.map(p =>
            (1 / (1 + exp(-p.y*(w dot p.x))) - 1) * p.y * p.x
          ).reduce(_ + _)

但是你将如何处理全局状态w。似乎w也必须是DStream(可能使用updateStateByKey),但是它的最新值会以某种方式传递到points地图函数中,而我不会认为是可能的。我认为DStreams不能以这种方式进行通信。我是正确的,还是可以在Spark Streaming中进行这样的迭代计算?

2 个答案:

答案 0 :(得分:2)

我刚刚发现foreachRDD功能非常简单。 MLlib实际上提供了可以用DStream训练的模型,我在streamingLinearAlgorithm代码中找到了答案。看起来您可以在驱动程序中本地保存全局更新变量并在.foreachRDD中更新它,因此实际上不需要将其转换为DStream本身。因此,您可以将此应用于我提供的示例

points.foreachRDD{(rdd,time) =>

     val gradient=rdd.map(p=> (1 / (1 + exp(-p.y*(w dot p.x))) - 1) * p.y * p.x
     )).reduce(_ + _)

  w -= gradient

  }

答案 1 :(得分:-1)

嗯......你可以通过并行化迭代器然后折叠它来更新渐变来实现某些目的。

另外......我认为你应该保留Spark Streaming,因为这个问题看起来没有任何将它链接到任何类型流媒体要求的功能。

// So, assuming... points is somehow a RDD[ Point ]
val points = sc.textFile(...).map(parsePoint).cache()
var w = Vector.random(D)

// since fold is ( T )( ( T, T) => T ) => T
val temps = sc.parallelize( 1 to ITERATIONS ).map( w )

// now fold over temps.
val gradient = temps.fold( w )( ( acc, v ) => {
  val gradient = points.map( p =>
    (1 / (1 + exp(-p.y*(acc dot p.x))) - 1) * p.y * p.x
  ).reduce(_ + _)
  acc - gradient
}