我试图用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_model的conda_env参数保存转换器库的版本,并在将模型加载到use_project中时检查其版本是否相同。
    但是如果我必须更换变压器或在其中调试的话,这是很痛苦的。

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

    其他信息:
    在linux上工作(ubuntu)
    mlflow = 1.5.0
    python = 3.7.3

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

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

    最佳答案

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

    关于python - mlflow如何使用自定义转换器保存sklearn管道?,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/60530176/

  • 10-10 23:01