A logged model carries its dependencies and interface, so others can load and use it without your training code.
Each flavor module has log_model, e.g. mlflow.sklearn.log_model(model, name="model"). In MLflow 3 this creates a LoggedModel, a first-class entity with its own ID, linked to the active run. The return value (ModelInfo) has a model_uri such as models:/m-....
A logged model directory contains:
MLmodel: a YAML file listing flavors, signature and metadata,- the serialized model (for sklearn, a pickle-free
model.skopsfile by default in recent 3.x releases), requirements.txt,conda.yamlandpython_env.yamlwith pinned dependencies,- an optional
input_example.
Load it two ways:
- Native flavor:
mlflow.sklearn.load_model(uri)returns the original estimator with all its methods. - pyfunc:
mlflow.pyfunc.load_model(uri)returns a genericPyFuncModelwhosepredict(data)works the same for every flavor, which is what serving and batch scoring use.
URIs you will see: models:/<model_id>, runs:/<run_id>/<path> for older-style references, and models:/<name>/<version> or models:/<name>@<alias> for registered models.
Always pass an input_example (a few rows of real input): MLflow infers the signature from it and validates that the model can be loaded and called. Version mismatches between the training and loading environments are the most common loading problem; the logged requirements tell you what to install.
Example
import mlflow
from sklearn.datasets import load_diabetes
from sklearn.linear_model import Ridge
X, y = load_diabetes(return_X_y=True, as_frame=True)
model = Ridge(alpha=0.5).fit(X, y)
with mlflow.start_run():
info = mlflow.sklearn.log_model(model, name="ridge", input_example=X.head(3))
print(info.model_uri.startswith("models:/")) # True (MLflow 3 LoggedModel URI)
native = mlflow.sklearn.load_model(info.model_uri)
print(type(native).__name__, native.alpha) # Ridge 0.5
generic = mlflow.pyfunc.load_model(info.model_uri)
print(generic.predict(X.head(2)).round(1)) # same predictions as native.predict
print(generic.metadata.get_input_schema().input_names()[:3]) # ['age', 'sex', 'bmi']Remember
<flavor>.log_model(model, name=...)creates a LoggedModel with an MLmodel file and pinned requirements- Load natively for full API, or via
mlflow.pyfuncfor a uniform predict - Pass
input_exampleso a signature is inferred and the model is validated
Watch out for
- Loading a model in an environment with different library versions than the ones logged in requirements.txt, causing deserialization errors.
- Logging tree-based sklearn models with skops serialization without listing their types in skops_trusted_types (or choosing serialization_format="cloudpickle"), which fails with an untrusted-types error.