使用PySpark在数据框架上应用sklearn训练的模型

时间:2017-05-31 13:14:50

标签: python apache-spark scikit-learn pyspark

我使用Python训练了一个随机森林算法,并希望将它应用于PySpark的大数据集。

我首先加载了训练有素的sklearn RF模型(使用joblib),将包含这些功能的数据加载到Spark数据帧中,然后添加一个包含预测的列,并使用用户定义的函数:

def predictClass(features):
    return rf.predict(features)
udfFunction = udf(predictClass, StringType())
new_dataframe = dataframe.withColumn('prediction', 
udfFunction('features'))

它需要花费很多时间才能运行,是否有更有效的方法来做同样的事情? (不使用Spark ML)

3 个答案:

答案 0 :(得分:2)

在最近的项目中,我不得不做同样的事情。对于pyspark每次必须读取sklearn模型的每一行都应用udf的坏事,这就是为什么要花很多时间才能完成的原因。我发现的最佳解决方案是在rdd上使用.mapPartitions或foreachPartition方法,此处的确是一个很好的解释

https://github.com/mahmoudparsian/pyspark-tutorial/blob/master/tutorial/map-partitions/README.md

它之所以能够快速运行,是因为它确保您没有改组,并且对于每个分区pyspark都必须读取模型并仅预测一次。因此,流程为:

  • 将DF转换为RDD
  • 将模型广播到节点,以便工作人员可以访问
  • 编写一个以插入程序(包含分区中的所有行)为参数的udf函数
  • 遍历行并使用您的特征(顺序很重要)创建合适的矩阵
  • 只调用一次。predict一次
  • 收益预测
  • 根据需要将rdd转换为df

答案 1 :(得分:0)

sklearn RF模型在酸洗时可能会非常大。在任务调度期间频繁的模型挖掘/解开可能会导致问题。您可以考虑使用广播变量。

来自official document

  

广播变量允许程序员在每台机器上保留一个只读变量,而不是随副本一起发送它的副本。例如,它们可用于以有效的方式为每个节点提供大输入数据集的副本。 Spark还尝试使用高效的广播算法来分发广播变量,以降低通信成本。

答案 2 :(得分:0)

现在,您还可以使用spark 2.3中引入的pandas_udf,以实现较高的处理速度和分布式计算。它基于pyarrow用于内存中计算的 Apache Arrow 的python实现。