机器学习模型序列化

目录

1 pickle

2 joblib

3 安全性和可维护性的局限性

4 Interoperable formats 可互操作的格式


        机器学习过程分为训练过程和预测过程。训练过程得到一个模型,预测过程得到预测结果。为了节省时间,最好能够在每次执行预测时,调用已经构造好的模型,而不是每次预测前都需要重新训练一次模型。以“决策树”为例,最好能够在每次执行分类时调用已经构造好的决策树。

        本文将使用两种方法来实现模型的保存和加载:Pickle和joblib。

  • 不跨平台使用时,可以用Pickle和joblib,例如可以用joblib.dump进行模型持久化为pkl文件;
  • 跨平台使用时可以使用ONNX与PMML,例如根据sklearn2pmml转成pmml文件,通过jpmml去部署到线上。

pickle和joblib的区别:

  • joblib为sklearn自带的工具,做了很多的优化,对于大数据而言,joblib比pickle更高效,而joblib只能将对象存储在磁盘文件中,不能保存为字符串。
  • pickle较慢,在序列化的时候很吃内存,如果数据较大,有可能pickle的时候内存溢出了。

1 pickle

  • pickle.dumps(obj) — 把 obj 对象序列化后以 bytes 对象返回,不写入文件;
  • pickle.loads(bytes_object) — 从 bytes 对象中读取一个反序列化对象,并返回其重组后的对象;
  • pickle.dump(obj , file) — 序列化对象,并将结果数据流写入到文件对象中,这个文件可以是实际的物理文件,也可以是类似于文件的对象,这个对象具有write()方法,可以接受单个的字符串参数;
  • pickle.load(file) — 反序列化对象,将文件中的数据解析为一个Python对象;

        缺省情况下,dumps()和dump()使用可打印的ASCII表示来创建pickle。两者都有一个final参数,这个参数是可选的,若这个参数为True,则该参数指定用更快更小的二进制表示来创建pickle。loads()和load()则会自动检测pickle是二进制格式还是文本格式。在实际使用复杂对象的系统中,使用二进制格式可以在大小和速度方面带来显著的改进。

from sklearn import svm
from sklearn import datasets
clf = svm.SVC()
X, y= datasets.load_iris(return_X_y=True)
clf.fit(X, y)

import pickle
# 不写入文件
s = pickle.dumps(clf)
clf2 = pickle.loads(s)
clf2.predict(X[0:1])

y[0]

# 写入文件
#保存模型
model_file = 'final_model.sav'
with open(clf,'wb') as model_f:
    #序列化
    dump(model,model_f)
#加载模型
with open(clf,'rb') as model_f:
    #反序列化
    loaded_model = load(model_f)
    result = loaded_model.score(X_test,Y_test)
    print(result)

2 joblib

joblib模块是机器学习库SciPy的一部分,它提供很多使Python作业pipeline的方法。

同时,它也提供了用于保存、加载NumPy数据变量、机器学习模型的方法。这对于需要保存大量训练参数、存储整个数据集的某些机器学习算法(如K近邻)非常有用。

对于大数据而言,joblib比pickle更加高效,但是joblib只能将对象存储在磁盘文件中,不能保存为字符串。

#加载模块
from sklearn import datasets
from sklearn.externals import joblib
from sklearn.linear_model import LinearRegression
from sklearn.cross_validation import train_test_split
#分割数据集
data_x,data_y = datasets.load_iris(return_X_y=True)
train_X,test_X,train_y,test_y = train_test_split(data_x,data_y,test_size=0.2,random_state=2,stratify=data_y)
#训练模型
lr = LinearRegression()
lr.fit(train_X,train_y)

#将训练的模型保存
direction = joblib.dump(lr,"H:/lr_model_20180911.pkl")

#下载模型
lr = joblib.load("".join(direction))
#模型预测
lr.predict(test_X)
#重新设置模型参数并训练
lr.set_params(normalize=True).fit(train_X,train_y)
#新模型做预测
lr.predict(test_X)

3 安全性和可维护性的局限性

pickle(和通过扩展的 joblib),在安全性和可维护性方面存在一些问题。 有以下原因,

  • 安全性:绝对不要使用未经 pickle 的不受信任的数据,因为它可能会在加载时执行恶意代码。
  • 不一定兼容,虽然一个版本的 scikit-learn 模型可以在其他版本中加载,但这完全不建议并且也是不可取的。 还应该了解到,对于这些数据执行的操作可能会产生不同及意想不到的结果。

