We are currently solving the following issue within our repository. Here is the issue text:
--- BEGIN ISSUE ---
MLFlow Logger slows training steps dramatically, despite only setting metrics to be logged on epoch
## 🐛 Bug

When using the MLFlow logger, with a remote server, logging per step introduces latency which slows the training loop.
I have tried to configure logging of metrics only per epoch, however it seems this still results in much slower performance. I suspect the logger is still communicating with the MLFlow server on each training step.

### To Reproduce
1. Start an MLFlow server locally
```
mlflow ui
```
2. Run the minimal code example below as is, (with MLFlow logger set to use the default file uri.)
3. Uncomment out the `tracking_uri` to use the local MLFlow server and run the code again. You will see a 2-3 times drop in the iterations per second.

#### Code sample
```
import torch
from torch.utils.data import TensorDataset, DataLoader
import pytorch_lightning as pl

class MyModel(pl.LightningModule):
    def __init__(self):
        super().__init__()
        self.num_examples = 5000
        self.num_valid = 1000
        self.batch_size = 64
        self.lr = 1e-3
        self.wd = 1e-2
        self.num_features = 2
        self.linear = torch.nn.Linear(self.num_features, 1)
        self.loss_func = torch.nn.MSELoss()
        self.X = torch.rand(self.num_examples, self.num_features)
        self.y = self.X.matmul(torch.rand(self.num_features, 1)) + torch.rand(self.num_examples)
        
    def forward(self, x):
        return self.linear(x)

    def train_dataloader(self): 
        ds = TensorDataset(self.X[:-self.num_valid], self.X[:-self.num_valid])
        dl = DataLoader(ds, batch_size=self.batch_size)
        return dl

    def val_dataloader(self): 
        ds = TensorDataset(self.X[-self.num_valid:], self.X[-self.num_valid:])
        dl = DataLoader(ds, batch_size=self.batch_size)
        return dl

    def configure_optimizers(self):
        return torch.optim.Adam(self.parameters(), lr=self.lr, weight_decay=self.wd)

    def training_step(self, batch, batch_idx):
        x, y = batch
        yhat = self(x)
        loss = self.loss_func(yhat, y)
        result = pl.TrainResult(minimize=loss)
        result.log('train_loss', loss, on_epoch=True, on_step=False)
        return result

    def validation_step(self, batch, batch_idx):
        x, y = batch
        yhat = self(x)
        loss = self.loss_func(yhat, y)
        result = pl.EvalResult(early_stop_on=loss)
        result.log('val_loss', loss, on_epoch=True, on_step=False)
        return result

if __name__ == '__main__':
    from pytorch_lightning.loggers import TensorBoardLogger, MLFlowLogger
    mlf_logger = MLFlowLogger(
        experiment_name=f"MyModel",
        # tracking_uri="http://localhost:5000"
    )
    trainer = pl.Trainer(
        min_epochs=5,
        max_epochs=50,
        early_stop_callback=True,
        logger=mlf_logger
    )
    model = MyModel()
    trainer.fit(model)
```

### Expected behavior

When using the TrainResult and EvalResult, or manually handling metric logging using the `training_epoch_end` and `validation_epoch_end` callbacks. It should be possible to avoid the MLFlow logger from communicating with the server in each training loop. 
This would make it feasible to implement the MLFlow when a remote server is used for experiment tracking.

### Environment
```
* CUDA:
	- GPU:
	- available:         False
	- version:           None
* Packages:
	- numpy:             1.18.2
	- pyTorch_debug:     False
	- pyTorch_version:   1.6.0+cpu
	- pytorch-lightning: 0.9.0
	- tensorboard:       2.2.0
	- tqdm:              4.48.2
* System:
	- OS:                Linux
	- architecture:
		- 64bit
		-
	- processor:         x86_64
	- python:            3.7.9
	- version:           #1 SMP Tue May 26 11:42:35 UTC 2020
```
### Additional context

We host a MLFlow instance in AWS and would like to be able to track experiments without affecting the training speed. 
It appears that in general the MLFlow logger is much less performant than the default Tensorboard Logger, but this would not be much of a problem if we could avoid calls to the logger during the training loop.

