Skip to content

Add support for MLFlow logger #1847

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
Merged
Show file tree
Hide file tree
Changes from 15 commits
Commits
Show all changes
19 commits
Select commit Hold shift + click to select a range
ba569b1
add mlflow loggger
DoMaLi94 Mar 11, 2024
091d3ca
Add mlflow logger import to __init__.py
DoMaLi94 Mar 11, 2024
cc9be43
Add mlflow package to requirements for logging
DoMaLi94 Mar 11, 2024
185fab5
Add example notebook on how to use mlflow logger
DoMaLi94 Mar 11, 2024
9fe07d7
Add mlruns to gitignore (default mlflow save directory)
DoMaLi94 Mar 11, 2024
bf324e2
Add README.md to mlflow logger example
DoMaLi94 Mar 11, 2024
0391845
Merge branch 'openvinotoolkit:main' into feature/mlflow-logger
DoMaLi94 Mar 11, 2024
e5c1aad
Merge branch 'openvinotoolkit:main' into feature/mlflow-logger
DoMaLi94 Mar 23, 2024
912cf0d
Remove unnecessary import from notebook
DoMaLi94 Mar 23, 2024
cbd624f
Fix pre-commit error
DoMaLi94 Mar 23, 2024
ff5d169
Use try_import to check if mlflow package is installed
DoMaLi94 Mar 23, 2024
396a51f
Change the required mlflow version in requirements/loggers.txt to >=1…
DoMaLi94 Apr 1, 2024
59978f6
Add mlflow>=1.0.0 to the loggers requirements in pyproject.toml
DoMaLi94 Apr 1, 2024
e3514f1
Merge branch 'main' into feature/mlflow-logger
DoMaLi94 Apr 1, 2024
8cf4be2
Merge branch 'main' into feature/mlflow-logger
DoMaLi94 Apr 2, 2024
42bcd51
Fix infinite running time of the mlflow notebook and suppress warnings
DoMaLi94 Apr 2, 2024
4021705
Delete requirements/loggers.txt
samet-akcay Apr 5, 2024
41a551e
Merge branch 'openvinotoolkit:main' into feature/mlflow-logger
DoMaLi94 Apr 5, 2024
b26dc68
Merge branch 'openvinotoolkit:main' into feature/mlflow-logger
DoMaLi94 Apr 22, 2024
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -175,3 +175,4 @@ docs/source/_build/
# logs
wandb/
lightning_logs/
mlruns
1,827 changes: 1,827 additions & 0 deletions notebooks/600_loggers/601_mlflow_logging.ipynb

Large diffs are not rendered by default.

18 changes: 18 additions & 0 deletions notebooks/600_loggers/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
# Using the MLFlow Logger

## Notebook Contents

This notebook demonstrates how to use the MLFlow logger. The notebook is divided into the following sections:

- Installation
- Run MLFlow Server
- Dataset Directory
- Imports
- Data Module
- Model
- MLFlow Logger
- Training
- Testing
- Demo Track Figure
- Save Model to MLFLow
- Load Model from MLFlow
1 change: 1 addition & 0 deletions pyproject.toml
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,7 @@ loggers = [
"gradio>=4",
"tensorboard",
"wandb==0.12.17",
"mlflow >=1.0.0",
]
notebooks = ["gitpython", "ipykernel", "ipywidgets", "notebook"]
dev = [
Expand Down
1 change: 1 addition & 0 deletions requirements/loggers.txt
Original file line number Diff line number Diff line change
Expand Up @@ -2,5 +2,6 @@ comet-ml>=3.31.7
gradio>=4
tensorboard
wandb==0.12.17
mlflow >=1.0.0
GitPython
ipykernel
2 changes: 2 additions & 0 deletions src/anomalib/loggers/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@

try:
from .comet import AnomalibCometLogger # noqa: F401
from .mlflow import AnomalibMLFlowLogger # noqa: F401
from .tensorboard import AnomalibTensorBoardLogger # noqa: F401
from .wandb import AnomalibWandbLogger # noqa: F401

Expand All @@ -23,6 +24,7 @@
"AnomalibCometLogger",
"AnomalibTensorBoardLogger",
"AnomalibWandbLogger",
"AnomalibMLFlowLogger",
],
)
except ImportError:
Expand Down
103 changes: 103 additions & 0 deletions src/anomalib/loggers/mlflow.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,103 @@
"""MLFlow logger with add image interface."""