为了用以后版本的 scikit-learn 来重构类似的模型, 额外的元数据应该随着 pickled model 一起被保存:

  • 训练数据,例如:引用不可变的快照
  • 用于生成模型的 python 源代码
  • scikit-learn 的各版本以及各版本对应的依赖包
  • 在训练数据的基础上获得的交叉验证得分

这样可以检查交叉验证得分是否与以前相同。

由于模型内部表示可能在两种不同架构上不一样,因此不支持在一个架构上转储模型并将其加载到另一个体系架构上。为了克服可移植性问题,通常在生产环境中使用诸如docker之类的容器来部署pickle模型。

不完全支持Joblib序列化在python版本之间的兼容性。请注意,对于一组非常有限的对象,当使用python 2保存一个pickle并用python 3加载它时,这似乎可以工作,但是强烈建议不要依赖它。

如果要在python版本之间切换,则需要为每个python版本保存不同的joblib pickle。

在保存、加载模型时,需要注意以下常见问题:

  • Python版本。可以肯定的是,当加载并反序列化模型时,需要使用相同版本的Python来序列化模型。
  • 库版本。在反序列化已保存的模型时,使用机器学习库的版本需要相同,包括NumPy版本和scikit-learn版本。
  • 手动序列化。有时候可能需要手动输出模型的参数,以便将来可以直接在scikit-learn或其他平台中使用它们。通常,在机器学习中,用于预测的算法比用于学习参数的算法简单得多,可以很容易地在代码中实现。当版本不同时,请重新安装对应版本进行模型加载,否则,你将遇到一些奇奇怪怪的问题。

4 Interoperable formats 可互操作的格式,ONNX、PMML

        为了满足可重复性和质量控制的需要,当考虑不同的体系结构和环境时,以开放神经网络交换(ONNX)格式或预测模型标记语言(PMML)格式导出的模型可能比单独使用 pickle更好。在您希望将模型用于与训练模型不同的环境中进行预测的情况下,这些方法很有用。

        ONNX是模型的二进制序列化。开发它是为了提高数据模型的可互操作表示的可用性。它旨在促进数据模型在不同机器学习框架之间的转换,并提高它们在不同计算体系结构上的可移植性。有关更多详细信息,请参阅ONNX教程。为了将scikit-learn模型转换为ONNX,已经开发了特定工具sklearn-onnx

       PMML是XML文档标准的实现,该XML文档标准定义为表示数据模型以及用于生成数据模型的数据。PMML具有人机可读性,是在不同平台上进行模型验证和长期归档的不错选择。另一方面,作为XML,当性能至关重要时,它的冗长性对生产没有帮助。要将scikit-learn模型转换为PMML,您可以使用例如根据Affero GPLv3许可发行的sklearn2pmml

ONNX和PMML都是与平台和环境无关的模型表示标准,可以让模型部署脱离模型训练环境,简化了部署流程,加速模型快速上线到生产环境中。这两个标准都得到了各大厂商和框架的支持,具有广泛的应用。

  • PMML是一个比较成熟的标准,在ONNX诞生之前,可以说是模型表示的实际标准,对传统数据挖掘模型有丰富的支持,最新 PMML4.4 可以支持多达19种模型类型。但是,目前PMML缺乏对深度学习模型的支持,下一版本5.0有可能会添加对深度神经网络的支持,但是因为PMML是基于老式的XML格式,使用文本格式来存储深度神经网络模型结构和参数会带来模型大小和性能的问题,目前该问题还没有一个完美的解决方案。关于PMML的详细介绍,可以参考文章《使用PMML部署机器学习模型》
  • ONNX作为一个新的标准,刚开始主要提供对深度神经网络模型的支持,解决模型在不同框架下互操作和交换的问题。目前通过ONNX-ML,ONNX已经可以支持传统非神经网络机器学习模型,但是目前模型类型还不够丰富。ONNX使用protobuf二进制格式来序列化模型,可以提供更好的传输性能。

       ONNX和PMML这两种格式都有成熟的开源类库和框架支持,PMML有JPMMLPMML4SPyPMML等。ONNX有微软的ONNX runtimeNVIDIA TensorRT等。用户可以根据自己的实际情况选择合适的跨平台格式来部署AI模型。

Java PMML API:https://github.com/jpmml/

5 机器学习模型上线

