我正在尝试腌制sklearn机器学习模型,并将其加载到另一个项目中。该模型包装在具有编码,缩放等功能的管道中。当我想在管道中使用自写转换器执行更高级的任务时,问题就开始了。
假设我有2个项目:
如果在“ 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感到震惊。管道似乎没有这种可能性-如果无法加载适合的对象,适合管道的意义何在?后来?是的,如果我仅使用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')
test_project
main.py
from sklearn.externals import joblib pipeline = joblib.load('path.x')
预期结果是使用正确的转换方法正确加载了管道。
实际结果是加载文件时的异常。
我正在尝试腌制sklearn机器学习模型,并将其加载到另一个项目中。该模型包装在具有编码,缩放等功能的管道中。当我要使用...
我已经创建了一种解决方法。我不认为这是对我的问题的完整答案,但总之,它使我从问题中继续前进。