我正在尝试pickle 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”之类的东西并抛出异常(exception):
ModuleNotFoundError: No module named 'src.feature_extraction'
我还应该补充一点,我从一开始的意图就是简化模型的使用,因此程序员可以像任何其他模型一样加载模型,传递非常简单的、人类可读的特征,以及对实际特征的所有“神奇”预处理模型(例如梯度提升)正在内部发生。
我想在两个项目的根目录中创建/dependencies/xxx_model/目录,并在其中存储所有需要的类和函数(将代码从“train_project”复制到“use_project”),因此项目的结构是相同的,变压器可以被加载。我发现这个解决方案非常不优雅,因为它会强制使用该模型的任何项目的结构。
我想到只是重新创建管道和“use_project”内的所有变压器,并以某种方式从“train_project”加载变压器的拟合值。
最好的解决方案是,如果转储的文件包含所有需要的信息并且不需要任何依赖项,老实说,我对 sklearn.Pipelines 似乎没有这种可能性感到震惊 - 如果我无法加载安装的管道,那么安装管道有什么意义稍后反对?是的,如果我只使用 sklearn 类,而不创建自定义类,它会起作用,但非自定义类不具备所有需要的功能。
示例代码:
火车项目
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]
火车项目
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')
预期结果是管道正确加载,并且可以使用转换方法。
实际结果是加载文件时出现异常。
最佳答案
我找到了一个非常简单的解决方案。假设您使用 Jupyter 笔记本进行训练:
- 创建一个定义自定义转换器的
.py
文件,并将其导入 Jupyter Notebook。
这是文件custom_transformer.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]
- 训练您的模型,从
.py
文件导入此类,并使用joblib
保存它。
import joblib
from custom_transformer import FilterOutBigValuesTransformer
from sklearn.externals import joblib
from sklearn.preprocessing import MinMaxScaler
pipeline = Pipeline([
('filter', FilterOutBigValuesTransformer()),
('encode', MinMaxScaler()),
])
X=load_some_pandas_dataframe()
pipeline.fit(X)
joblib.dump(pipeline, 'pipeline.pkl')
- 在不同的 Python 脚本中加载
.pkl
文件时,您必须导入.py
文件才能使其正常工作:
import joblib
from utils import custom_transformer # decided to save it in a utils directory
pipeline = joblib.load('pipeline.pkl')
关于python - 使用自定义变压器时如何正确pickle sklearn管道,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/57888291/