mlflow 如何使用自定义转换器保存 sklearn 管道?

Posted

技术标签:

【中文标题】mlflow 如何使用自定义转换器保存 sklearn 管道?【英文标题】:mlflow How to save a sklearn pipeline with custom transformer? 【发布时间】:2020-06-17 04:31:45 【问题描述】:

我正在尝试使用 mlflow 保存一个 sklearn 机器学习模型,这是一个包含我定义的自定义转换器的管道,并将其加载到另一个项目中。 我的自定义转换器继承自 BaseEstimator 和 TransformerMixin。

假设我有 2 个项目:

train_project:它在 src.ml.transformers.py 中有自定义转换器 use_project:src中有其他东西,或者根本没有src目录

所以在我的 train_project 中我会这样做:

mlflow.sklearn.log_model(preprocess_pipe, 'model/preprocess_pipe')

然后当我尝试将其加载到 use_project 时:

preprocess_pipe = mlflow.sklearn.load_model(f'ref_model_path/preprocess_pipe')

发生错误:

[...]
File "/home/quentin/anaconda3/envs/api_env/lib/python3.7/site-packages/mlflow/sklearn.py", line 210, in _load_model_from_local_file
    return pickle.load(f)
ModuleNotFoundError: No module named 'train_project'

我尝试使用格式 mlflow.sklearn.SERIALIZATION_FORMAT_CLOUDPICKLE :

mlflow.sklearn.log_model(preprocess_pipe, 'model/preprocess_pipe', serialization_format=mlflow.sklearn.SERIALIZATION_FORMAT_CLOUDPICKLE)

但我在加载过程中遇到同样的错误。

我在 mlflow.pyfunc.log_model 中看到了选项 code_path,但我不清楚它的用途和目的。

我认为 mlflow 提供了一种简单的方法来保存模型并对其进行序列化,以便它们可以在任何地方使用,只有当您拥有本机 sklearn 模型(或 keras,...)时才如此吗?

似乎这个问题与pickle功能更相关(mlflow使用它并且pickle需要安装所有依赖项)。

到目前为止,我发现的唯一解决方案是将我的转换器制作成一个包,并将其导入两个项目中。使用 log_modelconda_env 参数保存我的转换器库的版本,并在我将模型加载到我的 use_project 时检查它是否是相同的版本。 但是,如果我必须更换变压器或在其中调试,那就太痛苦了……

有人有更好的解决方案吗? 更优雅?也许我会错过一些 mlflow 功能?

其他信息: 在 Linux (ubuntu) 上工作 mlflow=1.5.0 蟒蛇=3.7.3

我在 mlflow.sklearn api 的测试中看到他们使用自定义转换器进行了测试,但他们将其加载到同一个文件中,因此它似乎无法解决我的问题,但也许它可以帮助其他人:

https://github.com/mlflow/mlflow/blob/master/tests/sklearn/test_sklearn_model_export.py

【问题讨论】:

您解决了这个问题吗?我们有类似的过程。你试过mlflow.pyfunc吗? 【参考方案1】:

您可以使用code_path 参数来保存Python 文件依赖项(或包含文件依赖项的目录)。加载模型时,这些文件会附加到系统路径中。 模型文件夹将包含一个目录code,其中包含所有这些文件。

【讨论】:

【参考方案2】:

您要做的是序列化您在train.py 之外的模块中训练的“自定义”内容,对吗?

您可能需要做的是使用mlflow.pyfunc.log_modelcode 参数记录您的模型,该参数包含一个字符串列表,其中包含您需要反序列化和进行预测的模块的路径,如文档所述@ 987654321@.

需要明确的是,每个 mlflow 模型本质上都是 PyFunc。即使您使用mlflow.sklearn 记录模型,您也可以使用mlflow.pyfunc.load_model 加载它。 PyFunc 所做的是以独特的方式标准化所有模型和框架,这将保证您始终声明如何:

    使用load_context() 方法对模型进行反序列化 使用predict() 方法进行预测

如果您确定继承 mlflow 的 PythonModel 类的对象中的这两件事,则可以将您的模型记录为 PyFunc。

mlflow.sklearn.log_model 所做的基本上是总结了您声明序列化和反序列化的方式。如果您坚持使用 sklearn 的基本模块,例如基本的转换器和管道,那么您将始终可以使用它。但是当你需要一些自定义的东西时,你可以参考 Pyfuncs。

你可以找到一个非常有用的例子here。请注意,它准确说明了如何进行预测,将输入转换为 XGBoost 的 DMatrix。

【讨论】:

以上是关于mlflow 如何使用自定义转换器保存 sklearn 管道?的主要内容,如果未能解决你的问题,请参考以下文章

如何在 @DataMongoTest 中使用自定义转换器?

如何在 Android 中保存自定义 Java 对象?

如何在 mlflow 中添加系数、p 值和相关变量名称?

如何使方法 JSON 可序列化以在自定义 Pyspark 转换器中使用

如何创建自定义可写转换器?

如何使用 mlflow.pyfunc.log_model() 通过 Keras 步骤记录 sklearn 管道?类型错误:无法腌制 _thread.RLock 对象