我需要序列化 scikit-learn/statsmodels 模型,以便将所有依赖项(代码 + 数据)打包在一个人工制品中,并且该人工制品可用于初始化模型并进行预测。使用 picklemodule
不是一个选项,因为这只会处理数据依赖关系(代码不会被打包)。所以,我一直在用Dill进行实验。为了使我的问题更准确,以下是我构建模型并将其持久化的示例。
from sklearn import datasets
from sklearn import svm
from sklearn.preprocessing import Normalizer
import dill
digits = datasets.load_digits()
training_data_X = digits.data[:-5]
training_data_Y = digits.target[:-5]
test_data_X = digits.data[-5:]
test_data_Y = digits.target[-5:]
class Model:
def __init__(self):
self.normalizer = Normalizer()
self.clf = svm.SVC(gamma=0.001, C=100.)
def train(self, training_data_X, training_data_Y):
normalised_training_data_X = normalizer.fit_transform(training_data_X)
self.clf.fit(normalised_training_data_X, training_data_Y)
def predict(self, test_data_X):
return self.clf.predict(self.normalizer.fit_transform(test_data_X))
model = Model()
model.train(training_data_X, training_data_Y)
print model.predict(test_data_X)
dill.dump(model, open("my_model.dill", 'w'))
与此相对应,这是我如何初始化持久模型(在新会话中)并进行预测。请注意,此代码没有显式初始化或了解class Model
.
import dill
from sklearn import datasets
digits = datasets.load_digits()
training_data_X = digits.data[:-5]
training_data_Y = digits.target[:-5]
test_data_X = digits.data[-5:]
test_data_Y = digits.target[-5:]
with open("my_model.dill") as model_file:
model = dill.load(model_file)
print model.predict(test_data_X)
有没有人用过莳萝是这样的?这个想法是让数据科学家为ModelWrapper class
他们实现的每个模型扩展一个,然后围绕这个构建基础架构,以保持模型、将模型部署为服务并管理模型的整个生命周期。
class ModelWrapper(object):
__metaclass__ = abc.ABCMeta
def __init__(self, model):
self.model = model
@abc.abstractmethod
def predict(self, input):
return
def dumps(self):
return dill.dumps(self)
def loads(self, model_string):
self.model = dill.loads(model_string)
除了安全隐患(任意代码执行)和模块scikit-learn
必须安装在为模型服务的机器上的要求之外,这种方法是否存在任何其他缺陷?任何意见或建议将是最有帮助的。