Repository: pytorch/ignite

Issue:
StateParamScheduler raises KeyError when save_history=true and multiple parameters are scheduled
## 🐛 Bug description
When scheduling multiple parameters on an engine, a `KeyError` exception is raised when `save_history=True`
To reproduce the bug: 
```python
    engine = Engine(lambda e, b: None)
    exp_state_parameter_scheduler1 = ExpStateScheduler(
        param_name="exp_scheduled_param1", initial_value=initial_value, gamma=gamma, save_history=True
    )
    exp_state_parameter_scheduler2 = ExpStateScheduler(
        param_name="exp_scheduled_param2", initial_value=initial_value, gamma=gamma, save_history=True
    )
    exp_state_parameter_scheduler1.attach(engine, Events.EPOCH_COMPLETED)
    exp_state_parameter_scheduler2.attach(engine, Events.EPOCH_COMPLETED)
    engine.run([0] * 8, max_epochs=max_epochs)
```
A fix should be applied here :
https://github.com/pytorch/ignite/blob/79678b916e1fbef702f861d71d5832e17c188351/ignite/handlers/state_param_scheduler.py#L55

```python
        if self.save_history:
            if not hasattr(engine.state, "param_history") or engine.state.param_history is None:  # type: ignore
                setattr(engine.state, "param_history", {})
            engine.state.param_history.setdefault(self.param_name, [])  # type: ignore[attr-defined]
```


<!-- A clear and concise description of what the bug is. -->
<!-- Please, add steps on how to reproduce it. -->
<!-- If you have a code sample, error messages, stack traces, please provide it here as well -->
<!-- A clear and concise description of what you expected to happen. -->

## Environment

- PyTorch Version (e.g., 1.4):
- Ignite Version (e.g., 0.3.0):
- OS (e.g., Linux):
- How you installed Ignite (`conda`, `pip`, source):
- Python version:
- Any other relevant information:



Discussion:

Resolving patch:
diff --git a/ignite/handlers/state_param_scheduler.py b/ignite/handlers/state_param_scheduler.py
--- a/ignite/handlers/state_param_scheduler.py
+++ b/ignite/handlers/state_param_scheduler.py
@@ -52,7 +52,7 @@ def attach(
         if self.save_history:
             if not hasattr(engine.state, "param_history") or engine.state.param_history is None:  # type: ignore
                 setattr(engine.state, "param_history", {})
-                engine.state.param_history.setdefault(self.param_name, [])  # type: ignore[attr-defined]
+            engine.state.param_history.setdefault(self.param_name, [])  # type: ignore[attr-defined]
 
         engine.add_event_handler(event, self)
 


Test patch:
diff --git a/tests/ignite/handlers/test_state_param_scheduler.py b/tests/ignite/handlers/test_state_param_scheduler.py
--- a/tests/ignite/handlers/test_state_param_scheduler.py
+++ b/tests/ignite/handlers/test_state_param_scheduler.py
@@ -40,6 +40,11 @@ def __call__(self, event_index):
     {"param_name": "custom_scheduled_param", "lambda_obj": LambdaState(initial_value=10, gamma=0.99)},
 )
 
+config7 = (
+    StepStateScheduler,
+    {"param_name": "step_scheduled_param", "initial_value": 10, "gamma": 0.99, "step_size": 5},
+)
+
 
 @pytest.mark.parametrize(
     "max_epochs, milestones_values,  save_history, expected_param_history", [config1, config2],
@@ -354,6 +359,28 @@ def _test(scheduler_cls, **scheduler_kwargs):
             )
 
 
+def test_multiple_scheduler_with_save_history():
+    engine_multiple_schedulers = Engine(lambda e, b: None)
+    configs = [config3, config4, config5, config6, config7]
+    for scheduler, config in configs:
+        if "save_history" in config:
+            del config["save_history"]
+        _scheduler = scheduler(**config, save_history=True)
+        _scheduler.attach(engine_multiple_schedulers)
+
+    engine_multiple_schedulers.run([0] * 8, max_epochs=2)
+
+    for scheduler, config in configs:
+        engine = Engine(lambda e, b: None)
+        _scheduler = scheduler(**config, save_history=True)
+        _scheduler.attach(engine)
+        engine.run([0] * 8, max_epochs=2)
+        torch.testing.assert_allclose(
+            engine_multiple_schedulers.state.param_history[config["param_name"]],
+            engine.state.param_history[config["param_name"]],
+        )
+
+
 def test_docstring_examples():
     # LambdaStateScheduler