from typing import Literal

import numpy as np
from lightning.pytorch.loggers.mlflow import MLFlowLogger
from lightning.pytorch.utilities import rank_zero_only
from matplotlib.figure import Figure

from anomalib.utils.exceptions.imports import try_import

from .base import ImageLoggerBase

try_import("mlflow")


class AnomalibMLFlowLogger(ImageLoggerBase, MLFlowLogger):
"""Logger for MLFlow.

Adds interface for ``add_image`` in the logger rather than calling the
experiment object.

.. note::
Same as the MLFlowLogger provided by PyTorch Lightning and the doc string is reproduced below.

Track your parameters, metrics, source code and more using
`MLFlow <https://mlflow.org/#core-concepts>`_.

Install it with pip:

.. code-block:: bash

pip install mlflow

Args:
experiment_name: The name of the experiment.
run_name: Name of the new run.
The `run_name` is internally stored as a ``mlflow.runName`` tag.
If the ``mlflow.runName`` tag has already been set in `tags`, the value is overridden by the `run_name`.
tracking_uri: Address of local or remote tracking server.
If not provided, defaults to `MLFLOW_TRACKING_URI` environment variable if set, otherwise it falls
back to `file:<save_dir>`.
save_dir: A path to a local directory where the MLflow runs get saved.
Defaults to `./mlruns` if `tracking_uri` is not provided.
Has no effect if `tracking_uri` is provided.
log_model: Log checkpoints created by `ModelCheckpoint` as MLFlow artifacts.

- if ``log_model == 'all'``, checkpoints are logged during training.
- if ``log_model == True``, checkpoints are logged at the end of training, \
except when `save_top_k == -1` which also logs every checkpoint during training.
- if ``log_model == False`` (default), no checkpoint is logged.

prefix: A string to put at the beginning of metric keys. Defaults to ``''``.
kwargs: Additional arguments like `tags`, `artifact_location` etc. used by
`MLFlowExperiment` can be passed as keyword arguments in this logger.

Example:
>>> from anomalib.loggers import AnomalibMLFlowLogger
>>> from anomalib.engine import Engine
...
>>> mlflow_logger = AnomalibMLFlowLogger()
>>> engine = Engine(logger=mlflow_logger)

See Also:
- `MLFlow Documentation <https://mlflow.org/docs/latest/>`_.
"""

def __init__(
self,
experiment_name: str | None = "anomalib_logs",
run_name: str | None = None,
tracking_uri: str | None = None,
save_dir: str | None = "./mlruns",
log_model: Literal[True, False, "all"] | None = False,
prefix: str | None = "",
**kwargs,
) -> None:
super().__init__(
experiment_name=experiment_name,
run_name=run_name,
tracking_uri=tracking_uri,
save_dir=save_dir,
log_model=log_model,
prefix=prefix,
**kwargs,
)

@rank_zero_only
def add_image(self, image: np.ndarray | Figure, name: str | None = None, **kwargs) -> None:
"""Interface to log images in the mlflow loggers.

Args:
image (np.ndarray | Figure): Image to log.
name (str | None): The tag of the image defaults to ``None``.
kwargs: Additional keyword arguments that are only used if `image` is of type Figure.
These arguments are passed directly to the method that saves the figure.
If `image` is a NumPy array, `kwargs` has no effect.
"""
# Need to call different functions of `Experiment` for Figure vs np.ndarray
if isinstance(image, Figure):
self.experiment.log_figure(run_id=self.run_id, figure=image, artifact_file=name, **kwargs)
else:
self.experiment.log_image(run_id=self.run_id, image=image, artifact_file=name)