【发布时间】:2020-01-13 05:51:32
【问题描述】:
我正在尝试腌制一个 sklearn 机器学习模型,并将其加载到另一个项目中。该模型包含在管道中,该管道执行特征编码、缩放等。当我想在管道中使用自写转换器来执行更高级的任务时,问题就开始了。
假设我有 2 个项目:
- train_project:它在 src.feature_extraction.transformers.py 中有自定义转换器
- use_project:src中有其他东西,或者根本没有src目录
如果在“train_project”中我使用 joblib.dump() 保存管道,然后在“use_project”中使用 joblib.load() 加载它,它将找不到诸如“src.feature_extraction.transformers”之类的内容并抛出例外:
ModuleNotFoundError: 没有名为“src.feature_extraction”的模块
我还应该补充一点,我从一开始的意图是简化模型的使用,因此程序师可以像加载任何其他模型一样加载模型,传递非常简单、人类可读的特征,以及对实际特征的所有“魔法”预处理模型(例如梯度提升)正在内部发生。
我想在两个项目的根目录中创建 /dependencies/xxx_model/ 目录,并在其中存储所有需要的类和函数(将代码从“train_project”复制到“use_project”),因此项目的结构是相同的,并且转换器可以被加载。我发现这个解决方案非常不优雅,因为它会强制使用该模型的任何项目的结构。
我想只是在“use_project”中重新创建管道和所有变压器,并以某种方式从“train_project”加载变压器的拟合值。
最好的解决方案是,如果转储文件包含所有需要的信息并且不需要依赖项,我真的很震惊 sklearn.Pipelines 似乎没有这种可能性 - 如果我无法加载安装管道,那么安装管道有什么意义后来反对?是的,如果我只使用 sklearn 类而不创建自定义类,它会起作用,但非自定义类没有所有需要的功能。
示例代码:
train_project
src.feature_extraction.transformers.py
from sklearn.pipeline import TransformerMixin
class FilterOutBigValuesTransformer(TransformerMixin):
def __init__(self):
pass
def fit(self, X, y=None):
self.biggest_value = X.c1.max()
return self
def transform(self, X):
return X.loc[X.c1 <= self.biggest_value]
train_project
main.py
from sklearn.externals import joblib
from sklearn.preprocessing import MinMaxScaler
from src.feature_extraction.transformers import FilterOutBigValuesTransformer
pipeline = Pipeline([
('filter', FilterOutBigValuesTransformer()),
('encode', MinMaxScaler()),
])
X=load_some_pandas_dataframe()
pipeline.fit(X)
joblib.dump(pipeline, 'path.x')
测试项目
main.py
from sklearn.externals import joblib
pipeline = joblib.load('path.x')
预期的结果是管道正确加载了可以使用的转换方法。
加载文件时实际结果是异常。
【问题讨论】:
-
我也有同样的问题,我会分享我到目前为止所尝试的。交换 joblib,pickle 。重新导入我的自定义 featureUnion 子类。如果您想出出路,请在此处发布。
标签: python scikit-learn persistence pipeline joblib