|
1 | 1 | # trainplot |
2 | 2 |
|
3 | | -Dynamically updating plots in Jupyter notebooks, e.g. for visualizing training progress. Inspired by [livelossplot](https://github.com/stared/livelossplot), and aims to be easier to use with better jupyter notebook support. |
4 | | - |
5 | | - |
6 | | -## Installation |
| 3 | +Dynamically updating plots in Jupyter notebooks, e.g. for visualizing machine learning training progress. |
7 | 4 |
|
8 | 5 | ```bash |
| 6 | + |
9 | 7 | pip install trainplot |
10 | 8 | ``` |
11 | 9 |
|
| 10 | +<p align="center"><img src="https://github.com/user-attachments/assets/03bd661c-37d7-41a4-ba91-891f57ebfcf8" width="400" center></p> |
| 11 | + |
| 12 | + |
12 | 13 |
|
13 | 14 | ## Usage |
14 | 15 |
|
15 | | -This is a simple example ([example notebook](examples/basic-example.ipynb)): |
| 16 | +Basic usage: |
16 | 17 |
|
17 | 18 | ```python |
18 | 19 | from trainplot import plot |
19 | | -from time import sleep |
20 | 20 |
|
21 | | -for i in range(50): |
22 | | - plot(loss = 1/(i+1), acc = 1-1/(.01*i**2+1)) |
23 | | - sleep(.1) |
| 21 | +for i in range(100): |
| 22 | + loss = ... |
| 23 | + acc = ... |
| 24 | + plot(loss=loss, accuracy=acc) |
24 | 25 | ``` |
25 | 26 |
|
26 | | -<img src="https://github.com/JonasLoos/trainplot/assets/33965649/935e8d52-0c37-4469-9cb8-24fa77b467ff" width="500"> |
27 | | - |
28 | | ---- |
29 | | - |
30 | | -Example for the tf/keras callback ([example notebook](examples/tf-keras-mnist-example.ipynb)): |
| 27 | +If you use keras, you can use the `TrainPlotKerasCallback`: |
31 | 28 |
|
32 | 29 | ```python |
33 | 30 | from trainplot import TrainPlotKeras |
34 | 31 |
|
35 | 32 | model = ... |
36 | | -model.fit(x_train, y_train, validation_data=(x_test, y_test), epochs=10, callbacks=[TrainPlotKeras()]) |
37 | | -``` |
38 | | - |
39 | | -<img src="https://github.com/JonasLoos/trainplot/assets/33965649/4ddff79a-978e-434c-a6c3-571cf48c0892" width="500"> |
40 | | - |
41 | | ---- |
42 | | - |
43 | | -It also works together with e.g. `tqdm.notebook` and printing ([example notebook](examples/different-output-example.ipynb)): |
44 | | - |
45 | | -```python |
46 | | -from trainplot import plot |
47 | | -from tqdm.notebook import trange |
48 | | -from time import sleep |
49 | | - |
50 | | -for i in trange(50): |
51 | | - plot(i=i, root=i**.5) |
52 | | - if i % 10 == 0: |
53 | | - print(f'currently at {i} iterations') |
54 | | - sleep(0.1) |
| 33 | +model.fit(x_train, y_train, validation_data=(x_test, y_test), epochs=10, callbacks=[TrainPlotKerasCallback()]) |
55 | 34 | ``` |
56 | 35 |
|
57 | | -<img src="https://github.com/JonasLoos/trainplot/assets/33965649/7571efab-7a3f-4414-b537-a2dffd9e1bec" width="400"> |
| 36 | +For more examples, see the [`examples`](examples/) folder. |
58 | 37 |
|
59 | | ---- |
60 | | - |
61 | | -You can make use of a TrainPlot object to add a bunch of custumizations ([example notebook](examples/4plots-example.ipynb)): |
62 | | - |
63 | | -```python |
64 | | -from trainplot import TrainPlot |
65 | | -from time import sleep |
66 | | - |
67 | | -tp = TrainPlot( |
68 | | - update_period=.2, |
69 | | - fig_args=dict(nrows=2, ncols=2, figsize=(10, 8), gridspec_kw={'height_ratios': [1, 1], 'width_ratios': [1, 1]}), |
70 | | - plot_pos={'loss': (0, 0, 0), 'accuracy': (0, 1, 0), 'val_loss': (1, 0, 0), 'val_accuracy': (1, 1, 0)}, |
71 | | - plot_args={'loss': {'color': 'orange'}, 'accuracy': {'color': 'green'}, 'val_loss': {'color': 'orange', 'label': 'validation loss'}, 'val_accuracy': {'color': 'green', 'label': 'validation accuracy'}}, |
72 | | -) |
73 | | - |
74 | | -for i in range(100, 200): |
75 | | - tp(step=i, loss=(i/100-2)**4, accuracy=i/2, val_loss=(i/100-2.1)**4, val_accuracy=i/2.1) |
76 | | - sleep(0.1) |
77 | | -``` |
78 | 38 |
|
79 | | -<img src="https://github.com/JonasLoos/trainplot/assets/33965649/599314e2-d1c1-4044-a915-6316722a2324" width="600"> |
| 39 | +## Features |
80 | 40 |
|
81 | | ---- |
| 41 | +* **Lightweight**: No external plotting dependencies |
| 42 | +* **Custom rendering**: Uses HTML5 Canvas for fast, smooth updates |
| 43 | +* **Multiple series**: Automatically handles multiple data series with different colors |
| 44 | +* **Real-time updates**: Configurable update periods to balance performance and responsiveness |
| 45 | +* **Keras support**: Built-in callback for TensorFlow/Keras models |
82 | 46 |
|
83 | | -More: |
84 | | -* When using a Trainplot object, you can also put the plot into a separate cell than the training loop: [example notebook](examples/separate-output-example.ipynb) |
85 | | -* Experimental plotly support (`from trainplot.trainplot import TrainPlotPlotlyExperimental`): [example notebook](examples/plotly-example.ipynb) |
86 | 47 |
|
87 | 48 | ## How it works |
88 | 49 |
|
89 | | -Trainplot outputs the matplotlib figure to an `ipywidgets.Output` widget, so it doesn't interfere with other outputs like `tqdm` or print statements. To avoid wasting resources and flickering, the figure is only updated with a given `update_period`. |
90 | | -A `post_run_cell` callback is added to the `IPython` instance, so that all updated TrainPlot figures include all new data when a cell execution is finished. |
91 | | -When using `trainplot.plot`, a TrainPlot object is created for the current cell and cell-execution-count. |
| 50 | +Trainplot uses a custom HTML5 Canvas-based plotting solution that renders directly in Jupyter notebooks. For synchronization between Python and the JavaScript-based plotting function, [`anywidget`](https://github.com/manzt/anywidget) is used. To avoid wasting resources and flickering, the plot is only updated with a given `update_period`. A `post_run_cell` callback is added to the `IPython` instance, so that all updated TrainPlot figures include all new data when a cell execution is finished. When using `trainplot.plot`, a TrainPlot object is created for the current cell. |
0 commit comments