Python模型本地持久化存储

Python模型本地持久化存储

通常我们线下训练好的模型,部署到线上运行,这就需要把模型进行本地硬盘持久化,比如保持到文件中,然后再在其他主机上导入内存进行分类和预测。下面就介绍几种模型持久化存储方法。

1. pickle模块

pickle是python标准模块,一种标准的序列化对象的方法。你可以使用pickle操作来序列化你的任何类对象,当然也包括机器学习模型,保存这种序列化的格式到一个文件中。需要的时候,你可以在这个存储文件中反序列化你的对象(模型),用它进行新的对象处理(分类或预测)。示例如下:如何使用Pima Indians onset of diabetes数据集,训练一个logistic回归模型,保存模型到文件,导入模型对未知数据进行预测。运行以下代码把模型存入你工作路径中的finalized_model.sav,导入模型,用未知数据评估模型的准确率。

pickle模块提供了以下函数对:dumps(object)返回一个字符串,它包含了一个pickle格式的对象;loads(string)返回包含在pickle字符串中的对象;dump(object,file)将对象写到文件,这个文件可以是实际的物理文件,也可以是类似于文件的对象,这个对象具有write()方法,可以接受单个的字符串参数;load(file)返回包含在pickle文件中对象。

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

# Save Model Using Pickle
import pandas
from sklearn import model_selection
from sklearn.linear_model import LogisticRegression
import pickle
url = "https://archive.ics.uci.edu/ml/machine-learning-databases/pima-indians-diabetes/pima-indians-diabetes.data"
names = ['preg', 'plas', 'pres', 'skin', 'test', 'mass', 'pedi', 'age', 'class']
dataframe = pandas.read_csv(url, names=names)
array = dataframe.values
X = array[:,0:8]
Y = array[:,8]
test_size = 0.33
seed = 7
X_train, X_test, Y_train, Y_test = model_selection.train_test_split(X, Y, test_size=test_size, random_state=seed)
# Fit the model on 33%
model = LogisticRegression()
model.fit(X_train, Y_train)
# save the model to disk
filename = 'finalized_model.pkl'
pickle.dump(model, open(filename, 'wb'))

# some time later...

# load the model from disk
loaded_model = pickle.load(open(filename, 'rb'))
result = loaded_model.score(X_test, Y_test)
print(result)

2. joblib模块

joblib模块是sklean中专门用于保存机器学习模型。其可以用于存储参数很多,占空间很大的模型,比如KNN。其用法和pickle模块基本一致,主要就是dump和load函数:

# Save Model Using joblib
import pandas
from sklearn import model_selection
from sklearn.linear_model import LogisticRegression
from sklearn.externals import joblib
url = "https://archive.ics.uci.edu/ml/machine-learning-databases/pima-indians-diabetes/pima-indians-diabetes.data"
names = ['preg', 'plas', 'pres', 'skin', 'test', 'mass', 'pedi', 'age', 'class']
dataframe = pandas.read_csv(url, names=names)
array = dataframe.values
X = array[:,0:8]
Y = array[:,8]
test_size = 0.33
seed = 7
X_train, X_test, Y_train, Y_test = model_selection.train_test_split(X, Y, test_size=test_size, random_state=seed)
# Fit the model on 33%
model = LogisticRegression()
model.fit(X_train, Y_train)
# save the model to disk
filename = 'finalized_model.m'
joblib.dump(model, filename)

# some time later...

# load the model from disk
loaded_model = joblib.load(filename)
result = loaded_model.score(X_test, Y_test)
print(result)

注意点

1. python的版本:记录下python的版本。需要相同大版本号的python来序列化和反序列化模型。
2. 库的版本:主要的库的版本要保持一致,不仅限于Numpy和scikit-learn的版本。
3. 手动序列化:你可能想要手动的输出你的模型参数以便于你可以直接把他们用在scikit-learn或者其他的平台。确实学习算法参数实现比算法本身实现要难得多。如果你有能力也可以自己写代码来导出参数。

4. 保存文件名:一般pickle模块保存为.pkl后缀,而joblib模块保存为.m后缀。实际上并无严格要求,只是文件名,其实任何后缀名都可以。但是如果我们私下统一的话,代码的可阅读性强,更加规范。

5. 上述两个模块用于模型持久化操作区别不大,都是sklearn官方推荐用法。

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

但是既然有了pickle模块,sklearn又设计了joblib,应该有性能和存储大小的优势。实际测试发现:在序列化的时候,joblib库和pickle库时间差不多,好像pickle要快一丢丢。而反序列化时,joblib库和pickle库要快好几个数量级。而且joblib的存储模型比pickle库小一半(这个测试不够准确,只用了一个很小的模型,仅用于参考。但是基本的大小比较应该可以看出来)

joblib对于sklearn使用的NumPy数组特别适用,因此使用joblib可能会有性能和大小方面的好处。

6. 他们实际上使用相同的序列化协议。查看documentationjoblib.dump - 您可以使用参数joblib指定pickle压缩级别。

7. java调用。如果你用python训练模型之后,交给技术部门是用java正式上线运行,此时joblib就不行了。推荐使用pmml,github上有sklearn to pmml的模块可以免费使用,强烈推荐。(复制的自己没有用过)

8. pickle不提供安全保证。如果你在多线程通信(inter-process communication)或者数据存储或存储数据中使用pickle。joblib更适合大数据量的模型,且只能往硬盘存储,不能往字符串对象里存储。

9. 还有cPickle库可以用,效率更高。下面是官网对其介绍:这个库比pickle更快,有更好的性能。(1)比pickle快100倍,因为用c实现。(2)Pickler() and Unpickler()是函数,而不是类,所以你不能继承出子类来进行扩展自定义功能。但是大多数的场景不需要如此,但是这样做提高了很多性能。(3)pickle和cpickle的序列化协议相同,因此可以相互替代,格式完全相同。(4)pickle和cpickle在API调用上有些小的差别。

10. 主要函数:

  1. pickle.dump, pickle.load
  2. joblib.dump, joblib.load

没有更多推荐了,返回首页