Repository: pytorch/ignite

Issue:
Checkpoint loading doesn't work if object doesn't contain a torch.nn.Module
## 🐛 Bug description

Running the following code:
```python
from ignite.handlers import Checkpoint
Checkpoint.load_objects(to_load=to_load, checkpoint=checkpoint)
```

results in the following error:
```
load_state_dict() got an unexpected keyword argument 'strict'
```

if ```to_load``` doesn't contain a ```torch.nn.Module```. 

For example, ```{"optimizer": optimizer}``` fails, but ```{"model": torch.nn.Linear(10, 10)}``` succeeds.

## Notebook to reproduce
https://colab.research.google.com/drive/1G-iVC-ixMQrw90AEp5mDuSjxUAPyO8YF?usp=sharing


## Environment
Run on google colab with:
torch version 1.10.0+cu111
ignite version 0.4.8




Discussion:
@KevinMusgrave thanks for the report. I tried your colab and it fails elsewhere.

However, you should be able to save model, optimizer, lr_scheduler, trainer etc
Here is a working code (tested in your colab)
```python
!rm -rf /tmp/models

import torch
from ignite.engine import Engine, Events
from ignite.handlers import ModelCheckpoint, Checkpoint
trainer = Engine(lambda engine, batch: None)
handler = ModelCheckpoint('/tmp/models', 'myprefix', n_saved=None, create_dir=True)
model = torch.nn.Linear(3, 3)
optimizer = torch.optim.SGD(model.parameters(), lr=1e-3)
to_save = {"weights": model, "optimizer": optimizer, "trainer": trainer}
trainer.add_event_handler(Events.EPOCH_COMPLETED(every=2), handler, to_save)
trainer.run(torch.randn(10, 1), 5)

to_load = to_save
checkpoint_fp = "/tmp/models/myprefix_checkpoint_40.pt"
checkpoint = torch.load(checkpoint_fp)
Checkpoint.load_objects(to_load=to_load, checkpoint=checkpoint)

# or using a string for checkpoint filepath

to_load = to_save
checkpoint_fp = "/tmp/models/myprefix_checkpoint_40.pt"
Checkpoint.load_objects(to_load=to_load, checkpoint=checkpoint_fp)
```

Meanwhile I'll try to figure out what is the issue that give you reported error: "load_state_dict() got an unexpected keyword argument 'strict'".

EDIT:

I see, both `Checkpoint.load_objects` and `ModelCheckpoint.load_objects` do not work if saving only one object like optimizer or trainer.
Thanks again for reporting and the repro code!

Resolving patch:
diff --git a/ignite/handlers/checkpoint.py b/ignite/handlers/checkpoint.py
--- a/ignite/handlers/checkpoint.py
+++ b/ignite/handlers/checkpoint.py
@@ -573,25 +573,27 @@ def load_objects(to_load: Mapping, checkpoint: Union[str, Mapping], **kwargs: An
             warnings.warn("kwargs contains keys other than strict and these will be ignored")
 
         is_state_dict_strict = kwargs.get("strict", True)
+
+        def _load_object(obj: Any, chkpt_obj: Any) -> None:
+            if isinstance(obj, (nn.DataParallel, nn.parallel.DistributedDataParallel)):
+                obj = obj.module
+            if isinstance(obj, torch.nn.Module):
+                obj.load_state_dict(chkpt_obj, strict=is_state_dict_strict)
+            else:
+                obj.load_state_dict(chkpt_obj)
+
         if len(to_load) == 1:
             # single object and checkpoint is directly a state_dict
             key, obj = list(to_load.items())[0]
             if key not in checkpoint_obj:
-                if isinstance(obj, (nn.DataParallel, nn.parallel.DistributedDataParallel)):
-                    obj = obj.module
-                obj.load_state_dict(checkpoint_obj, strict=is_state_dict_strict)
+                _load_object(obj, checkpoint_obj)
                 return
 
         # multiple objects to load
         for k, obj in to_load.items():
             if k not in checkpoint_obj:
                 raise ValueError(f"Object labeled by '{k}' from `to_load` is not found in the checkpoint")
-            if isinstance(obj, (nn.DataParallel, nn.parallel.DistributedDataParallel)):
-                obj = obj.module
-            if isinstance(obj, torch.nn.Module):
-                obj.load_state_dict(checkpoint_obj[k], strict=is_state_dict_strict)
-            else:
-                obj.load_state_dict(checkpoint_obj[k])
+            _load_object(obj, checkpoint_obj[k])
 
     def state_dict(self) -> "OrderedDict[str, List[Tuple[int, str]]]":
         """Method returns state dict with saved items: list of ``(priority, filename)`` pairs.


Test patch:
diff --git a/tests/ignite/handlers/test_checkpoint.py b/tests/ignite/handlers/test_checkpoint.py
--- a/tests/ignite/handlers/test_checkpoint.py
+++ b/tests/ignite/handlers/test_checkpoint.py
@@ -1671,3 +1671,22 @@ def test_get_default_score_fn():
     score_fn = Checkpoint.get_default_score_fn("loss", -1)
     score = score_fn(engine)
     assert score == -0.123
+
+
+@pytest.mark.parametrize("obj_to_save", ["optim", "trainer"])
+def test_load_single_object(obj_to_save, dirname):
+    # Checks https://github.com/pytorch/ignite/issues/2479
+
+    trainer = Engine(lambda e, b: None)
+    if obj_to_save == "optim":
+        t = torch.tensor(0.0)
+        optim = torch.optim.SGD([t], lr=0.1)
+        to_save = {"optim": optim}
+    elif obj_to_save == "trainer":
+        to_save = {"trainer": trainer}
+
+    c = Checkpoint(to_save, save_handler=dirname)
+    c(trainer)
+
+    checkpoint_fp = dirname / c.last_checkpoint
+    Checkpoint.load_objects(to_load=to_save, checkpoint=str(checkpoint_fp))