python - 使用自定义变压器时如何正确pickle sklearn管道

标签 python scikit-learn persistence pipeline joblib

我正在尝试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 笔记本进行训练:

  1. 创建一个定义自定义转换器的 .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/

    相关文章:

    Python:将本地时间转换为另一个时区

    python - 在 OpenShift 上使用 Django

    python - 将模型从一个 Django 应用程序迁移到多个其他应用程序

    python - GridseachCV - 值错误 : Found input variables with inconsistent numbers of samples: [33 1]

    authentication - ServiceStack Redis 身份验证持久化

    google-app-engine - 具有 HashMap 子字段的 Google App Engine JDO 持久性

    Python,复杂的正则表达式解析器

    python - SelectKBest 与 chi2 给出 ValueError : could not convert string to float

    ios - 在核心数据 swift 中使用 one -> may 关系保存数据集合

    python - 点集之间的有符号距离