Repository: pytorch/ignite

Issue:
Wrong event used in doc example of "ignite.contrib.handlers.LRScheduler"
At first, thanks for this nice project! 

While reading the documentation, I encountered, that in the  little example on how to use `ignite.contrib.handlers.LRScheduler` the `ITERATION_COMPLETED` event is used instead of the `ITERATION_STARTED` event.  From pytorch documentation, the event should be triggered, when the iteration started.



Example from pytorch documentation ([doc link](https://pytorch.org/docs/stable/optim.html#torch.optim.lr_scheduler.StepLR)):

```python
>>> # Assuming optimizer uses lr = 0.05 for all groups
>>> # lr = 0.05     if epoch < 30
>>> # lr = 0.005    if 30 <= epoch < 60
>>> # lr = 0.0005   if 60 <= epoch < 90
>>> # ...
>>> scheduler = StepLR(optimizer, step_size=30, gamma=0.1)
>>> for epoch in range(100):
>>>     scheduler.step()  # is called at iteration start
>>>     train(...)
>>>     validate(...)
```

Example from `ignite.contrib` documentation ([doc link](https://pytorch.org/ignite/contrib/handlers.html#ignite.contrib.handlers.LRScheduler)):
```python
from ignite.contrib.handlers.param_scheduler import LRScheduler
from torch.optim.lr_scheduler import StepLR

step_scheduler = StepLR(optimizer, step_size=3, gamma=0.1)
scheduler = LRScheduler(step_scheduler)
trainer.add_event_handler(Events.ITERATION_COMPLETED, scheduler)  # Should this be Events.ITERATION_STARTED?
```

Minimum pytorch example to show behaviour of pytorch schedulers:
```python
import torch
optimizer = torch.optim.Adam([torch.Tensor([1,2,3])], lr=0.001) # initial learning rate is 0.001
lr_scheduler = torch.optim.lr_scheduler.StepLR(optimizer ,30)

lr_scheduler.get_lr() # outputs 0.01 instead of 0.001

lr_scheduler.step()
lr_scheduler.get_lr() # outputs 0.001 after first call of step()
```



Discussion:
@Bibonaut yes, you are correct about that, thanks for catching !
If you would like to send a PR, we'll highly appreciate community contributions. 

PS. glad that you like the project !

Resolving patch:
diff --git a/ignite/contrib/handlers/param_scheduler.py b/ignite/contrib/handlers/param_scheduler.py
--- a/ignite/contrib/handlers/param_scheduler.py
+++ b/ignite/contrib/handlers/param_scheduler.py
@@ -189,7 +189,7 @@ class LinearCyclicalScheduler(CyclicalScheduler):
         from ignite.contrib.handlers.param_scheduler import LinearCyclicalScheduler
 
         scheduler = LinearCyclicalScheduler(optimizer, 'lr', 1e-3, 1e-1, len(train_loader))
-        trainer.add_event_handler(Events.ITERATION_COMPLETED, scheduler)
+        trainer.add_event_handler(Events.ITERATION_STARTED, scheduler)
         #
         # Linearly increases the learning rate from 1e-3 to 1e-1 and back to 1e-3
         # over the course of 1 epoch
@@ -233,7 +233,7 @@ class CosineAnnealingScheduler(CyclicalScheduler):
         from ignite.contrib.handlers.param_scheduler import CosineAnnealingScheduler
 
         scheduler = CosineAnnealingScheduler(optimizer, 'lr', 1e-1, 1e-3, len(train_loader))
-        trainer.add_event_handler(Events.ITERATION_COMPLETED, scheduler)
+        trainer.add_event_handler(Events.ITERATION_STARTED, scheduler)
         #
         # Anneals the learning rate from 1e-1 to 1e-3 over the course of 1 epoch.
         #
@@ -251,10 +251,10 @@ class CosineAnnealingScheduler(CyclicalScheduler):
         )
 
         scheduler1 = LinearCyclicalScheduler(optimizer.param_groups[0], 'lr', 1e-7, 1e-5, len(train_loader))
-        trainer.add_event_handler(Events.ITERATION_COMPLETED, scheduler1, "lr (base)")
+        trainer.add_event_handler(Events.ITERATION_STARTED, scheduler1, "lr (base)")
 
         scheduler2 = CosineAnnealingScheduler(optimizer.param_groups[1], 'lr', 1e-5, 1e-3, len(train_loader))
-        trainer.add_event_handler(Events.ITERATION_COMPLETED, scheduler2, "lr (fc)")
+        trainer.add_event_handler(Events.ITERATION_STARTED, scheduler2, "lr (fc)")
 
     .. [Smith17] Smith, Leslie N. "Cyclical learning rates for training neural networks."
                  Applications of Computer Vision (WACV), 2017 IEEE Winter Conference on. IEEE, 2017
@@ -291,7 +291,7 @@ class ConcatScheduler(ParamScheduler):
         scheduler_2 = CosineAnnealingScheduler(optimizer, "lr", start_value=0.5, end_value=0.01, cycle_size=60)
 
         combined_scheduler = ConcatScheduler(schedulers=[scheduler_1, scheduler_2], durations=[30, ])
-        trainer.add_event_handler(Events.ITERATION_COMPLETED, combined_scheduler)
+        trainer.add_event_handler(Events.ITERATION_STARTED, combined_scheduler)
         #
         # Sets the Learning rate linearly from 0.1 to 0.5 over 30 iterations. Then
         # starts an annealing schedule from 0.5 to 0.01 over 60 iterations.
@@ -409,7 +409,7 @@ class LRScheduler(ParamScheduler):
 
         step_scheduler = StepLR(optimizer, step_size=3, gamma=0.1)
         scheduler = LRScheduler(step_scheduler)
-        trainer.add_event_handler(Events.ITERATION_COMPLETED, scheduler)
+        trainer.add_event_handler(Events.ITERATION_STARTED, scheduler)
     """
 
     def __init__(self, lr_scheduler, save_history=False, **kwds):


Test patch: