保存ML模型以备将来使用
Posted
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了保存ML模型以备将来使用相关的知识,希望对你有一定的参考价值。
我正在将一些机器学习算法(如线性回归,Logistic回归和朴素贝叶斯)应用于某些数据,但我试图避免使用RDD并开始使用DataFrame,因为RDDs are slower比pyspark下的Dataframes(见图1)。
我使用DataFrames的另一个原因是因为ml库有一个非常有用的类来调整模型,这是CrossValidator这个类在适合它之后返回一个模型,显然这个方法必须测试几个场景,然后返回一个fitted model(带参数的最佳组合)。
我使用的集群不是那么大,数据相当大,有些适合需要几个小时,所以我想保存这些模型以便以后重用它们,但我还没有意识到,有什么我忽略的东西?
笔记:
- mllib的模型类有一个保存方法(即NaiveBayes),但mllib没有CrossValidator并使用RDD,所以我有预谋地避免它。
- 目前的版本是spark 1.5.1。
Spark 2.0.0+
乍一看,所有Transformers
和Estimators
都使用以下界面实现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
和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
函数,但截至今天,这些函数与其他支持的语言不兼容 - 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 Pipelines非常有用,并且交叉验证器或不同评估器等工具在任何机器管道中都是必须的,即使上述任何一个都没有特别难以在低级MLlib API上实现,最好还是准备好使用,通用和相对良好测试的解决方案。
到目前为止一直很好,但有一些问题:
- 据我所知,
DataFrames
或select
等withColumn
上的简单操作显示出类似于map
等RDD等价物的性能, - 在某些情况下,与调整好的低级转换相比,增加典型管道中的列数实际上会降低性能。您当然可以在正确的方式上添加drop-column-transformer,
- 许多ML算法,包括围绕其
ml.classification.NaiveBayes
API的are simply wrappersmllib
, - PySpark ML / MLlib算法将实际处理委托给Scala对应物,
- 最后但并非最不重要的是RDD仍然在那里,即使隐藏在DataFrame API背后
我相信在一天结束时,使用ML而不是MLLib可以获得相当优雅的高级API。您可以做的一件事是将两者结合起来创建一个自定义的多步骤管道:
- 使用ML加载,清理和转换数据,
- 提取所需数据(参见例如extractLabeledPoints方法)并传递给
MLLib
算法, - 添加自定义交叉验证/评估
- 使用您选择的方法保存
MLLib
模型(Spark模型或PMML)
它不是最佳解决方案,但鉴于当前的API,它是我能想到的最佳解决方案。
似乎保存模型的API功能现在还没有实现(参见Spark issue tracker SPARK-6725)。
发布了一个替代方案(How to save models from ML Pipeline to S3 or HDFS?),它简单地序列化了模型,但它是一种Java方法。我希望在PySpark中你可以做类似的事情,即腌制模型写入磁盘。
以上是关于保存ML模型以备将来使用的主要内容,如果未能解决你的问题,请参考以下文章