### Solution
I've done a bit of debugging in the codebase and have been able to isolate the cause in two places
https://github.com/PyTorchLightning/pytorch-lightning/blob/d438ad8a8db3e76d3ed4e3c6bc9b91d6b3266b8e/pytorch_lightning/loggers/mlflow.py#L125-L129
Here `self.experiment` is called regardless of whether `self._run_id` exists. If we add an `if not self._run_id` here we avoid calling `self._mlflow_client.get_experiment_by_name(self._experiment_name)` on each step.
However we still call it each time we log metrics to MFlow, because of the property `self.experiment`.

https://github.com/PyTorchLightning/pytorch-lightning/blob/d438ad8a8db3e76d3ed4e3c6bc9b91d6b3266b8e/pytorch_lightning/loggers/mlflow.py#L100-L112
Here if we store `expt` within the logger and only call `self._mlflow_client.get_experiment_by_name` when it does not exist, we eliminate all overhead, it runs as fast as fast as the tensorboard logger and all the mlflow logging appears to be working as expected.

I'd be happy to raise a PR for this fix.

--- END ISSUE ---

Below are some code segments, each from a relevant file. One or more of these files may contain bugs.
--- BEGIN FILES ---
Path: `pytorch_lightning/loggers/mlflow.py`
Content:
```
1 # Copyright The PyTorch Lightning team.
2 #
3 # Licensed under the Apache License, Version 2.0 (the "License");
4 # you may not use this file except in compliance with the License.
5 # You may obtain a copy of the License at
6 #
7 #     http://www.apache.org/licenses/LICENSE-2.0
8 #
9 # Unless required by applicable law or agreed to in writing, software
10 # distributed under the License is distributed on an "AS IS" BASIS,
11 # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 # See the License for the specific language governing permissions and
13 # limitations under the License.
14 
15 """
16 MLflow
17 ------
18 """
19 from argparse import Namespace
20 from time import time
21 from typing import Optional, Dict, Any, Union
22 
23 try:
24     import mlflow
25     from mlflow.tracking import MlflowClient
26     _MLFLOW_AVAILABLE = True
27 except ModuleNotFoundError:  # pragma: no-cover
28     mlflow = None
29     MlflowClient = None
30     _MLFLOW_AVAILABLE = False
31 
32 
33 from pytorch_lightning import _logger as log
34 from pytorch_lightning.loggers.base import LightningLoggerBase, rank_zero_experiment
35 from pytorch_lightning.utilities import rank_zero_only
36 
37 
38 LOCAL_FILE_URI_PREFIX = "file:"
39 
40 
41 class MLFlowLogger(LightningLoggerBase):
42     """
43     Log using `MLflow <https://mlflow.org>`_. Install it with pip:
44 
45     .. code-block:: bash
46 
47         pip install mlflow
48 
49     Example:
50         >>> from pytorch_lightning import Trainer
51         >>> from pytorch_lightning.loggers import MLFlowLogger
52         >>> mlf_logger = MLFlowLogger(
53         ...     experiment_name="default",
54         ...     tracking_uri="file:./ml-runs"
55         ... )
56         >>> trainer = Trainer(logger=mlf_logger)
57 
58     Use the logger anywhere in you :class:`~pytorch_lightning.core.lightning.LightningModule` as follows:
59 
60     >>> from pytorch_lightning import LightningModule
61     >>> class LitModel(LightningModule):
62     ...     def training_step(self, batch, batch_idx):
63     ...         # example
64     ...         self.logger.experiment.whatever_ml_flow_supports(...)
65     ...
66     ...     def any_lightning_module_function_or_hook(self):
67     ...         self.logger.experiment.whatever_ml_flow_supports(...)
68 
69     Args:
70         experiment_name: The name of the experiment
71         tracking_uri: Address of local or remote tracking server.
72             If not provided, defaults to `file:<save_dir>`.
73         tags: A dictionary tags for the experiment.
74         save_dir: A path to a local directory where the MLflow runs get saved.
75             Defaults to `./mlflow` if `tracking_uri` is not provided.
76             Has no effect if `tracking_uri` is provided.
77 
78     """
79 
80     def __init__(self,
81                  experiment_name: str = 'default',
82                  tracking_uri: Optional[str] = None,
83                  tags: Optional[Dict[str, Any]] = None,
84                  save_dir: Optional[str] = './mlruns'):
85 
86         if not _MLFLOW_AVAILABLE:
87             raise ImportError('You want to use `mlflow` logger which is not installed yet,'
88                               ' install it with `pip install mlflow`.')
89         super().__init__()
90         if not tracking_uri:
91             tracking_uri = f'{LOCAL_FILE_URI_PREFIX}{save_dir}'
92 
93         self._experiment_name = experiment_name
94         self._experiment_id = None
95         self._tracking_uri = tracking_uri
96         self._run_id = None
97         self.tags = tags
98         self._mlflow_client = MlflowClient(tracking_uri)
99 
100     @property
101     @rank_zero_experiment
102     def experiment(self) -> MlflowClient:
103         r"""
104         Actual MLflow object. To use MLflow features in your
105         :class:`~pytorch_lightning.core.lightning.LightningModule` do the following.
106 
107         Example::
108 
109             self.logger.experiment.some_mlflow_function()
110 
111         """
112         expt = self._mlflow_client.get_experiment_by_name(self._experiment_name)
113 
114         if expt:
115             self._experiment_id = expt.experiment_id
116         else:
117             log.warning(f'Experiment with name {self._experiment_name} not found. Creating it.')
118             self._experiment_id = self._mlflow_client.create_experiment(name=self._experiment_name)
119 
120         if not self._run_id:
121             run = self._mlflow_client.create_run(experiment_id=self._experiment_id, tags=self.tags)
122             self._run_id = run.info.run_id
123         return self._mlflow_client
124 
125     @property
126     def run_id(self):
127         # create the experiment if it does not exist to get the run id
128         _ = self.experiment
129         return self._run_id
130 
131     @property
132     def experiment_id(self):
133         # create the experiment if it does not exist to get the experiment id
134         _ = self.experiment
135         return self._experiment_id
136 
137     @rank_zero_only
138     def log_hyperparams(self, params: Union[Dict[str, Any], Namespace]) -> None:
139         params = self._convert_params(params)
140         params = self._flatten_dict(params)
141         for k, v in params.items():
142             self.experiment.log_param(self.run_id, k, v)
143 
144     @rank_zero_only
145     def log_metrics(self, metrics: Dict[str, float], step: Optional[int] = None) -> None:
146         assert rank_zero_only.rank == 0, 'experiment tried to log from global_rank != 0'
147 
148         timestamp_ms = int(time() * 1000)
149         for k, v in metrics.items():
150             if isinstance(v, str):
151                 log.warning(f'Discarding metric with string value {k}={v}.')
152                 continue
153             self.experiment.log_metric(self.run_id, k, v, timestamp_ms, step)
154 
155     @rank_zero_only
156     def finalize(self, status: str = 'FINISHED') -> None:
157         super().finalize(status)
158         status = 'FINISHED' if status == 'success' else status
159         if self.experiment.get_run(self.run_id):
160             self.experiment.set_terminated(self.run_id, status)
161 
162     @property
163     def save_dir(self) -> Optional[str]:
164         """
165         The root file directory in which MLflow experiments are saved.
166 
167         Return:
168             Local path to the root experiment directory if the tracking uri is local.
169             Otherwhise returns `None`.
170         """
171         if self._tracking_uri.startswith(LOCAL_FILE_URI_PREFIX):
172             return self._tracking_uri.lstrip(LOCAL_FILE_URI_PREFIX)
173 
174     @property
175     def name(self) -> str:
176         return self.experiment_id
177 
178     @property
179     def version(self) -> str:
180         return self.run_id
181
```
--- END FILES ---

Please first localize the bug based on the issue statement, and then generate a patch according to the `git diff` format fenced by three backticks.

Here is an example:

```diff
diff --git a/examples/server_async.py b/examples/server_async.py
--- a/examples/server_async.py
+++ b/examples/server_async.py
@@ -313,4 +313,4 @@
 
 
 if __name__ == "__main__":
-    asyncio.run(run_async_server("."), debug=True)
+    asyncio.run(run_async_server(), debug=True)
diff --git a/examples/server_sync.py b/examples/server_sync.py
--- a/examples/server_sync.py
+++ b/examples/server_sync.py
@@ -313,5 +313,5 @@
 
 
 if __name__ == "__main__":
-    server = run_sync_server(".")
+    server = run_sync_server()
     server.shutdown()

```

diff --git a/pytorch_lightning/loggers/mlflow.py b/pytorch_lightning/loggers/mlflow.py
--- a/pytorch_lightning/loggers/mlflow.py
+++ b/pytorch_lightning/loggers/mlflow.py
@@ -109,15 +109,15 @@
             self.logger.experiment.some_mlflow_function()
 
         """
