Skip to content

Commit 51d5799

Browse files
committed
[DLMED] add tutorial
Signed-off-by: Nic Ma <[email protected]>
1 parent 48ff664 commit 51d5799

File tree

2 files changed

+119
-26
lines changed

2 files changed

+119
-26
lines changed
Lines changed: 119 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,119 @@
1+
# Overview
2+
This tutorial shows how to extend the features of workflow in the model-zoo bundles based on `event-handler` mechanism.
3+
Here we try to add the execution time computation logic in the spleen segmentation bundle.
4+
5+
## Event-handler mechanism
6+
The bundles in the `model-zoo` are constructed by MONAI workflow, which can enable quick start of training and evaluation experiments.
7+
The MONAI workflow is compatible with pytorch-ignite `Engine` and `Event-Handler` mechanism: https://pytorch-ignite.ai/.
8+
9+
So we can easily extend new features to the workflow by defining a new independent event handler and attaching to the workflow engine.
10+
11+
Here is all the supported `Event` in MONAI:
12+
| Module | Event name | Description |
13+
| --- | --- | --- |
14+
| ignite.engine.Events | STARTED | triggered when engine's run is started |
15+
| ignite.engine.Events | EPOCH_STARTED | triggered when the epoch is started |
16+
| ignite.engine.Events | GET_BATCH_STARTED | triggered before next batch is fetched |
17+
| ignite.engine.Events | GET_BATCH_COMPLETED | triggered after the batch is fetched |
18+
| ignite.engine.Events | ITERATION_STARTED | triggered when an iteration is started |
19+
| monai.engines.IterationEvents | FORWARD_COMPLETED | triggered when `network(image, label)` is completed |
20+
| monai.engines.IterationEvents | LOSS_COMPLETED | triggered when `loss(pred, label)` is completed |
21+
| monai.engines.IterationEvents | BACKWARD_COMPLETED | triggered when `loss.backward()` is completed |
22+
| monai.engines.IterationEvents | MODEL_COMPLETED | triggered when all the model related operations completed |
23+
| monai.engines.IterationEvents | INNER_ITERATION_STARTED | triggered when the iteration has an inner loop and the loop is started |
24+
| monai.engines.IterationEvents | INNER_ITERATION_COMPLETED | triggered when the iteration has an inner loop and the loop is completed |
25+
| ignite.engine.Events | ITERATION_COMPLETED | triggered when the iteration is ended |
26+
| ignite.engine.Events | DATALOADER_STOP_ITERATION | triggered when dataloader has no more data to provide |
27+
| ignite.engine.Events | EXCEPTION_RAISED | triggered when an exception is encountered |
28+
| ignite.engine.Events | TERMINATE_SINGLE_EPOCH | triggered when the run is about to end the current epoch |
29+
| ignite.engine.Events | TERMINATE | triggered when the run is about to end completely |
30+
| ignite.engine.Events | INTERRUPT | triggered when the run is interrupted |
31+
| ignite.engine.Events | EPOCH_COMPLETED | triggered when the epoch is ended |
32+
| ignite.engine.Events | COMPLETED | triggered when engine's run is completed |
33+
34+
For more information about the `Event` of pytorch-ignite, please refer to:
35+
https://pytorch.org/ignite/generated/ignite.engine.events.Events.html
36+
37+
Users can also register their own customized `Event` to the workflow engine.
38+
39+
A typical handler must contain the `attach()` function and several callback functions to handle the attached events.
40+
For example, here we define a dummy handler to do some logic when iteration started and completed for every 5 iterations:
41+
```py
42+
from ignite.engine import Engine, Events
43+
44+
45+
class DummyHandler:
46+
def attach(self, engine: Engine) -> None:
47+
engine.add_event_handler(Events.ITERATION_STARTED(every=5), self.iteration_started)
48+
engine.add_event_handler(Events.ITERATION_COMPLETED(every=5), self.iteration_completed)
49+
50+
def iteration_started(self, engine: Engine) -> None:
51+
pass
52+
53+
def iteration_completed(self, engine: Engine) -> None:
54+
pass
55+
```
56+
57+
## Download example MONAI bundle from model-zoo
58+
```
59+
python -m monai.bundle download --name spleen_ct_segmentation --version "0.1.1" --bundle_dir "./"
60+
```
61+
62+
## Extend the workflow to print the execution time for every iteration, every epoch and total time
63+
Here we define a new handler in `spleen_ct_segmentation/scripts/timer.py` to compute and print the time consumption details:
64+
```py
65+
from time import time
66+
from ignite.engine import Engine, Events
67+
68+
69+
class TimerHandler:
70+
def __init__(self) -> None:
71+
self.start_time = 0
72+
self.epoch_start_time = 0
73+
self.iteration_start_time = 0
74+
75+
def attach(self, engine: Engine) -> None:
76+
engine.add_event_handler(Events.STARTED, self.started)
77+
engine.add_event_handler(Events.EPOCH_STARTED, self.epoch_started)
78+
engine.add_event_handler(Events.ITERATION_STARTED, self.iteration_started)
79+
engine.add_event_handler(Events.ITERATION_COMPLETED, self.iteration_completed)
80+
engine.add_event_handler(Events.EPOCH_COMPLETED, self.epoch_completed)
81+
engine.add_event_handler(Events.COMPLETED, self.completed)
82+
83+
def started(self, engine: Engine) -> None:
84+
self.start_time = time()
85+
86+
def epoch_started(self, engine: Engine) -> None:
87+
self.epoch_start_time = time()
88+
89+
def iteration_started(self, engine: Engine) -> None:
90+
self.iteration_start_time = time()
91+
92+
def iteration_completed(self, engine: Engine) -> None:
93+
print(f"iteration {engine.state.iteration} execution time: {time() - self.iteration_start_time}")
94+
95+
def epoch_completed(self, engine: Engine) -> None:
96+
print(f"epoch {engine.state.epoch} execution time: {time() - self.epoch_start_time}")
97+
98+
def completed(self, engine: Engine) -> None:
99+
print(f"total execution time: {time() - self.start_time}")
100+
```
101+
Then add the handler to the `"train": {"handlers: [...]"}` list of `train.json` config:
102+
```json
103+
{
104+
"_target_": "scripts.timer.TimerHandler"
105+
}
106+
```
107+
108+
## Command example
109+
To run the workflow with this customized handler, `PYTHONPATH` should be revised to include the path to the customized scripts:
110+
```
111+
export PYTHONPATH=$PYTHONPATH:"<path to 'spleen_ct_segmentation/scripts'>"
112+
```
113+
And please make sure the folder `spleen_ct_segmentation/scripts` is a valid python module (it has a `__init__.py` file in the folder).
114+
115+
Execute training:
116+
117+
```
118+
python -m monai.bundle run training --meta_file configs/metadata.json --config_file configs/train.json --logging_file configs/logging.conf
119+
```

model_zoo/extend_workflow_with_handler/README.md

Lines changed: 0 additions & 26 deletions
This file was deleted.

0 commit comments

Comments
 (0)