保存ML模型以备将来使用

时间:2015-10-08 23:50:01

标签: apache-spark pyspark apache-spark-mllib apache-spark-ml

我正在将一些机器学习算法(如线性回归,Logistic回归和Naive Bayes)应用于某些数据,但我试图避免使用RDD并开始使用DataFrame,因为RDDs are slower比pyspark下的Dataframes更多(参见pic 1)。

我使用DataFrames的另一个原因是因为ml库有一个非常有用的类来调整模型CrossValidator这个类在拟合之后返回一个模型,显然这个方法必须测试几个场景,并且之后返回fitted model(具有最佳参数组合)。

我使用的集群不是很大,而且数据非常大,有些需要花费数小时,所以我想保存这些模型以便以后再使用它们,但我还没有意识到如何,有什么东西我无视?

注意:

  • mllib的模型类有一个保存方法(即NaiveBayes),但mllib没有CrossValidator并使用RDD,所以我有预谋地避免它。
  • 目前的版本是spark 1.5.1。

2 个答案:

答案 0 :(得分:23)

Spark 2.0.0 +

乍一看,所有TransformersEstimators都通过以下界面实施MLWritable

def write: MLWriter
def save(path: String): Unit 
带有以下界面的

MLReadable

def read: MLReader[T]
def load(path: String): T

这意味着您可以使用save方法将模型写入磁盘,例如

import org.apache.spark.ml.PipelineModel

val model: PipelineModel
model.save("/path/to/model")

稍后阅读:

val reloadedModel: PipelineModel = PipelineModel.load("/path/to/model")

PySpark中也分别使用MLWritable / JavaMLWritableMLReadable / JavaMLReadable实现了等效方法:

from pyspark.ml import Pipeline, PipelineModel

model = Pipeline(...).fit(df)
model.save("/path/to/model")

reloaded_model = PipelineModel.load("/path/to/model")

SparkR提供write.ml / read.ml个功能,但截至今天,这些功能与其他受支持的语言不兼容 - SPARK-15572

请注意,loader类必须与存储的PipelineStage的类匹配。例如,如果您保存LogisticRegressionModel,则应使用LogisticRegressionModel.load而不是LogisticRegression.load

如果您使用Spark< = 1.6.0并遇到模型保存的一些问题,我建议您切换版本。

除Spark特定方法外,还有越来越多的库设计用于使用Spark独立方法保存和加载Spark ML模型。请参阅示例How to serve a Spark MLlib model?

Spark> = 1.6

从Spark 1.6开始,可以使用save方法保存模型。因为几乎每个model都实现了MLWritable接口。例如,LinearRegressionModel拥有它,因此可以使用它将模型保存到所需的路径。

Spark< 1.6

我相信你在这里做出了错误的假设。

DataFrames上的某些操作可以进行优化,与普通RDDs相比,可以提高性能。 DataFrames提供了有效的缓存,而且比RDD API更容易理解SQLish API。

ML管道非常有用,交叉验证器或不同评估器等工具在任何机器管道中都是必须的,即使上述任何一个都没有特别难以在低级别MLlib API上实现,它也要好得多。准备使用,通用和相对良好的测试解决方案。

到目前为止一直很好,但有一些问题:

  • 据我所知DataFrames select上的简单操作,withColumnmap显示与其类似ml.classification.NaiveBayes
  • 等RDD等效类似的效果
  • 在某些情况下,与经过良好调整的低级转换相比,增加典型管道中的列数实际上会降低性能。您当然可以在正确的方式上添加drop-column-transformers,
  • 许多ML算法,包括围绕其mllib API的MLLib are simply wrappers
  • PySpark ML / MLlib算法将实际处理委托给其Scala对应物,
  • 最后但并非最不重要的是RDD仍在那里,即使隐藏在DataFrame API背后

我相信在一天结束时使用ML而不是MLLib所获得的是非常优雅的高级API。您可以做的一件事是将两者结合起来创建一个自定义的多步骤管道:

  • 使用ML加载,清理和转换数据,
  • 提取所需数据(请参阅示例extractLabeledPoints方法)并传递给MLLib算法,
  • 添加自定义交叉验证/评估
  • 使用您选择的方法保存<td> <button class="btn btn-primary" onclick='openModel(<?php echo"id=$row[id]";?>') >View Details</button> </td> 模型(Spark模型或PMML

这不是最佳解决方案,但鉴于当前的API,它是我能想到的最佳解决方案。

答案 1 :(得分:5)

似乎现在没有实现保存模型的API功能(请参阅Spark issue tracker SPARK-6725)。

发布了一个替代方案(How to save models from ML Pipeline to S3 or HDFS?),其中只涉及序列化模型,但它是一种Java方法。我希望在PySpark中你可以做类似的事情,即挑选模型写入磁盘。