-        expt = self._mlflow_client.get_experiment_by_name(self._experiment_name)
-
-        if expt:
-            self._experiment_id = expt.experiment_id
-        else:
-            log.warning(f'Experiment with name {self._experiment_name} not found. Creating it.')
-            self._experiment_id = self._mlflow_client.create_experiment(name=self._experiment_name)
-
-        if not self._run_id:
+        if self._experiment_id is None:
+            expt = self._mlflow_client.get_experiment_by_name(self._experiment_name)
+            if expt is not None:
+                self._experiment_id = expt.experiment_id
+            else:
+                log.warning(f'Experiment with name {self._experiment_name} not found. Creating it.')
+                self._experiment_id = self._mlflow_client.create_experiment(name=self._experiment_name)
+
+        if self._run_id is None:
             run = self._mlflow_client.create_run(experiment_id=self._experiment_id, tags=self.tags)
             self._run_id = run.info.run_id
         return self._mlflow_client

{"golden_diff": "diff --git a/pytorch_lightning/loggers/mlflow.py b/pytorch_lightning/loggers/mlflow.py\n--- a/pytorch_lightning/loggers/mlflow.py\n+++ b/pytorch_lightning/loggers/mlflow.py\n@@ -109,15 +109,15 @@\n             self.logger.experiment.some_mlflow_function()\n \n         \"\"\"\n-        expt = self._mlflow_client.get_experiment_by_name(self._experiment_name)\n-\n-        if expt:\n-            self._experiment_id = expt.experiment_id\n-        else:\n-            log.warning(f'Experiment with name {self._experiment_name} not found. Creating it.')\n-            self._experiment_id = self._mlflow_client.create_experiment(name=self._experiment_name)\n-\n-        if not self._run_id:\n+        if self._experiment_id is None:\n+            expt = self._mlflow_client.get_experiment_by_name(self._experiment_name)\n+            if expt is not None:\n+                self._experiment_id = expt.experiment_id\n+            else:\n+                log.warning(f'Experiment with name {self._experiment_name} not found. Creating it.')\n+                self._experiment_id = self._mlflow_client.create_experiment(name=self._experiment_name)\n+\n+        if self._run_id is None:\n             run = self._mlflow_client.create_run(experiment_id=self._experiment_id, tags=self.tags)\n             self._run_id = run.info.run_id\n         return self._mlflow_client\n", "issue": "MLFlow Logger slows training steps dramatically, despite only setting metrics to be logged on epoch\n## \ud83d\udc1b Bug\r\n\r\nWhen using the MLFlow logger, with a remote server, logging per step introduces latency which slows the training loop.\r\nI have tried to configure logging of metrics only per epoch, however it seems this still results in much slower performance. I suspect the logger is still communicating with the MLFlow server on each training step.\r\n\r\n### To Reproduce\r\n1. Start an MLFlow server locally\r\n```\r\nmlflow ui\r\n```\r\n2. Run the minimal code example below as is, (with MLFlow logger set to use the default file uri.)\r\n3. Uncomment out the `tracking_uri` to use the local MLFlow server and run the code again. You will see a 2-3 times drop in the iterations per second.\r\n\r\n#### Code sample\r\n```\r\nimport torch\r\nfrom torch.utils.data import TensorDataset, DataLoader\r\nimport pytorch_lightning as pl\r\n\r\nclass MyModel(pl.LightningModule):\r\n    def __init__(self):\r\n        super().__init__()\r\n        self.num_examples = 5000\r\n        self.num_valid = 1000\r\n        self.batch_size = 64\r\n        self.lr = 1e-3\r\n        self.wd = 1e-2\r\n        self.num_features = 2\r\n        self.linear = torch.nn.Linear(self.num_features, 1)\r\n        self.loss_func = torch.nn.MSELoss()\r\n        self.X = torch.rand(self.num_examples, self.num_features)\r\n        self.y = self.X.matmul(torch.rand(self.num_features, 1)) + torch.rand(self.num_examples)\r\n        \r\n    def forward(self, x):\r\n        return self.linear(x)\r\n\r\n    def train_dataloader(self): \r\n        ds = TensorDataset(self.X[:-self.num_valid], self.X[:-self.num_valid])\r\n        dl = DataLoader(ds, batch_size=self.batch_size)\r\n        return dl\r\n\r\n    def val_dataloader(self): \r\n        ds = TensorDataset(self.X[-self.num_valid:], self.X[-self.num_valid:])\r\n        dl = DataLoader(ds, batch_size=self.batch_size)\r\n        return dl\r\n\r\n    def configure_optimizers(self):\r\n        return torch.optim.Adam(self.parameters(), lr=self.lr, weight_decay=self.wd)\r\n\r\n    def training_step(self, batch, batch_idx):\r\n        x, y = batch\r\n        yhat = self(x)\r\n        loss = self.loss_func(yhat, y)\r\n        result = pl.TrainResult(minimize=loss)\r\n        result.log('train_loss', loss, on_epoch=True, on_step=False)\r\n        return result\r\n\r\n    def validation_step(self, batch, batch_idx):\r\n        x, y = batch\r\n        yhat = self(x)\r\n        loss = self.loss_func(yhat, y)\r\n        result = pl.EvalResult(early_stop_on=loss)\r\n        result.log('val_loss', loss, on_epoch=True, on_step=False)\r\n        return result\r\n\r\nif __name__ == '__main__':\r\n    from pytorch_lightning.loggers import TensorBoardLogger, MLFlowLogger\r\n    mlf_logger = MLFlowLogger(\r\n        experiment_name=f\"MyModel\",\r\n        # tracking_uri=\"http://localhost:5000\"\r\n    )\r\n    trainer = pl.Trainer(\r\n        min_epochs=5,\r\n        max_epochs=50,\r\n        early_stop_callback=True,\r\n        logger=mlf_logger\r\n    )\r\n    model = MyModel()\r\n    trainer.fit(model)\r\n```\r\n\r\n### Expected behavior\r\n\r\nWhen using the TrainResult and EvalResult, or manually handling metric logging using the `training_epoch_end` and `validation_epoch_end` callbacks. It should be possible to avoid the MLFlow logger from communicating with the server in each training loop. \r\nThis would make it feasible to implement the MLFlow when a remote server is used for experiment tracking.\r\n\r\n### Environment\r\n```\r\n* CUDA:\r\n\t- GPU:\r\n\t- available:         False\r\n\t- version:           None\r\n* Packages:\r\n\t- numpy:             1.18.2\r\n\t- pyTorch_debug:     False\r\n\t- pyTorch_version:   1.6.0+cpu\r\n\t- pytorch-lightning: 0.9.0\r\n\t- tensorboard:       2.2.0\r\n\t- tqdm:              4.48.2\r\n* System:\r\n\t- OS:                Linux\r\n\t- architecture:\r\n\t\t- 64bit\r\n\t\t-\r\n\t- processor:         x86_64\r\n\t- python:            3.7.9\r\n\t- version:           #1 SMP Tue May 26 11:42:35 UTC 2020\r\n```\r\n### Additional context\r\n\r\nWe host a MLFlow instance in AWS and would like to be able to track experiments without affecting the training speed. \r\nIt appears that in general the MLFlow logger is much less performant than the default Tensorboard Logger, but this would not be much of a problem if we could avoid calls to the logger during the training loop.\r\n\r\n### Solution\r\nI've done a bit of debugging in the codebase and have been able to isolate the cause in two places\r\nhttps://github.com/PyTorchLightning/pytorch-lightning/blob/d438ad8a8db3e76d3ed4e3c6bc9b91d6b3266b8e/pytorch_lightning/loggers/mlflow.py#L125-L129\r\nHere `self.experiment` is called regardless of whether `self._run_id` exists. If we add an `if not self._run_id` here we avoid calling `self._mlflow_client.get_experiment_by_name(self._experiment_name)` on each step.\r\nHowever we still call it each time we log metrics to MFlow, because of the property `self.experiment`.\r\n\r\nhttps://github.com/PyTorchLightning/pytorch-lightning/blob/d438ad8a8db3e76d3ed4e3c6bc9b91d6b3266b8e/pytorch_lightning/loggers/mlflow.py#L100-L112\r\nHere if we store `expt` within the logger and only call `self._mlflow_client.get_experiment_by_name` when it does not exist, we eliminate all overhead, it runs as fast as fast as the tensorboard logger and all the mlflow logging appears to be working as expected.\r\n\r\nI'd be happy to raise a PR for this fix.\n", "before_files": [{"content": "# Copyright The PyTorch Lightning team.\n#\n# Licensed under the Apache License, Version 2.0 (the \"License\");\n# you may not use this file except in compliance with the License.\n# You may obtain a copy of the License at\n#\n#     http://www.apache.org/licenses/LICENSE-2.0\n#\n# Unless required by applicable law or agreed to in writing, software\n# distributed under the License is distributed on an \"AS IS\" BASIS,\n# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n# See the License for the specific language governing permissions and\n# limitations under the License.\n\n\"\"\"\nMLflow\n------\n\"\"\"\nfrom argparse import Namespace\nfrom time import time\nfrom typing import Optional, Dict, Any, Union\n\ntry:\n    import mlflow\n    from mlflow.tracking import MlflowClient\n    _MLFLOW_AVAILABLE = True\nexcept ModuleNotFoundError:  # pragma: no-cover\n    mlflow = None\n    MlflowClient = None\n    _MLFLOW_AVAILABLE = False\n\n\nfrom pytorch_lightning import _logger as log\nfrom pytorch_lightning.loggers.base import LightningLoggerBase, rank_zero_experiment\nfrom pytorch_lightning.utilities import rank_zero_only\n\n\nLOCAL_FILE_URI_PREFIX = \"file:\"\n\n\nclass MLFlowLogger(LightningLoggerBase):\n    \"\"\"\n    Log using `MLflow <https://mlflow.org>`_. Install it with pip:\n\n    .. code-block:: bash\n\n        pip install mlflow\n\n    Example:\n        >>> from pytorch_lightning import Trainer\n        >>> from pytorch_lightning.loggers import MLFlowLogger\n        >>> mlf_logger = MLFlowLogger(\n        ...     experiment_name=\"default\",\n        ...     tracking_uri=\"file:./ml-runs\"\n        ... )\n        >>> trainer = Trainer(logger=mlf_logger)\n\n    Use the logger anywhere in you :class:`~pytorch_lightning.core.lightning.LightningModule` as follows:\n\n    >>> from pytorch_lightning import LightningModule\n    >>> class LitModel(LightningModule):\n    ...     def training_step(self, batch, batch_idx):\n    ...         # example\n    ...         self.logger.experiment.whatever_ml_flow_supports(...)\n    ...\n    ...     def any_lightning_module_function_or_hook(self):\n    ...         self.logger.experiment.whatever_ml_flow_supports(...)\n\n    Args:\n        experiment_name: The name of the experiment\n        tracking_uri: Address of local or remote tracking server.\n            If not provided, defaults to `file:<save_dir>`.\n        tags: A dictionary tags for the experiment.\n        save_dir: A path to a local directory where the MLflow runs get saved.\n            Defaults to `./mlflow` if `tracking_uri` is not provided.\n            Has no effect if `tracking_uri` is provided.\n\n    \"\"\"\n\n    def __init__(self,\n                 experiment_name: str = 'default',\n                 tracking_uri: Optional[str] = None,\n                 tags: Optional[Dict[str, Any]] = None,\n                 save_dir: Optional[str] = './mlruns'):\n\n        if not _MLFLOW_AVAILABLE:\n            raise ImportError('You want to use `mlflow` logger which is not installed yet,'\n                              ' install it with `pip install mlflow`.')\n        super().__init__()\n        if not tracking_uri:\n            tracking_uri = f'{LOCAL_FILE_URI_PREFIX}{save_dir}'\n\n        self._experiment_name = experiment_name\n        self._experiment_id = None\n        self._tracking_uri = tracking_uri\n        self._run_id = None\n        self.tags = tags\n        self._mlflow_client = MlflowClient(tracking_uri)\n\n    @property\n    @rank_zero_experiment\n    def experiment(self) -> MlflowClient:\n        r\"\"\"\n        Actual MLflow object. To use MLflow features in your\n        :class:`~pytorch_lightning.core.lightning.LightningModule` do the following.\n\n        Example::\n\n            self.logger.experiment.some_mlflow_function()\n\n        \"\"\"\n        expt = self._mlflow_client.get_experiment_by_name(self._experiment_name)\n\n        if expt:\n            self._experiment_id = expt.experiment_id\n        else:\n            log.warning(f'Experiment with name {self._experiment_name} not found. Creating it.')\n            self._experiment_id = self._mlflow_client.create_experiment(name=self._experiment_name)\n\n        if not self._run_id:\n            run = self._mlflow_client.create_run(experiment_id=self._experiment_id, tags=self.tags)\n            self._run_id = run.info.run_id\n        return self._mlflow_client\n\n    @property\n    def run_id(self):\n        # create the experiment if it does not exist to get the run id\n        _ = self.experiment\n        return self._run_id\n\n    @property\n    def experiment_id(self):\n        # create the experiment if it does not exist to get the experiment id\n        _ = self.experiment\n        return self._experiment_id\n\n    @rank_zero_only\n    def log_hyperparams(self, params: Union[Dict[str, Any], Namespace]) -> None:\n        params = self._convert_params(params)\n        params = self._flatten_dict(params)\n        for k, v in params.items():\n            self.experiment.log_param(self.run_id, k, v)\n\n    @rank_zero_only\n    def log_metrics(self, metrics: Dict[str, float], step: Optional[int] = None) -> None:\n        assert rank_zero_only.rank == 0, 'experiment tried to log from global_rank != 0'\n\n        timestamp_ms = int(time() * 1000)\n        for k, v in metrics.items():\n            if isinstance(v, str):\n                log.warning(f'Discarding metric with string value {k}={v}.')\n                continue\n            self.experiment.log_metric(self.run_id, k, v, timestamp_ms, step)\n\n    @rank_zero_only\n    def finalize(self, status: str = 'FINISHED') -> None:\n        super().finalize(status)\n        status = 'FINISHED' if status == 'success' else status\n        if self.experiment.get_run(self.run_id):\n            self.experiment.set_terminated(self.run_id, status)\n\n    @property\n    def save_dir(self) -> Optional[str]:\n        \"\"\"\n        The root file directory in which MLflow experiments are saved.\n\n        Return:\n            Local path to the root experiment directory if the tracking uri is local.\n            Otherwhise returns `None`.\n        \"\"\"\n        if self._tracking_uri.startswith(LOCAL_FILE_URI_PREFIX):\n            return self._tracking_uri.lstrip(LOCAL_FILE_URI_PREFIX)\n\n    @property\n    def name(self) -> str:\n        return self.experiment_id\n\n    @property\n    def version(self) -> str:\n        return self.run_id\n", "path": "pytorch_lightning/loggers/mlflow.py"}], "after_files": [{"content": "# Copyright The PyTorch Lightning team.\n#\n# Licensed under the Apache License, Version 2.0 (the \"License\");\n# you may not use this file except in compliance with the License.\n# You may obtain a copy of the License at\n#\n#     http://www.apache.org/licenses/LICENSE-2.0\n#\n# Unless required by applicable law or agreed to in writing, software\n# distributed under the License is distributed on an \"AS IS\" BASIS,\n# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n# See the License for the specific language governing permissions and\n# limitations under the License.\n\n\"\"\"\nMLflow\n------\n\"\"\"\nfrom argparse import Namespace\nfrom time import time\nfrom typing import Optional, Dict, Any, Union\n\ntry:\n    import mlflow\n    from mlflow.tracking import MlflowClient\n    _MLFLOW_AVAILABLE = True\nexcept ModuleNotFoundError:  # pragma: no-cover\n    mlflow = None\n    MlflowClient = None\n    _MLFLOW_AVAILABLE = False\n\n\nfrom pytorch_lightning import _logger as log\nfrom pytorch_lightning.loggers.base import LightningLoggerBase, rank_zero_experiment\nfrom pytorch_lightning.utilities import rank_zero_only\n\n\nLOCAL_FILE_URI_PREFIX = \"file:\"\n\n\nclass MLFlowLogger(LightningLoggerBase):\n    \"\"\"\n    Log using `MLflow <https://mlflow.org>`_. Install it with pip:\n\n    .. code-block:: bash\n\n        pip install mlflow\n\n    Example:\n        >>> from pytorch_lightning import Trainer\n        >>> from pytorch_lightning.loggers import MLFlowLogger\n        >>> mlf_logger = MLFlowLogger(\n        ...     experiment_name=\"default\",\n        ...     tracking_uri=\"file:./ml-runs\"\n        ... )\n        >>> trainer = Trainer(logger=mlf_logger)\n\n    Use the logger anywhere in you :class:`~pytorch_lightning.core.lightning.LightningModule` as follows:\n\n    >>> from pytorch_lightning import LightningModule\n    >>> class LitModel(LightningModule):\n    ...     def training_step(self, batch, batch_idx):\n    ...         # example\n    ...         self.logger.experiment.whatever_ml_flow_supports(...)\n    ...\n    ...     def any_lightning_module_function_or_hook(self):\n    ...         self.logger.experiment.whatever_ml_flow_supports(...)\n\n    Args:\n        experiment_name: The name of the experiment\n        tracking_uri: Address of local or remote tracking server.\n            If not provided, defaults to `file:<save_dir>`.\n        tags: A dictionary tags for the experiment.\n        save_dir: A path to a local directory where the MLflow runs get saved.\n            Defaults to `./mlflow` if `tracking_uri` is not provided.\n            Has no effect if `tracking_uri` is provided.\n\n    \"\"\"\n\n    def __init__(self,\n                 experiment_name: str = 'default',\n                 tracking_uri: Optional[str] = None,\n                 tags: Optional[Dict[str, Any]] = None,\n                 save_dir: Optional[str] = './mlruns'):\n\n        if not _MLFLOW_AVAILABLE:\n            raise ImportError('You want to use `mlflow` logger which is not installed yet,'\n                              ' install it with `pip install mlflow`.')\n        super().__init__()\n        if not tracking_uri:\n            tracking_uri = f'{LOCAL_FILE_URI_PREFIX}{save_dir}'\n\n        self._experiment_name = experiment_name\n        self._experiment_id = None\n        self._tracking_uri = tracking_uri\n        self._run_id = None\n        self.tags = tags\n        self._mlflow_client = MlflowClient(tracking_uri)\n\n    @property\n    @rank_zero_experiment\n    def experiment(self) -> MlflowClient:\n        r\"\"\"\n        Actual MLflow object. To use MLflow features in your\n        :class:`~pytorch_lightning.core.lightning.LightningModule` do the following.\n\n        Example::\n\n            self.logger.experiment.some_mlflow_function()\n\n        \"\"\"\n        if self._experiment_id is None:\n            expt = self._mlflow_client.get_experiment_by_name(self._experiment_name)\n            if expt is not None:\n                self._experiment_id = expt.experiment_id\n            else:\n                log.warning(f'Experiment with name {self._experiment_name} not found. Creating it.')\n                self._experiment_id = self._mlflow_client.create_experiment(name=self._experiment_name)\n\n        if self._run_id is None:\n            run = self._mlflow_client.create_run(experiment_id=self._experiment_id, tags=self.tags)\n            self._run_id = run.info.run_id\n        return self._mlflow_client\n\n    @property\n    def run_id(self):\n        # create the experiment if it does not exist to get the run id\n        _ = self.experiment\n        return self._run_id\n\n    @property\n    def experiment_id(self):\n        # create the experiment if it does not exist to get the experiment id\n        _ = self.experiment\n        return self._experiment_id\n\n    @rank_zero_only\n    def log_hyperparams(self, params: Union[Dict[str, Any], Namespace]) -> None:\n        params = self._convert_params(params)\n        params = self._flatten_dict(params)\n        for k, v in params.items():\n            self.experiment.log_param(self.run_id, k, v)\n\n    @rank_zero_only\n    def log_metrics(self, metrics: Dict[str, float], step: Optional[int] = None) -> None:\n        assert rank_zero_only.rank == 0, 'experiment tried to log from global_rank != 0'\n\n        timestamp_ms = int(time() * 1000)\n        for k, v in metrics.items():\n            if isinstance(v, str):\n                log.warning(f'Discarding metric with string value {k}={v}.')\n                continue\n            self.experiment.log_metric(self.run_id, k, v, timestamp_ms, step)\n\n    @rank_zero_only\n    def finalize(self, status: str = 'FINISHED') -> None:\n        super().finalize(status)\n        status = 'FINISHED' if status == 'success' else status\n        if self.experiment.get_run(self.run_id):\n            self.experiment.set_terminated(self.run_id, status)\n\n    @property\n    def save_dir(self) -> Optional[str]:\n        \"\"\"\n        The root file directory in which MLflow experiments are saved.\n\n        Return:\n            Local path to the root experiment directory if the tracking uri is local.\n            Otherwhise returns `None`.\n        \"\"\"\n        if self._tracking_uri.startswith(LOCAL_FILE_URI_PREFIX):\n            return self._tracking_uri.lstrip(LOCAL_FILE_URI_PREFIX)\n\n    @property\n    def name(self) -> str:\n        return self.experiment_id\n\n    @property\n    def version(self) -> str:\n        return self.run_id\n", "path": "pytorch_lightning/loggers/mlflow.py"}]}