stared / livelossplot

Live training loss plot in Jupyter Notebook for Keras, PyTorch and others
https://p.migdal.pl/livelossplot
MIT License
1.29k stars 143 forks source link

Modularization: a serious rewrite #82

Closed stared closed 4 years ago

stared commented 4 years ago

The goal is version 0.5.0:

Some things won't be backward compatible.

A project with @bartolo1024. So far this branch does not work - work in progress.

To do:

stared commented 4 years ago

I made some progress on reimplementing metrics plots.

from livelossplot.plot_losses import PlotLosses
plotlosses = PlotLosses()
plotlosses.logger.groups = {'acccuracy': ['acc', 'val_acc'], 'log-loss': ['loss', 'val_loss']}
plotlosses.update({
    'acc': 0.5,
    'val_acc': 0.4,
    'loss': 1.2,
    'val_loss': 1.1
})
plotlosses.update({
    'acc': 0.55,
    'val_acc': 0.45,
    'loss': 1.1,
    'val_loss': 1.0
})
plotlosses.update({
    'acc': 0.65,
    'val_acc': 0.55,
    'loss': 1.0,
    'val_loss': 0.9
})

Then plotlosses.logger.grouped_log_history() gives

{'acccuracy': {'acc': [LogItem(step=0, value=0.5),
   LogItem(step=1, value=0.55),
   LogItem(step=2, value=0.65)],
  'val_acc': [LogItem(step=0, value=0.4),
   LogItem(step=1, value=0.45),
   LogItem(step=2, value=0.55)]},
 'log-loss': {'loss': [LogItem(step=0, value=1.2),
   LogItem(step=1, value=1.1),
   LogItem(step=2, value=1.0)],
  'val_loss': [LogItem(step=0, value=1.1),
   LogItem(step=1, value=1.0),
   LogItem(step=2, value=0.9)]}}

And plotlosses.send() (in Jupyter Notebook) draws:

image

Now @Bartolo1024 your turn. :)

stared commented 4 years ago

Instead of NamedTuple we may want to use TypedDict due to easier dict/JSON compatibility.

However, let's double-check as it may be only Python 3.8+ (not acceptable as of now).

Bartolo1024 commented 4 years ago

Instead of NamedTuple we may want to use TypedDict due to easier dict/JSON compatibility.

However, let's double-check as it may be only Python 3.8+ (not acceptable as of now).

We can use this for python 3.5, but with mypy_extensions in dependencies (as in your links). Currently, it is not so good.

stared commented 4 years ago

@Bartolo1024 Thanks, rebase-merged here.

For workflow - it is nice that there are tests, but I think conda is not needed. At the same time, we may need Python package from https://github.com/stared/livelossplot/actions/new.

stared commented 4 years ago

These version matrices seem to work well, vide antipatch #88.

image

stared commented 4 years ago

It seems to be an issue not with our library, but with matplotlib (support 3.6+). https://github.com/matplotlib/matplotlib/issues/12358

I vote for dropping Python 3.5 support, as matplotlib is the main dependency. Bonus: we will get f-strings! :)

stared commented 4 years ago
Bartolo1024 commented 4 years ago

What do you think about this old keras import: https://github.com/Bartolo1024/livelossplot/blob/serious-rewrite-old-keras-plugin-compatibility/livelossplot/__init__.py ? We can add custom module-finder to python import pipeline, detect old modules, print warning and import it dynamically. I have found good article about importlib if you want to read more about it: https://manikos.github.io/how-pythons-import-machinery-works

stared commented 4 years ago

@Bartolo1024 If it works, it is great.

However, this "deprecated" part (PlotLossesKeras, PlotLossesTensorFlowKeras) should be either un-deprecated (as a proper way to run things) or removed completely.

For supporting previous paths, I suggest adding all things supported in livelossplot 0.4.2.


For other parts, IMHO we should think hard about making a less Java-esque API.

Right now the code would work

from livelossplot import PlotLosses
from livelossplot.output_plugins.extrema_print import ExtremaPrint
from livelossplot.output_plugins.matplotlib import Matplotlib

Flat is better than nested.

I find Keras and PyTorch API nice, so it is, by all means, possible to use some nesting. Though, each time I write import matplotlib.pyplot as plt I die a little bit.

So, for simplicity, what do you think about:

Then it is simpler:

from livelossplot import PlotLosses
from livelossplot.outputs import Matplotlib, ExtremaPrint

plotlosses  = PlotLosses(outputs=[Matplotlib(), ExtremaPrint()])

OR

import livelossplot as llp

plotlosses = llp.PlotLosses(outputs=[llp.outputs.Matplotlib(), llp.outputs.ExtremaPrint()])

Let me know what you think about these API variants.

stared commented 4 years ago

Making it work for Python 3.5 was proven to be much more difficult than I have anticipated.

Another stuff - I try to make a version for Python 3.5 (then Matplotlib 3.0), but I get some issues with installing Cython. Or Numpy - I don't know, I DID specify numpy<1.18;python_version<"3.6" and still it tries to install 1.18. Don't know how to solve it.

Bartolo1024 commented 4 years ago

from livelossplot import PlotLosses from livelossplot.outputs import Matplotlib, ExtremaPrint

plotlosses = PlotLosses(outputs=[Matplotlib(), ExtremaPrint()])

I like this. Simplified "inputs" and "outputs" are better, than names with "_plugin" suffix.

stared commented 4 years ago

So, after some thinking I went for two syntaxes:

from livelossplot.inputs.keras import PlotLossesCallback
from livelossplot import PlotLossesKeras

I think that I will favor the second one, as:

Now I focus on updating examples. How is your work going?

Bartolo1024 commented 4 years ago

I have auto group generation and auto metric to name, but don't know if it is pure. https://github.com/stared/livelossplot/pull/92

loss
        Validation loss          (min:    0.105, max:    2.000, cur:    0.105)
        Training loss            (min:    0.091, max:    0.500, cur:    0.091)
acc
        Validation Accuracy      (min:    0.754, max:    1.000, cur:    0.975)
        Training Accuracy        (min:    0.719, max:    0.990, cur:    0.948)
Bartolo1024 commented 4 years ago

After all can you: