-
Notifications
You must be signed in to change notification settings - Fork 3.4k
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
Abstract log_figure API that implements reasonable default for all lo… #6227
Abstract log_figure API that implements reasonable default for all lo… #6227
Conversation
…ggers Takes a plt.figure (along with some metadata) and logs it to the respective logger - CSV logger and testtube are in silent no-op - matplotlib becomes base requirement
Hello @Haydnspass! Thanks for updating this PR. There are currently no PEP 8 issues detected in this Pull Request. Cheers! 🍻 Comment last updated at 2021-06-18 11:17:14 UTC |
@@ -173,6 +174,20 @@ def log_metrics(self, metrics: Dict[str, float], step: Optional[int] = None): | |||
""" | |||
pass | |||
|
|||
def log_figure(self, name: str, figure: plt.figure, step: Optional[int] = None, close: bool = True) -> None: |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think we should add additional **kwargs
here.
When the user knows they are using a particular logger that supports additinal arguments, we should allow it to be passed down.
for example, in one of the loggers you have a description, and this could be customized then by the user.
This would then still be logger agnostic, where loggers simply ignore unknown **kwargs
when it's not applicable.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Funnily I had it including **kwargs two times, and changed it back and forth ...
I do not like it because:
- Silently ignoring arguments that are unexpected is not what python does by default when you parse **kwargs
- It'll most certainly break for
LoggerCollection
unless one implements a more complex logic which then makes the whole implementation unnecessary
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I also think **kwargs
is really necessary here. Each logger can have many different arguments
Silently ignoring arguments that are unexpected is not what python does by default when you parse **kwargs
I don't get this
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
If you add **kwargs it will break LoggerCollection if you don't do anything. So what do you do if you have logger A that can take a certain argument that logger B in your collection does not? Ignore argument, raise?
Or add more complex logic that looks something like this
my_mwargs = {
'loggerA': {'kwarga': 1},
'loggerB': {'kwargb': 2},
}
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
--> Needs design decision
pytorch_lightning/loggers/mlflow.py
Outdated
figure.savefig(filename) | ||
self.experiment.log_artifact(self.run_id, filename, artifact_path="figure_" + name) | ||
|
||
Path(filename).unlink() # delete temporary file |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
do we need to wait here before this was uploaded (upload may be async, not sure)?
Also if this is temporary, can we consider this to be saved in /tmp?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
That's a good point, couldn't find anything in the docs of mlflow ...
I don't like this temporary thing anyways but could not come up with a better solution
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Changed to temporary file
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Overall looks good ! Some comments to be addressed from @awaelchli @justusschock
Co-authored-by: Adrian Wälchli <aedu.waelchli@gmail.com>
Co-authored-by: Adrian Wälchli <aedu.waelchli@gmail.com>
Co-authored-by: Nicki Skafte <skaftenicki@gmail.com>
This pull request has been automatically marked as stale because it has not had recent activity. It will be closed in 7 days if no further activity occurs. If you need further help see our docs: https://pytorch-lightning.readthedocs.io/en/latest/generated/CONTRIBUTING.html#pull-request or ask the assistance of a core contributor here or on Slack. Thank you for your contributions. |
# ToDo: Once its stable, use ml_flow.log_figure | ||
with tempfile.TemporaryDirectory() as tmp_dir: | ||
figure_path = Path(tmp_dir) / figure_fname | ||
figure.savefig(figure_path) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Did you check the figure is properly rendered ? From past experience, figure.savefig
never worked for me.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Just changed the test for it to an actual functional one instead of mocking, and for me it works fine. The .png / .pdf is created as expected.
Locally it works as well. What happened in your case? The file was created but not filled?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It was filled, but savefig was adding borders and axis around the image.
Hi @Haydnspass , I am sorry that the response was delayed so much. What do you think about enabling general media logging first (see #9545 for an example in wandb) for all loggers and then treat (matplotlib) figures just as a special case of images? That does not mean, that we need to abandon this PR, but maybe you and @borisdayma can put together a draft for a more general logger API for media upon which we can then rebuild this PR? |
@justusschock But of course, I don't have an emotional connection to this PR :D if something better/more general appears then this should be used. The issue for me is, that I don't have much time to work on this, and its a bit unfortunate to run behind master all the time and spend the time on resolving conflicts :/ |
We've chosen to move away from defining a set interface for all logger implementations as it becomes limiting and difficult when all their nuances and differences are considered. Closing this PR. Thank you so much for your effort anyways @Haydnspass! 💜 |
Transfer of #4975
Sorry for the mess with choosing the wrong branch. It was faster for me to manually include the changes, so I am opening a new PR.
What does this PR do?
Make abstraction layer for figure logging, i.e. add default for logging figures for all implemented loggers.
My suggestion to #4973
ToDo:
TestTube(defaults to base)CSV(defaults to base)Before submitting
PR review
Anyone in the community is free to review the PR once the tests have passed.
Before you start reviewing make sure you have read Review guidelines. In short, see the following bullet-list:
Did you have fun?
Make sure you had fun coding 🙃