Source code for mlflow.keras.load

"""Functions for loading Keras models saved with MLflow."""

import os

import keras
import numpy as np
import pandas as pd

from mlflow.exceptions import INVALID_PARAMETER_VALUE, MlflowException
from mlflow.models import Model
from mlflow.models.model import MLMODEL_FILE_NAME
from mlflow.tracking.artifact_utils import _download_artifact_from_uri
from mlflow.utils.annotations import experimental

_MODEL_SAVE_PATH = "model"


[docs]class KerasModelWrapper: def __init__(self, model, signature, save_exported_model=False): self.model = model self.signature = signature self.save_exported_model = save_exported_model
[docs] def get_raw_model(self): """ Returns the underlying model. """ return self.model
[docs] def get_model_call_method(self): if self.save_exported_model: return self.model.serve else: return self.model.predict
[docs] def predict(self, data, **kwargs): model_call = self.get_model_call_method() if isinstance(data, pd.DataFrame): return pd.DataFrame(model_call(data.values), index=data.index) supported_input_types = (np.ndarray, list, tuple, dict) if not isinstance(data, supported_input_types): raise MlflowException( f"`data` must be one of: {[x.__name__ for x in supported_input_types]}, but " f"received type: {type(data)}.", INVALID_PARAMETER_VALUE, ) # Return numpy array for serving purposes. return keras.ops.convert_to_numpy(model_call(data))
def _load_keras_model(path, model_conf, custom_objects=None, **load_model_kwargs): save_exported_model = model_conf.flavors["keras"].get("save_exported_model") model_path = os.path.join(path, model_conf.flavors["keras"].get("data", _MODEL_SAVE_PATH)) if os.path.isdir(model_path): model_path = os.path.join(model_path, _MODEL_SAVE_PATH) if save_exported_model: try: import tensorflow as tf except ImportError: raise MlflowException( "`tensorflow` must be installed if you want to load an exported Keras 3 model, " "please install `tensorflow` by `pip install tensorflow`." ) return tf.saved_model.load(model_path) else: model_path += ".keras" return keras.saving.load_model( model_path, custom_objects=custom_objects, **load_model_kwargs, )
[docs]@experimental def load_model(model_uri, dst_path=None, custom_objects=None, load_model_kwargs=None): """ Load Keras model from MLflow. This method loads a saved Keras model from MLflow, and returns a Keras model instance. Args: model_uri: The URI of the saved Keras model in MLflow. For example: - `/Users/me/path/to/local/model` - `relative/path/to/local/model` - `s3://my_bucket/path/to/model` - `runs:/<mlflow_run_id>/run-relative/path/to/model` - `models:/<model_name>/<model_version>` - `models:/<model_name>/<stage>` For more information about supported URI schemes, see `Referencing Artifacts <https://www.mlflow.org/docs/latest/concepts.html#artifact-locations>`_. dst_path: The local filesystem path to which to download the model artifact. If unspecified, a local output path will be created. custom_objects: The `custom_objects` arg in `keras.saving.load_model`. load_model_kwargs: Extra args for `keras.saving.load_model`. .. code-block:: python :caption: Example import keras import mlflow import numpy as np model = keras.Sequential( [ keras.Input([28, 28, 3]), keras.layers.Flatten(), keras.layers.Dense(2), ] ) with mlflow.start_run() as run: mlflow.keras.log_model(model) model_url = f"runs:/{run.info.run_id}/{model_path}" loaded_model = mlflow.keras.load_model(model_url) # Test the loaded model produces the same output for the same input as the model. test_input = np.random.uniform(size=[2, 28, 28, 3]) np.testing.assert_allclose( keras.ops.convert_to_numpy(model(test_input)), loaded_model.predict(test_input), ) Returns: A Keras model instance. """ local_model_path = _download_artifact_from_uri(artifact_uri=model_uri, output_path=dst_path) load_model_kwargs = {} if load_model_kwargs is None else load_model_kwargs model_configuration_path = os.path.join(local_model_path, MLMODEL_FILE_NAME) model_conf = Model.load(model_configuration_path) return _load_keras_model(local_model_path, model_conf, custom_objects, **load_model_kwargs)
def _load_pyfunc(path): """Logics of loading a saved Keras model as a PyFunc model. This function is called by `mlflow.pyfunc.load_model`. Args: path: Local filesystem path to the MLflow Model with the `keras` flavor. """ model_meta_path1 = os.path.join(path, MLMODEL_FILE_NAME) model_meta_path2 = os.path.join(os.path.dirname(path), MLMODEL_FILE_NAME) if os.path.isfile(model_meta_path1): model_conf = Model.load(model_meta_path1) elif os.path.isfile(model_meta_path2): model_conf = Model.load(model_meta_path2) else: raise MlflowException(f"Cannot find file {MLMODEL_FILE_NAME} for the logged model.") save_exported_model = model_conf.flavors["keras"].get("save_exported_model") loaded_model = _load_keras_model(path, model_conf) return KerasModelWrapper(loaded_model, model_conf.signature, save_exported_model)