[Spark Streaming]如何在每次收到新邮件时加载模型?

时间:2016-10-17 04:31:00

标签: scala serialization apache-spark spark-streaming

在Spark Streaming中,每次收到新消息时,都会使用模型根据此新消息预测某个消息。但随着时间的推移,模​​型可以由于某种原因而改变,所以我想在新消息进入时重新加载模型。我的代码看起来像这样

def loadingModel(@transient sc:SparkContext)={
  val model=LogisticRegressionModel.load(sc, "/home/zefu/BIA800/LRModel")
  model
}

var error=0.0
var size=0.0
implicit def bool2int(b:Boolean) = if (b) 1 else 0
def updateState(batchTime: Time, key: String, value: Option[String], state: State[Array[Double]]): Option[(String, Double,Double)] = {
  val model=loadingModel(sc)
  val parts = value.getOrElse("0,0,0,0").split(",").map { _.toDouble }
  val pairs = LabeledPoint(parts(0), Vectors.dense(parts.tail))
  val prediction = model.predict(pairs.features)
  val wrong= prediction != pairs.label
  error = state.getOption().getOrElse(Array(0.0,0.0))(0) + 1.0*(wrong:Int)
  size=state.getOption().getOrElse(Array(0.0,0.0))(1) + 1.0
  val output = (key, error,size)
  state.update(Array(error,size))
  Some(output)
}
val stateSpec = StateSpec.function(updateState _)
  .numPartitions(1)
setupLogging()
val kafkaParams = Map("metadata.broker.list" -> "localhost:9092")
val topics = List("test").toSet
val lines = KafkaUtils.createDirectStream[String, String, StringDecoder, StringDecoder](
  ssc, kafkaParams, topics).mapWithState(stateSpec)

当我运行此代码时,会出现这样的异常

Exception in thread "main" org.apache.spark.SparkException: Task not serializable

如果您需要更多信息,请告诉我们。 谢谢!

1 个答案:

答案 0 :(得分:0)

当在DStream函数中使用模型时,spark似乎序列化上下文对象(因为模型的加载函数使用sc),并且它失败,因为上下文对象不可序列化。一种解决方法是将DStream转换为RDD,收集结果,然后在驱动程序中运行模型预测/评分。

使用netcat实用程序来模拟流,尝试使用以下代码将DStream转换为RDD,它可以工作。看看它是否有帮助。

val ssc = new StreamingContext(sc,Seconds(10))
val lines = ssc.socketTextStream("xxx", 9998)
val linedstream = lines.map(lineRDD =>  Vectors.dense(lineRDD.split(" ").map(_.toDouble)) )
val logisModel = LogisticRegressionModel.load(sc, /path/LR_Model")
linedstream.foreachRDD( rdd => {
    for(item <- rdd.collect().toArray) {
    val predictedVal = logisModel.predict(item)
        println(predictedVal + "|" + item);
    }
})

理解收集在此处不可扩展,但如果您认为您的流式传输消息的数量较少,则可能是一个选项。这是我在Spark 1.4.0中看到的可能,更高版本可能有一个修复。如果它有用,请看这个

Save ML model for future usage