Spark Streaming:如何实现自定义流式处理算法?

时间:2017-05-21 13:26:29

标签: python apache-spark pyspark regression spark-streaming

我一般都是Spark的新手,所以我想测试一下Spark Streaming的一些功能,我可能需要另外一个更大的项目。

我的玩具问题是我想处理一个流并学习随机梯度下降的线性回归(我知道已经提供了StreamingLinearRegression,但我想自己实现它):

class OnlineLinearRegression:
    def __init__(self, eta=0.1, nr_features=8):
        self.w = np.zeros(nr_features)
        self.nr_features = nr_features
        self.eta = eta

    def evaluate(self, x):
        return np.dot(self.w, x)

    def loss(self, pred, true_value):
        loss = (pred-true_value)*(pred-true_value)
        return loss

    def update_model(self, x, pred, y):
        bef_update = self.w
        self.w = self.w - self.eta * (pred - y) * np.array(x)
        print "=========================="
        print "UPDATE MODEL"
        print "self id " + str(id(self))
        print "w_before_update " + str(bef_update)
        print "w_after_update " + str(self.w)
        print "=========================="

    def prequential(self, e):
        y_hat = self.evaluate(e[0])
        ell = self.loss(y_hat, e[1])
        self.update_model(e[0], y_hat, e[1])
        return ell

    def processRDD(self, time, RDD):
        RDD.foreach(self.prequential)

我的主要方法如下:

if __name__ == "__main__":
    model = OnlineLinearRegression(eta=0.1,nr_features=8)
    print "ID-MODEL-CREATED: " + str(id(model))

    sc = SparkContext("local[*]", "Test Scenario")
    ssc = StreamingContext(sc, 0.5)

    text = ssc.socketTextStream("localhost", 9997)
    tuples = text.map(parser)
    tuples.foreachRDD(model.processRDD)

    ssc.start()
    ssc.awaitTermination() 

每秒生成一次数据,Spark Streaming的间隔为一秒(因此只处理一个样本/批次)。以下是OnlineLinearRegression update_model函数中生成的一些输出:

一旦开始:

ID-MODEL-CREATED:140184763844800

1。样品

  • self id 140411103203200

  • w_before_update [0. 0. 0. 0. 0. 0. 0. 0。]

  • w_after_update [0. 0.6825 0.5475 0.1425 0.771 0.33675 ​​0.1515 0.225]

2。样品

  • self id 140411106740920

  • w_before_update [0. 0. 0. 0. 0. 0. 0. 0。]

  • w_after_update [0。0.245 0.1855 0.063 0.15785 0.06965 0.03395 0.049]

第3。样本

  • self id 140411106740704

  • w_before_update [0. 0. 0. 0. 0. 0. 0. 0。]

  • w_after_update [1.8 0.477 0.378 0.1215 0.6093 0.23085 0.12735 0.189]

4。样本

  • self id 140411106738904

  • w_before_update [0. 0. 0. 0. 0. 0. 0. 0。]

  • w_after_update [0. 0.44 0.365 0.125 0.516 0.2155 0.114 0.155]

5。样品

  • self id 140411106738904(评论:与4中的ID相同,但是w仍然没有改变)

  • w_before_update [0. 0. 0. 0. 0. 0. 0. 0。]

  • w_after_update [0.7 0.231 0.1785 0.056 0.1435 0.06265 0.02765 0.0385]

我的问题:

  1. 为什么self_ids会发生变化,但同时有时会保持不变?我认为这是w仍为零向量的原因。但是__init__只被调用一次。

  2. 我对Spark有什么误解,有什么方法可以解决这个问题,以便我有一个迭代操作的全局模型?

  3. 非常感谢。

    修改:将tuples.foreachRDD(model.processRDD)更改为tuples.map(model.prequential)没有帮助,输出类似(出现相同问题)。

1 个答案:

答案 0 :(得分:0)

尝试在单核上运行spark。问题在于与不同的工作人员共享模型(在您的案例核心中)。

以下是您为每批产品进行分布式处理的方法:

  • 使模型成为广播变量。
  • 每次更新都有Unpersist(blocking = true)。
  • 重播它。

为每个其他记录(示例/示例)广播它可能会导致大量网络流量延迟。您可以将每个批次视为样本数据(来自整个群体),并找到该数据最小的权重。然后使用该值更新模型。您可以更详细地阅读In Docker, how can I share files between containers and then save them to an image?

您可以进一步探索here