Python 无法使用 Docker 将 .pkl 文件加载到我的模型中

问题描述 投票:0回答:1

用于学习目的

我正在使用 Keras 开发自定义深度学习模型,这不是顺序模型。该模型具有双重输出:它生成用于预测的连续值和用于预测的多类标签。为了简化我的工作,我使用 scikit-learn Pipelines 并使用 joblib 保存整个管道。

我遇到了 scikit-learn 的 Keras 包装器的问题,该包装器是为顺序模型设计的。因此,我成功地构建了自己的自定义模型,并且它在本地表现良好。我什至付出了额外的努力,创建了一个概念验证 API 和一个小型网站来服务这个模型。

在我的本地环境中一切都运行顺利。然而,当我尝试构建 Docker 镜像时,遇到了问题。管道无法加载模型权重,导致出现如下错误消息:

Layer 'lstm_cell' expected 3 variables, but received 0 variables during loading. Expected: ['lstm/lstm_cell/kernel:0', 'lstm/lstm_cell/recurrent_kernel:0', 'lstm/lstm_cell/bias:0']

我想知道其他人以前是否遇到过这种情况。在 Docker 中处理 .pkl 文件是否存在问题,或者是否需要在上传之前压缩文件?我花了几个小时试图解决这个问题,我们将不胜感激任何帮助。

这是我的文件夹的一瞥:

.
└── END2END/
    ├── pipelines/
    │   ├── scripts
    │   ├── __init__py
    │   └── myscripts.py
    ├── train_models/
    │   ├── __init__.py
    │   ├── script2.py
    │   └── my_model_.pkl
    ├── api.py
    └── Dockerfile

还有我的模型:

def ModelLSTM(input_shape, hidden_units: int,
              output_1: int, output_2: int,
              lr: float, model_name: str) -> keras.Model:
    """ LSTM model - single multioutput model
    ### Arguments:
        - input_shape : input shapes
        - hidden_units : hidden units (LSTM units)
        - output_1 : number of outputs (forecasting outputs)
        - output_2 : number of outputs (failures outputs)
        - lr : learning rate
        - name: name of the model
       
    ### Returns:
        model (keras.Model)"""
   
    # Data Input
    inputs_ = keras.Input(
        shape=(input_shape[1], input_shape[2]),
        name='inputs'
    )

    # Lstm Layer
    hiddens_layers = layers.LSTM(hidden_units, return_sequences=True)(inputs_)

    # output forecasting 
    output_forecast = layers.Dense(output_1, activation='linear', name='forecast')(hiddens_layers)

    # output failures
    output_failures = layers.Dense(output_2, activation='sigmoid', name='failures')(hiddens_layers)

    # Create Model 
    model = keras.Model(inputs=inputs_, outputs=[output_forecast, output_failures], name=model_name)
    model.compile(loss={
        'forecast': 'mean_squared_error',
        'failures': custom_multilabel_loss},
    optimizer= tf.keras.optimizers.Adam(learning_rate=lr),
    metrics ={
        'forecast': 'mae',
        'failures': 'accuracy'})
    return model

这是我的 docker 文件


# Variables 
ARG WorkingDirectory=/project

# Pull Docker Image
FROM python:3.11-bullseye

# Set up Working Environment
WORKDIR $WorkingDirectory

# Create an "application" directory
RUN mkdir -p $WorkingDirectory/application
RUN export PYTHONPATH=$WorkingDirectory

# Copy Files
COPY . $WorkingDirectory/application

# Update Requirements 
RUN pip install --upgrade pip
RUN pip install --no-cache-dir -r $WorkingDirectory/application/requirements/requirements.txt
EXPOSE 8000

# Start API Server
CMD ["sh", "-c", "python ${ADD_DIR}/application/main.py"]

他们是我保存和加载管道的方式:

def save_pipeline(*, pipeline_to_saved: Pipeline, name: str) -> None:
    """
    Saved the versioned model and overwrite any previos saved models,
    this ensure there is only one trained model that can be called

    ### Arguments:
        - pipeline_to_save (`sklearn.Pipeline`) : pipeline already trained

    """

    # Versioned file name
    save_file_name = f"{name}_{_version}.pkl"
    save_path = TRAINED_MODEL_DIR / save_file_name

    # Re-write or delete model file
    remove_old_pipelines(files_to_keep=save_file_name)

    # saved
    joblib.dump(pipeline_to_saved, save_path)


def load_pipeline(*, file_name: str) -> Pipeline:
    """ Load Pipeline from trained model

    ### Arguments:
        - file_name (str): pipeline file name

    ### Returns:
        train_pipeline : Pipeline object
    """

    file_path = TRAINED_MODEL_DIR / f"{file_name}_{_version}.pkl"
    print(file_path)
    trained_pipeline = joblib.load(filename=file_path)
    return trained_pipeline

我对模型进行了两次重新训练,以确保其重量没有问题。在本地运行时,模型加载、运行并进行预测不会出现任何问题。

我尝试将权重文件移动到与“api.py”相同的位置,甚至尝试将路径硬编码到“.pkl”文件。

我知道我可以分割管道并使用“keras.load_weights”加载模型,然后将模型重新插入管道。但是,如果它在本地运行正常,我想知道为什么它在 Docker 中无法运行。”

docker deep-learning
1个回答
0
投票

经过大量研究,我找不到解决问题的简单方法。我认为发生的事情是这样的:我首先在 Windows 计算机上训练我的模型,但我尝试在 Linux 计算机上运行的 Docker 容器中使用它。这两个系统并不总是完美相处(我缺乏跨系统兼容性的复杂性方面的专业知识)。

我读到 .pkl 模型文件应该与创建它们时使用的相同版本的 Python (在 python 3.11.6 上训练并在 python 3.11.6 上构建)一起使用,所以我确定了这一点,但是 它没有无法解决问题我也尝试过压缩.pkl文件,正如一些人建议的那样,但是也不起作用。有些人说 Docker 可能在处理 .pkl 文件时遇到问题,但我可以确认这不是我的情况的问题。

最终对我有用的是一种不同的方法。我不只是复制文件,而是像以前一样重新创建了整个目录结构。然后,当我构建 Docker 容器时,我再次训练了模型(在 docker 映像内部)。令人惊讶的是,这解决了我的问题,并且该模型在 Docker 容器中完美运行。问题似乎是因为该模型是在 Windows 上训练的,但在 Linux 上的 Docker 容器中使用(我的假设)。

我分享这个以防其他人遇到同样的问题。 干杯

© www.soinside.com 2019 - 2024. All rights reserved.