5.1 可行的机器学习模型线上serving的方法

机器学习模型如何上线或者online学习?:https://www.zhihu.com/question/37426733

一、自研平台

二、预训练embedding+轻量级模型

三、PMML

四、TensorFlow Serving等原生serving平台

五、TensorFlow Serving的二次开发

5.2 美团一站式机器学习平台建设实践

美团:一站式机器学习平台建设实践https://tech.meituan.com/2020/01/23/meituan-delivery-machine-learning.html

        目前业界比较优秀的机器学习平台有很多,既有大公司研发的商用产品,如微软的Azure亚马逊的SageMaker阿里的PAI平台百度的PaddlePaddle以及腾讯的TI平台,也有很多开源的产品,如加州大学伯克利分校的Caffe、Google的TensorFlow、Facebook的PyTorch以及Apache的Spark MLlib等。而开源平台大都是机器学习或者深度学习基础计算框架,聚焦于训练机器学习或深度学习模型;公司的商用产品则是基于基础的机器学习和深度学习计算框架进行二次开发,提供一站式的生态化的服务,为用户提供从数据预处理模型训练模型评估模型在线预测的全流程开发和部署支持,以期降低算法同学的使用门槛。

        平台化阶段:

        为了避免各部门重复造轮子,提升研发的效率,同时统一业务指标和特征的计算口径,标准化配送侧的数据体系,美团配送的研发团队组建了一个算法工程小组,专门规整各业务线的机器学习工具集,希望建设一个统一的机器学习平台,其需求主要包括以下几个方面:

        平台化阶段,我们对美团配送机器学习平台的目标定位是:一站式机器学习平台,给算法同学提供一站式服务,覆盖算法同学调研、开发、上线、评估算法效果的全流程,包括:数据处理特征生产样本生成模型训练模型评估模型发布在线预测效果评估。为了响应这个目标,大家还给平台取了个大胆的名字——Turing,中文名称为图灵平台,虽然有点“胆大包天”,但是也算是对我们团队的一种鞭策。

1)首先在获取数据阶段,支持在线离线两个层面的处理,分别通过采样、过滤、归一化、标准化等手段生产实时和离线特征,并推送到在线的特征库,供线上服务使用。

2)模型训练阶段,支持分类、回归、聚类、深度学习等多种模型,并支持自定义Loss损失函数。

3)模型评估阶段,支持多种评估指标,如AUC、MSE、MAE、F1等。

4)模型发布阶段,提供一键部署功能,支持本地和远程两种模式,分别对应将模型部署在业务服务本地和部署在专用的在线预测集群

5)在线预测阶段,支持AB实验,灵活的灰度发布放量,并通过统一埋点日志实现AB实验效果评估。

(1) 离线训练平台:

(2)模型管理平台

        图灵平台集成了Spark ML、XGBoost、TensorFlow三种底层训练框架,基于此,我们的训练平台产出的机器学习模型种类也非常多,简单的有LR、SVM,树模型有GBDT、RF、XGB等,深度学习模型有RNN、DNN、LSTM、DeepFM等等。而我们的模型管理平台的目标就是提供统一的模型注册、发现、部署、切换、降级等解决方案,并为机器学习和深度学习模型提供高可用的线上预测服务。

        模型管理平台支持本地和远程两种部署模式:

  • 本地:模型和MLDL统一推送到业务方服务节点上,同时图灵平台提供一个Java的Lib包,嵌入到业务方应用中,业务方通过本地接口的方式调用模型计算

  • 远程:图灵平台维护了一个专用的在线计算集群,模型和MLDL统一部署到在线计算集群中,业务方应用通过RPC接口调用在线计算服务进行模型计算

(3)离线特征平台

        把各个离线特征作为K-V结构存储到Redis中,线上服务直接根据特征Key读取Redis获取特征Value。我们需要对离线特征从存储和获取进行优化。我们提出了特征组?的概念,同一维度的特征,按照特征组的结构进行聚合成一个KV,大大减少了Key的数目;并且提供了相对完善的管理功能,支持对特征组的动态调整(组装、拆分等)。

 

 

 

 

 

 

 

 

 

Model persistence:https://scikit-learn.org/stable/modules/model_persistence.html

Persistence:https://joblib.readthedocs.io/en/latest/persistence.html

模型持久化:http://scikitlearn.com.cn/0.21.3/33/

 

 

  • 0
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值