保存 ML 模型以备将来使用

Save ML model for future usage

我正在对某些数据应用一些机器学习算法,如线性回归、逻辑回归和朴素贝叶斯,但我试图避免使用 RDD 并开始使用 DataFrames,因为 RDDs are slower 比 pyspark 下的 Dataframes (见图 1)。

我使用 DataFrames 的另一个原因是因为 ml 库有一个 class 对调整模型非常有用,它是 CrossValidator this class returns a model after fitting it, obviously this method has to test several scenarios, and after that returns a fitted model(具有最佳参数组合)。

我使用的集群不是很大,数据也很大,有些拟合需要几个小时,所以我想保存这个模型以便以后重用,但我还没有意识到如何,我有什么东西吗忽略?

备注:

似乎 API 保存模型的功能到今天还没有实现(参见 Spark issue tracker SPARK-6725)。

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

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 / JavaMLWritable and MLReadable / 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 functions, but as of today, these are not compatible with other supported languages - SPARK-15572.

请注意,加载程序 class 必须与存储的 PipelineStage 的 class 相匹配。例如,如果您保存了 LogisticRegressionModel,您应该使用 LogisticRegressionModel.load 而不是 LogisticRegression.load

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

除了 Spark 特定方法之外,还有越来越多的库旨在使用 Spark 独立方法保存和加载 Spark ML 模型。例如参见 [​​=48=].

Spark >= 1.6

从 Spark 1.6 开始,可以使用 save 方法保存模型。因为几乎每个 model 实现 MLWritable interface. For example, LinearRegressionModel 都有它,因此可以使用它来将模型保存到所需的路径。

Spark < 1.6

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

可以优化 DataFrames 上的一些操作,与普通 RDDs 相比,它转化为改进的性能。 DataFrames 提供高效的缓存和 SQLish API 可以说比 RDD API 更容易理解。

ML 管道非常有用,交叉验证器或不同的评估器等工具在任何机器管道中都是必备的,即使上述 none 在低级 MLlib 之上实现特别困难API 最好有现成的、通用的和经过相对良好测试的解决方案。

到目前为止一切顺利,但存在一些问题:

  • 据我所知,在 DataFrames 上的简单操作,如 selectwithColumn 显示与其 RDD 等效项(如 map、[=102=)相似的性能]
  • 在某些情况下,与调整良好的低级转换相比,增加典型管道中的列数实际上会降低性能。您当然可以在纠正该问题的途中添加下降列变换器,
  • 许多 ML 算法,包括 ml.classification.NaiveBayes are simply wrappers mllib API,
  • PySpark ML/MLlib 算法将实际处理委托给它的 Scala 算法,
  • 最后但同样重要的是,RDD 仍然存在,即使很好地隐藏在 DataFrame 后面 API

我相信最终通过使用 ML 而不是 MLLib 得到的结果是相当优雅的、高级的 API。您可以做的一件事是将两者结合起来创建一个自定义的多步骤管道:

  • 使用 ML 加载、清理和转换数据,
  • 提取所需数据(参见 extractLabeledPoints 方法示例)并传递给 MLLib 算法,
  • 添加自定义交叉验证/评估
  • 使用您选择的方法保存 MLLib 模型(Spark 模型或 PMML

这不是最佳解决方案,但在给定当前 API.

的情况下,这是我能想到的最佳解决方案