vfdev-5: @amatsukawa thanks for this PR too !

I would change "Fixes #966" with related to #966 I think it wont completely fix it, right ?

I agree with updating `Checkpoint` and `EarlyStopping` to be derived from `Serializable`. However, automatic inclusion of `self` with `include_itself` should be carefully tested and I think it can be too short to have this in v0.4.0...
What do you think ?


amatsukawa: I changed the description. This does support the most of the functionality I had in mind, except for the "do it automatically" part (which as we discussed elsewhere, may not be realistic after all).

I did add a test to make sure `include_self` at least seemed to work as intended. I followed a fairly simple rule that seems to me like would have a high likelihood of correctness, which is to add `self.state_dict` *right before* the call to the save handler (which is the last thing in the method). 

I'm happy to remove `include_self` from the PR for now. Its effect would be that `Checkpoint` object cannot respect the `n_saved` parameter *across resumes*.
vfdev-5: @amatsukawa I need to play a bit with the code. Maybe, a complete integration test would be nice to ensure that saving and resume (`Checkpoint.load_objects`) work as intended...
Let's take a bit of time to check all this (during 24h) and than we take a decision either keep or remove as we plan to cut the release on June 25th. Does it sound good for you ?
amatsukawa: Is there an existing integration test for things that this touches, without checkpointing? If so, I can try to just add to it or create a copy of it for checkpointing.
vfdev-5: Maybe this one is the most integrating among the others : https://github.com/pytorch/ignite/blob/master/tests/ignite/handlers/test_checkpoint.py#L713

amatsukawa: @vfdev-5 I made a version of that test you linked with new features, PTAL.
amatsukawa: Oops, @vfdev-5 I'm sorry I didn't realized you had pushed some changes to this branch. I thought I had done something wrong in merging master to cause the conflict, so I force pushed.

Could you push your changes again?
vfdev-5: Yep, sorry, I have this practice (push into existing PRs), it can be surprising :)
I'll try to merge your newer commits and mine...
vfdev-5: I think if we are done with it, we can merge it like that. No need to update the docs as API is not that brilliant.
Ideally, it would be great to have a possibilty to add somehow those stateful components like `early_stop` and `best_checkpoint` to the trainer such that when we save the trainer, we save also appended components...
Something like that 
```python
trainer = Engine(lambda e, b: None)

to_save = {"trainer": trainer}
checkpoint = ModelCheckpoint(...)

evaluator = Engine(lambda e, b: None)
early_stopping = EarlyStopping(...)
evaluator.add_event_handler(Events.COMPLETED, early_stopping)

trainer.state.early_stopping = early_stopping
trainer.state_dict_user_keys.append("early_stopping")  # this wont work but an API like that maybe more interesting vs manual addition.
```
amatsukawa: Thanks for the review!

I would vote for merging this in to support this functionality manually for 0.4, and improving usability from there. 

As future work, perhaps hook states can appear in engine states, and both engines can be checkpointed. Alternatively, #912 happens, it may be fine to hide it inside a Trainer how it is now.
diff --git a/ignite/handlers/checkpoint.py b/ignite/handlers/checkpoint.py
index dcb2a50f..86975414 100644
--- a/ignite/handlers/checkpoint.py
+++ b/ignite/handlers/checkpoint.py
@@ -4,13 +4,14 @@ import os
 import tempfile
 import warnings
 from abc import ABCMeta, abstractmethod
-from collections import namedtuple
+from collections import OrderedDict, namedtuple
 from typing import Callable, Mapping, Optional, Union
 
 import torch
 import torch.nn as nn
 
 import ignite.distributed as idist
+from ignite.base import Serializable
 from ignite.engine import Engine, Events
 
 __all__ = ["Checkpoint", "DiskSaver", "ModelCheckpoint", "BaseSaveHandler"]
@@ -62,7 +63,7 @@ class BaseSaveHandler(metaclass=ABCMeta):
         pass
 
 
-class Checkpoint:
+class Checkpoint(Serializable):
     """Checkpoint handler can be used to periodically save and load objects which have attribute
     ``state_dict`/`load_state_dict``. This class can use specific save handlers to store on the disk or a cloud
     storage, etc. The Checkpoint handler (if used with :class:`~ignite.handlers.DiskSaver`) also handles automatically
@@ -92,6 +93,8 @@ class Checkpoint:
             Default is None, global_step based on attached engine. If provided, uses function output as global_step.
             To setup global step from another engine, please use :meth:`~ignite.handlers.global_step_from_engine`.
         archived (bool, optional): Deprecated argument as models saved by ``torch.save`` are already compressed.
+        include_self (bool): Whether to include the `state_dict` of this object in the checkpoint. If `True`, then
+            there must not be another object in ``to_save`` with key ``checkpointer``.
 
     .. _DistributedDataParallel: https://pytorch.org/docs/stable/nn.html#torch.nn.parallel.DistributedDataParallel
     .. _DataParallel: https://pytorch.org/docs/stable/nn.html#torch.nn.DataParallel
@@ -204,6 +207,7 @@ class Checkpoint:
     """
 
     Item = namedtuple("Item", ["priority", "filename"])
+    _state_dict_all_req_keys = ("saved",)
 
     def __init__(
         self,
@@ -215,6 +219,7 @@ class Checkpoint:
         n_saved: Optional[int] = 1,
         global_step_transform: Callable = None,
         archived: bool = False,
+        include_self: bool = False,
     ):
 
         if to_save is not None:  # for compatibility with ModelCheckpoint
@@ -226,6 +231,15 @@ class Checkpoint:
 
             self._check_objects(to_save, "state_dict")
 
+            if include_self:
+                if not isinstance(to_save, collections.MutableMapping):
+                    raise TypeError(
+                        "If `include_self` is True, then `to_save` must be mutable, but given {}.".format(type(to_save))
+                    )
+
+                if "checkpointer" in to_save:
+                    raise ValueError("Cannot have key 'checkpointer' if `include_self` is True: {}".format(to_save))
+
         if not (callable(save_handler) or isinstance(save_handler, BaseSaveHandler)):
             raise TypeError("Argument `save_handler` should be callable or inherit from BaseSaveHandler")
 
@@ -248,6 +262,7 @@ class Checkpoint:
         self._saved = []
         self._ext = ".pt"
         self.global_step_transform = global_step_transform
+        self.include_self = include_self
 
     @property
     def last_checkpoint(self) -> Optional[str]:
@@ -321,6 +336,10 @@ class Checkpoint:
             self._saved.append(Checkpoint.Item(priority, filename))
             self._saved.sort(key=lambda item: item[0])
 
+            if self.include_self:
+                # Now that we've updated _saved, we can add our own state_dict.
+                checkpoint["checkpointer"] = self.state_dict()
+
             try:
                 self.save_handler(checkpoint, filename, metadata)
             except TypeError:
@@ -408,6 +427,13 @@ class Checkpoint:
             else:
                 obj.load_state_dict(checkpoint[k])
 
+    def state_dict(self) -> OrderedDict:
+        return OrderedDict([("saved", [(p, f) for p, f in self._saved])])
+
+    def load_state_dict(self, state_dict: Mapping) -> None:
+        super().load_state_dict(state_dict)
+        self._saved = [Checkpoint.Item(p, f) for p, f in state_dict["saved"]]
+
 
 class DiskSaver(BaseSaveHandler):
     """Handler that saves input checkpoint on a disk.
@@ -545,6 +571,8 @@ class ModelCheckpoint(Checkpoint):
             Default is None, global_step based on attached engine. If provided, uses function output as global_step.
             To setup global step from another engine, please use :meth:`~ignite.handlers.global_step_from_engine`.
         archived (bool, optional): Deprecated argument as models saved by `torch.save` are already compressed.
+        include_self (bool): Whether to include the `state_dict` of this object in the checkpoint. If `True`, then
+            there must not be another object in ``to_save`` with key ``checkpointer``.
 
     Examples:
         >>> import os
@@ -576,6 +604,7 @@ class ModelCheckpoint(Checkpoint):
         save_as_state_dict: bool = True,
         global_step_transform: Optional[Callable] = None,
         archived: bool = False,
+        include_self: bool = False,
     ):
 
         if not save_as_state_dict:
@@ -606,6 +635,7 @@ class ModelCheckpoint(Checkpoint):
             n_saved=n_saved,
             global_step_transform=global_step_transform,
             archived=archived,
+            include_self=include_self,
         )
 
     @property
diff --git a/ignite/handlers/early_stopping.py b/ignite/handlers/early_stopping.py
index 8c7efa20..b1000b83 100644
--- a/ignite/handlers/early_stopping.py
+++ b/ignite/handlers/early_stopping.py
@@ -1,12 +1,14 @@
 import logging
-from typing import Callable
+from collections import OrderedDict
+from typing import Callable, Mapping
 
+from ignite.base import Serializable
 from ignite.engine import Engine
 
 __all__ = ["EarlyStopping"]
 
 
-class EarlyStopping:
+class EarlyStopping(Serializable):
     """EarlyStopping handler can be used to stop the training if no improvement after a given number of events.
 
     Args:
@@ -41,6 +43,11 @@ class EarlyStopping:
 
     """
 
+    _state_dict_all_req_keys = (
+        "counter",
+        "best_score",
+    )
+
     def __init__(
         self,
         patience: int,
@@ -87,3 +94,11 @@ class EarlyStopping:
         else:
             self.best_score = score
             self.counter = 0
+
+    def state_dict(self) -> OrderedDict:
+        return OrderedDict([("counter", self.counter), ("best_score", self.best_score)])
+
+    def load_state_dict(self, state_dict: Mapping) -> None:
+        super().load_state_dict(state_dict)
+        self.counter = state_dict["counter"]
+        self.best_score = state_dict["best_score"]

Checkpoint stateful handlers and metrics
## 🚀 Feature

<!-- A clear and concise description of the feature proposal -->
Things that are attached to the `Engine` might have state that would ideally be checkpointed and restored using as part of the `Engine`'s `state_dict`.

<!-- Please outline the motivation for the proposal. Is your feature request related to a problem? e.g., I'm always frustrated when [...]. If this is related to another GitHub issue, please link here too -->

An example is a `Checkpoint` handler when it has a `score_function`. Currently, the priorities the `Checkpoint` class stores is not saved anywhere. It is not able to recover gracefully from failure without manual intervention to parse the checkpoint path names, and directly setting the internals of the class.

<!-- A clear and concise description of what you want to happen. -->

Handlers and Metrics should have `state_dict` and `load_state_dict` methods (empty by default), and I think it should be possible for these to automatically make it into/restored from the `Engine`'s `state_dict` when it's attached to an `Engine`.

diff --git a/tests/ignite/handlers/test_checkpoint.py b/tests/ignite/handlers/test_checkpoint.py
index f69c82f5..9d6a779b 100644
--- a/tests/ignite/handlers/test_checkpoint.py
+++ b/tests/ignite/handlers/test_checkpoint.py
@@ -1,5 +1,6 @@
 import os
 import warnings
+from collections import OrderedDict
 from unittest.mock import MagicMock
 
 import pytest
@@ -8,7 +9,7 @@ import torch.nn as nn
 
 import ignite.distributed as idist
 from ignite.engine import Engine, Events, State
-from ignite.handlers import Checkpoint, DiskSaver, ModelCheckpoint
+from ignite.handlers import Checkpoint, DiskSaver, EarlyStopping, ModelCheckpoint, global_step_from_engine
 from ignite.handlers.checkpoint import BaseSaveHandler
 
 _PREFIX = "PREFIX"
@@ -63,6 +64,9 @@ def test_checkpoint_wrong_input():
     with pytest.warns(UserWarning, match=r"Argument archived is deprecated"):
         Checkpoint(to_save, lambda x: x, score_function=lambda e: 123, score_name="acc", archived=True)
 
+    with pytest.raises(ValueError, match=r"Cannot have key 'checkpointer' if `include_self` is True"):
+        Checkpoint({"checkpointer": model}, lambda x: x, include_self=True)
+
 
 def test_checkpoint_score_function_wrong_output():
     model = DummyModel()
@@ -111,6 +115,56 @@ def test_checkpoint_default():
     _test(to_save, {"model": model.state_dict(), "optimizer": optimizer.state_dict()}, "checkpoint")
 
 
+def test_checkpoint_include_self_state_dict():
+    def _test(to_save, obj, name):
+        save_handler = MagicMock(spec=BaseSaveHandler)
+
+        checkpointer = Checkpoint(to_save, save_handler=save_handler, include_self=True)
+        assert checkpointer.last_checkpoint is None
+
+        trainer = Engine(lambda e, b: None)
+        trainer.state = State(epoch=0, iteration=0)
+
+        checkpointer(trainer)
+        assert save_handler.call_count == 1
+
+        fname = "{}_0.pt".format(name)
+        obj["checkpointer"] = OrderedDict([("saved", [(0, fname)])])
+
+        metadata = {"basename": name, "score_name": None, "priority": 0}
+        save_handler.assert_called_with(obj, fname, metadata)
+
+        # Swap object, state should be maintained
+        checkpointer2 = Checkpoint(to_save, save_handler=save_handler, include_self=True)
+        checkpointer2.load_state_dict(checkpointer.state_dict())
+        assert checkpointer2.last_checkpoint == fname
+
+        trainer.state.epoch = 12
+        trainer.state.iteration = 1234
+        checkpointer2(trainer)
+        assert save_handler.call_count == 2
+        metadata["priority"] = 1234
+
+        # This delete only happens if state was restored correctly.
+        save_handler.remove.assert_called_with("{}_0.pt".format(name))
+
+        fname = "{}_1234.pt".format(name)
+        obj["checkpointer"] = OrderedDict([("saved", [(1234, fname)])])
+
+        save_handler.assert_called_with(obj, fname, metadata)
+        assert save_handler.remove.call_count == 1
+        assert checkpointer2.last_checkpoint == fname
+
+    model = DummyModel()
+    to_save = {"model": model}
+    _test(to_save, model.state_dict(), "model")
+
+    model = DummyModel()
+    optimizer = torch.optim.SGD(model.parameters(), lr=0.1)
+    to_save = {"model": model, "optimizer": optimizer}
+    _test(to_save, {"model": model.state_dict(), "optimizer": optimizer.state_dict()}, "checkpoint")
+
+
 def test_checkpoint_with_dp():
 
     model = DummyModel()
@@ -792,6 +846,138 @@ def test_save_model_optimizer_lr_scheduler_with_state_dict(dirname):
     _test_save_model_optimizer_lr_scheduler_with_state_dict("cpu", dirname)
 
 
+def _test_save_model_optimizer_lr_scheduler_with_validation(device, dirname, on_zero_rank=False):
+    torch.manual_seed(23)
+
+    def _build_objects(acc_list):
+
+        model = DummyModel().to(device)
+        optim = torch.optim.SGD(model.parameters(), lr=0.1)
+        lr_scheduler = torch.optim.lr_scheduler.ExponentialLR(optim, gamma=0.5)
+
+        def update_fn(engine, batch):
+            x = torch.rand((4, 1)).to(device)
+            optim.zero_grad()
+            y = model(x)
+            loss = y.pow(2.0).sum()
+            loss.backward()
+            if idist.has_xla_support:
+                import torch_xla.core.xla_model as xm
+
+                xm.optimizer_step(optim, barrier=True)
+            else:
+                optim.step()
+            lr_scheduler.step()
+
+        trainer = Engine(update_fn)
+
+        evaluator = Engine(lambda e, b: None)
+        acc_iter = iter(acc_list)
+
+        @evaluator.on(Events.EPOCH_COMPLETED)
+        def setup_result():
+            evaluator.state.metrics["accuracy"] = next(acc_iter)
+
+        @trainer.on(Events.EPOCH_COMPLETED)
+        def run_eval():
+            evaluator.run([0, 1, 2])
+
+        def score_function(engine):
+            return engine.state.metrics["accuracy"]
+
+        save_handler = DiskSaver(dirname, create_dir=True, require_empty=False)
+        early_stop = EarlyStopping(score_function=score_function, patience=2, trainer=trainer)
+        evaluator.add_event_handler(Events.COMPLETED, early_stop)
+
+        checkpointer = Checkpoint(
+            {
+                "trainer": trainer,
+                "model": model,
+                "optim": optim,
+                "lr_scheduler": lr_scheduler,
+                "early_stop": early_stop,
+            },
+            save_handler,
+            include_self=True,
+            global_step_transform=global_step_from_engine(trainer),
+        )
+        evaluator.add_event_handler(Events.COMPLETED, checkpointer)
+
+        return trainer, evaluator, model, optim, lr_scheduler, early_stop, checkpointer
+
+    trainer, evaluator, model, optim, scheduler, early, checkpointer = _build_objects([0.2, 0.3, 0.2])
+    trainer.run([0], max_epochs=3)
+
+    saved_objects = sorted(os.listdir(dirname))
+    saved_checkpoint = os.path.join(dirname, saved_objects[0])
+
+    loaded_obj = torch.load(saved_checkpoint, map_location=device)
+    for f in ["trainer", "model", "optim", "lr_scheduler", "early_stop", "checkpointer"]:
+        assert f in loaded_obj
+
+    trainer2, evaluator2, model2, optim2, scheduler2, early2, checkpointer2 = _build_objects([0.1, 0.1, 0.1])
+    Checkpoint.load_objects(
+        {
+            "trainer": trainer2,
+            "model": model2,
+            "optim": optim2,
+            "lr_scheduler": scheduler2,
+            "early_stop": early2,
+            "checkpointer": checkpointer2,
+        },
+        loaded_obj,
+    )
+    assert checkpointer2.last_checkpoint == checkpointer.last_checkpoint
+
+    model_state_dict = model.cpu().state_dict()
+    loaded_model_state_dict = model2.cpu().state_dict()
+    for key in model_state_dict.keys():
+        assert key in loaded_model_state_dict
+        model_value = model_state_dict[key]
+        loaded_model_value = loaded_model_state_dict[key]
+        assert model_value.cpu().numpy() == loaded_model_value.cpu().numpy()
+
+    optim_state_dict = optim.state_dict()
+    loaded_optimizer_state_dict = optim2.state_dict()
+    # "params" contains tensor IDs, which are different
+    del optim_state_dict["param_groups"][0]["params"]
+    del loaded_optimizer_state_dict["param_groups"][0]["params"]
+    for key in optim_state_dict.keys():
+        assert key in loaded_optimizer_state_dict
+        optim_value = optim_state_dict[key]
+        loaded_optim_value = loaded_optimizer_state_dict[key]
+        if idist.get_rank() == 0:
+            assert optim_value == loaded_optim_value
+
+    def _check_state_dict(original, loaded):
+        original_state_dict = original.state_dict()
+        loaded_state_dict = loaded.state_dict()
+        for key in original_state_dict.keys():
+            assert key in loaded_state_dict
+            original_value = original_state_dict[key]
+            loaded_value = loaded_state_dict[key]
+            assert original_value == loaded_value
+
+    _check_state_dict(trainer, trainer2)
+    _check_state_dict(scheduler, scheduler2)
+    _check_state_dict(early, early2)
+    _check_state_dict(checkpointer, checkpointer2)
+
+    trainer2.run([0], max_epochs=6)
+
+    # early stopping should have triggered
+    assert trainer2.state.epoch == 4
+
+    # If Checkpoint's state was restored correctly, it should continue to respect n_saved
+    # and delete old checkpoints, and have the correct last_checkpoint.
+    assert os.listdir(dirname) == ["checkpoint_4.pt"]
+    assert checkpointer2.last_checkpoint == "checkpoint_4.pt"
+
+
+def test_save_model_optimizer_lr_scheduler_with_validation(dirname):
+    _test_save_model_optimizer_lr_scheduler_with_validation("cpu", dirname)
+
+
 def test_checkpoint_load_objects():
 
     with pytest.raises(TypeError, match=r"Argument checkpoint should be a dictionary"):
@@ -1023,3 +1209,47 @@ def _test_tpu_saves_to_cpu_nprocs(index, dirname):
 def test_distrib_single_device_xla_nprocs(xmp_executor, dirname):
     n = int(os.environ["NUM_TPU_WORKERS"])
     xmp_executor(_test_tpu_saves_to_cpu_nprocs, args=(dirname,), nprocs=n)
+
+
+def _setup_checkpoint():
+    save_handler = MagicMock(spec=BaseSaveHandler)
+    model = DummyModel()
+    to_save = {"model": model}
+
+    checkpointer = Checkpoint(to_save, save_handler=save_handler, n_saved=None)
+    assert checkpointer.last_checkpoint is None
+
+    trainer = Engine(lambda e, b: None)
+    trainer.state = State(epoch=0, iteration=0)
+
+    checkpointer(trainer)
+    trainer.state.iteration = 10
+    checkpointer(trainer)
+    trainer.state.iteration = 20
+    checkpointer(trainer)
+    assert save_handler.call_count == 3
+    return checkpointer
+
+
+def test_checkpoint_state_dict():
+    checkpointer = _setup_checkpoint()
+    sd = checkpointer.state_dict()
+    assert "saved" in sd
+    assert isinstance(sd["saved"], list) and len(sd["saved"]) == len(checkpointer._saved)
+
+    for saved_item, true_item in zip(sd["saved"], checkpointer._saved):
+        assert saved_item[0] == true_item.priority
+        assert saved_item[1] == true_item.filename
+
+
+def test_checkpoint_load_state_dict():
+    true_checkpointer = _setup_checkpoint()
+
+    save_handler = MagicMock(spec=BaseSaveHandler)
+    model = DummyModel()
+    to_save = {"model": model}
+    checkpointer = Checkpoint(to_save, save_handler=save_handler, n_saved=None)
+
+    sd = {"saved": [(0, "model_0.pt"), (10, "model_10.pt"), (20, "model_20.pt")]}
+    checkpointer.load_state_dict(sd)
+    assert checkpointer._saved == true_checkpointer._saved
diff --git a/tests/ignite/handlers/test_early_stopping.py b/tests/ignite/handlers/test_early_stopping.py
index 3005fe31..793c922a 100644
--- a/tests/ignite/handlers/test_early_stopping.py
+++ b/tests/ignite/handlers/test_early_stopping.py
@@ -49,6 +49,31 @@ def test_simple_early_stopping():
     assert trainer.should_terminate
 
 
+def test_state_dict():
+
+    scores = iter([1.0, 0.8, 0.88])
+
+    def score_function(engine):
+        return next(scores)
+
+    trainer = Engine(do_nothing_update_fn)
+
+    h = EarlyStopping(patience=2, score_function=score_function, trainer=trainer)
+    # Call 3 times and check if stopped
+    assert not trainer.should_terminate
+    h(None)
+    assert not trainer.should_terminate
+
+    # Swap to new object, but maintain state
+    h2 = EarlyStopping(patience=2, score_function=score_function, trainer=trainer)
+    h2.load_state_dict(h.state_dict())
+
+    h2(None)
+    assert not trainer.should_terminate
+    h2(None)
+    assert trainer.should_terminate
+
+
 def test_early_stopping_on_delta():
 
     scores = iter([1.0, 2.0, 2.01, 3.0, 3.01, 3.02])

pip install -e .
parse_log_pytest
requirements.txt
pytest
apt-get update apt-get install -y gcc pip install torch torchvision -f https://download.pytorch.org/whl/cpu/torch_stable.html -U
3.7
requirements-dev.txt
pytest --no-header -rA --tb=line --color=no -p no:cacheprovider -W ignore::DeprecationWarning
absl-py==2.1.0
alembic==1.12.1
arrow==1.2.3
attrs==24.2.0
boto3==1.33.13
botocore==1.33.13
bravado==11.1.0
bravado-core==6.1.1
cached-property==1.5.2
cachetools==5.5.2
certifi @ file:///croot/certifi_1671487769961/work/certifi
charset-normalizer==3.4.1
click==7.1.2
cloudpickle==2.2.1
codecov==2.1.13
coverage==7.2.7
cycler==0.11.0
databricks-cli==0.18.0
dill==0.3.7
docker==6.1.3
docker-pycreds==0.4.0
entrypoints==0.4
exceptiongroup==1.2.2
execnet==2.0.2
Flask==1.1.4
fonttools==4.38.0
fqdn==1.5.1
funcsigs==1.0.2
furl==2.1.4
future==1.0.0
gitdb==4.0.12
GitPython==3.1.44
google-auth==2.38.0
google-auth-oauthlib==0.4.6
greenlet==3.1.1
grpcio==1.62.3
gunicorn==20.1.0
gym==0.26.2
gym-notices==0.0.8
hestia==0.6.0
humanfriendly==10.0
idna==3.10
importlib-metadata==5.2.0
importlib-resources==5.12.0
iniconfig==2.0.0
isoduration==20.11.0
itsdangerous==1.1.0
Jinja2==2.10.3
jmespath==1.0.1
joblib==1.3.2
jsonpatch==1.33
jsonpointer==3.0.0
jsonref==1.1.0
jsonschema==4.17.3
kiwisolver==1.4.5
Mako==1.2.4
Markdown==3.4.4
MarkupSafe==2.1.5
marshmallow==3.0.0rc5
matplotlib==3.5.3
mlflow==1.30.1
monotonic==1.6
msgpack==1.0.5
neptune-client==1.11.1
networkx==2.6.3
numpy==1.21.6
oauthlib==3.2.2
orderedmultidict==1.0.1
packaging==21.3
pandas==1.3.5
pathlib2==2.3.7.post1
Pillow==9.5.0
pkgutil_resolve_name==1.3.10
platformdirs==4.0.0
pluggy==1.2.0
polyaxon-client==0.6.1
polyaxon-schemas==0.6.1
polystores==0.2.5
prometheus-client==0.17.1
prometheus_flask_exporter==0.23.2
protobuf==3.20.3
psutil==7.0.0
pyasn1==0.5.1
pyasn1-modules==0.3.0
PyJWT==2.8.0
pynvml==11.5.3
pyparsing==3.1.4
pyrsistent==0.19.3
pytest==7.4.4
pytest-cov==4.1.0
pytest-xdist==3.5.0
python-dateutil==2.9.0.post0
-e git+https://github.com/pytorch/ignite.git@2d0f30adac705bb5c82c4f600b2ffbce1cdf8c68#egg=pytorch_ignite
pytz==2022.7.1
PyYAML==6.0.1
querystring-parser==1.2.4
requests==2.31.0
requests-file==2.1.0
requests-oauthlib==2.0.0
requests-toolbelt==1.0.0
rfc3339-validator==0.1.4
rfc3986-validator==0.1.1
rhea==0.5.5
rsa==4.9
s3transfer==0.8.2
scikit-learn==1.0.2
scipy==1.7.3
sentry-sdk==2.24.1
setproctitle==1.3.3
simplejson==3.20.1
six==1.17.0
smmap==5.0.2
SQLAlchemy==1.4.54
sqlparse==0.4.4
swagger-spec-validator==3.0.3
tabulate==0.9.0
tensorboard==2.11.2
tensorboard-data-server==0.6.1
tensorboard-plugin-wit==1.8.1
tensorboardX==2.6.2.2
threadpoolctl==3.1.0
tomli==2.0.1
torch==1.13.1+cpu
torchvision==0.14.1+cpu
tornado==6.2
tqdm==4.67.1
trains==0.16.4
typing_extensions==4.7.1
uri-template==1.3.0
urllib3==1.26.20
visdom==0.2.4
wandb==0.18.7
webcolors==1.13
websocket-client==1.6.1
Werkzeug==1.0.1
zipp==3.15.0

name: ignite
channels:
  - defaults
  - https://repo.anaconda.com/pkgs/main
  - https://repo.anaconda.com/pkgs/r
  - conda-forge
dependencies:
  - _libgcc_mutex=0.1=main
  - _openmp_mutex=5.1=1_gnu
  - ca-certificates=2025.2.25=h06a4308_0
  - certifi=2022.12.7=py37h06a4308_0
  - ld_impl_linux-64=2.40=h12ee557_0
  - libffi=3.4.4=h6a678d5_1
  - libgcc-ng=11.2.0=h1234567_1
  - libgomp=11.2.0=h1234567_1
  - libstdcxx-ng=11.2.0=h1234567_1
  - ncurses=6.4=h6a678d5_0
  - openssl=1.1.1w=h7f8727e_0
  - pip=22.3.1=py37h06a4308_0
  - python=3.7.16=h7a1cb2a_0
  - readline=8.2=h5eee18b_0
  - setuptools=65.6.3=py37h06a4308_0
  - sqlite=3.45.3=h5eee18b_0
  - tk=8.6.14=h39e8969_0
  - wheel=0.38.4=py37h06a4308_0
  - xz=5.6.4=h5eee18b_1
  - zlib=1.2.13=h5eee18b_1
  - pip:
      - absl-py==2.1.0
      - alembic==1.12.1
      - arrow==1.2.3
      - attrs==24.2.0
      - boto3==1.33.13
      - botocore==1.33.13
      - bravado==11.1.0
      - bravado-core==6.1.1
      - cached-property==1.5.2
      - cachetools==5.5.2
      - charset-normalizer==3.4.1
      - click==7.1.2
      - cloudpickle==2.2.1
      - codecov==2.1.13
      - coverage==7.2.7
      - cycler==0.11.0
      - databricks-cli==0.18.0
      - dill==0.3.7
      - docker==6.1.3
      - docker-pycreds==0.4.0
      - entrypoints==0.4
      - exceptiongroup==1.2.2
      - execnet==2.0.2
      - flask==1.1.4
      - fonttools==4.38.0
      - fqdn==1.5.1
      - funcsigs==1.0.2
      - furl==2.1.4
      - future==1.0.0
      - gitdb==4.0.12
      - gitpython==3.1.44
      - google-auth==2.38.0
      - google-auth-oauthlib==0.4.6
      - greenlet==3.1.1
      - grpcio==1.62.3
      - gunicorn==20.1.0
      - gym==0.26.2
      - gym-notices==0.0.8
      - hestia==0.6.0
      - humanfriendly==10.0
      - idna==3.10
      - importlib-metadata==5.2.0
      - importlib-resources==5.12.0
      - iniconfig==2.0.0
      - isoduration==20.11.0
      - itsdangerous==1.1.0
      - jinja2==2.10.3
      - jmespath==1.0.1
      - joblib==1.3.2
      - jsonpatch==1.33
      - jsonpointer==3.0.0
      - jsonref==1.1.0
      - jsonschema==4.17.3
      - kiwisolver==1.4.5
      - mako==1.2.4
      - markdown==3.4.4
      - markupsafe==2.1.5
      - marshmallow==3.0.0rc5
      - matplotlib==3.5.3
      - mlflow==1.30.1
      - monotonic==1.6
      - msgpack==1.0.5
      - neptune-client==1.11.1
      - networkx==2.6.3
      - numpy==1.21.6
      - oauthlib==3.2.2
      - orderedmultidict==1.0.1
      - packaging==21.3
      - pandas==1.3.5
      - pathlib2==2.3.7.post1
      - pillow==9.5.0
      - pkgutil-resolve-name==1.3.10
      - platformdirs==4.0.0
      - pluggy==1.2.0
      - polyaxon-client==0.6.1
      - polyaxon-schemas==0.6.1
      - polystores==0.2.5
      - prometheus-client==0.17.1
      - prometheus-flask-exporter==0.23.2
      - protobuf==3.20.3
      - psutil==7.0.0
      - pyasn1==0.5.1
      - pyasn1-modules==0.3.0
      - pyjwt==2.8.0
      - pynvml==11.5.3
      - pyparsing==3.1.4
      - pyrsistent==0.19.3
      - pytest==7.4.4
      - pytest-cov==4.1.0
      - pytest-xdist==3.5.0
      - python-dateutil==2.9.0.post0
      - pytorch-ignite==0.4.0
      - pytz==2022.7.1
      - pyyaml==6.0.1
      - querystring-parser==1.2.4
      - requests==2.31.0
      - requests-file==2.1.0
      - requests-oauthlib==2.0.0
      - requests-toolbelt==1.0.0
      - rfc3339-validator==0.1.4
      - rfc3986-validator==0.1.1
      - rhea==0.5.5
      - rsa==4.9
      - s3transfer==0.8.2
      - scikit-learn==1.0.2
      - scipy==1.7.3
      - sentry-sdk==2.24.1
      - setproctitle==1.3.3
      - simplejson==3.20.1
      - six==1.17.0
      - smmap==5.0.2
      - sqlalchemy==1.4.54
      - sqlparse==0.4.4
      - swagger-spec-validator==3.0.3
      - tabulate==0.9.0
      - tensorboard==2.11.2
      - tensorboard-data-server==0.6.1
      - tensorboard-plugin-wit==1.8.1
      - tensorboardx==2.6.2.2
      - threadpoolctl==3.1.0
      - tomli==2.0.1
      - torch==1.13.1+cpu
      - torchvision==0.14.1+cpu
      - tornado==6.2
      - tqdm==4.67.1
      - trains==0.16.4
      - typing-extensions==4.7.1
      - uri-template==1.3.0
      - urllib3==1.26.20
      - visdom==0.2.4
      - wandb==0.18.7
      - webcolors==1.13
      - websocket-client==1.6.1
      - werkzeug==1.0.1
      - zipp==3.15.0
prefix: /opt/conda/envs/ignite

tests/ignite/handlers/test_checkpoint.py::test_checkpoint_wrong_input tests/ignite/handlers/test_checkpoint.py::test_checkpoint_include_self_state_dict tests/ignite/handlers/test_checkpoint.py::test_save_model_optimizer_lr_scheduler_with_validation tests/ignite/handlers/test_checkpoint.py::test_checkpoint_state_dict tests/ignite/handlers/test_checkpoint.py::test_checkpoint_load_state_dict tests/ignite/handlers/test_early_stopping.py::test_state_dict
tests/ignite/handlers/test_checkpoint.py::test_checkpoint_score_function_wrong_output tests/ignite/handlers/test_checkpoint.py::test_checkpoint_default tests/ignite/handlers/test_checkpoint.py::test_checkpoint_with_dp tests/ignite/handlers/test_checkpoint.py::test_checkpoint_with_global_step_transform tests/ignite/handlers/test_checkpoint.py::test_checkpoint_with_score_function tests/ignite/handlers/test_checkpoint.py::test_checkpoint_with_score_name_and_function tests/ignite/handlers/test_checkpoint.py::test_checkpoint_with_int_score tests/ignite/handlers/test_checkpoint.py::test_checkpoint_with_score_function_and_trainer_epoch tests/ignite/handlers/test_checkpoint.py::test_checkpoint_with_score_name_and_function_and_trainer_epoch tests/ignite/handlers/test_checkpoint.py::test_checkpoint_last_checkpoint tests/ignite/handlers/test_checkpoint.py::test_checkpoint_last_checkpoint_on_score tests/ignite/handlers/test_checkpoint.py::test_checkpoint_save_handler_callable tests/ignite/handlers/test_checkpoint.py::test_model_checkpoint_args_validation tests/ignite/handlers/test_checkpoint.py::test_model_checkpoint_simple_recovery tests/ignite/handlers/test_checkpoint.py::test_model_checkpoint_simple_recovery_from_existing_non_empty tests/ignite/handlers/test_checkpoint.py::test_disk_saver_atomic tests/ignite/handlers/test_checkpoint.py::test_last_k tests/ignite/handlers/test_checkpoint.py::test_disabled_n_saved tests/ignite/handlers/test_checkpoint.py::test_best_k tests/ignite/handlers/test_checkpoint.py::test_best_k_with_suffix tests/ignite/handlers/test_checkpoint.py::test_removes_each_score_at_most_once tests/ignite/handlers/test_checkpoint.py::test_with_engine tests/ignite/handlers/test_checkpoint.py::test_with_state_dict tests/ignite/handlers/test_checkpoint.py::test_valid_state_dict_save tests/ignite/handlers/test_checkpoint.py::test_save_model_optimizer_lr_scheduler_with_state_dict tests/ignite/handlers/test_checkpoint.py::test_checkpoint_load_objects tests/ignite/handlers/test_checkpoint.py::test_checkpoint_load_objects_from_saved_file tests/ignite/handlers/test_checkpoint.py::test_load_checkpoint_with_different_num_classes tests/ignite/handlers/test_checkpoint.py::test_disksaver_wrong_input tests/ignite/handlers/test_checkpoint.py::test_distrib_cpu tests/ignite/handlers/test_early_stopping.py::test_args_validation tests/ignite/handlers/test_early_stopping.py::test_simple_early_stopping tests/ignite/handlers/test_early_stopping.py::test_early_stopping_on_delta tests/ignite/handlers/test_early_stopping.py::test_early_stopping_on_last_event_delta tests/ignite/handlers/test_early_stopping.py::test_early_stopping_on_cumulative_delta tests/ignite/handlers/test_early_stopping.py::test_simple_early_stopping_on_plateau tests/ignite/handlers/test_early_stopping.py::test_simple_no_early_stopping tests/ignite/handlers/test_early_stopping.py::test_with_engine_early_stopping tests/ignite/handlers/test_early_stopping.py::test_with_engine_early_stopping_on_plateau tests/ignite/handlers/test_early_stopping.py::test_with_engine_no_early_stopping tests/ignite/handlers/test_early_stopping.py::test_distrib_cpu
ignite/handlers/early_stopping.py ignite/handlers/checkpoint.py
ignite/handlers/early_stopping.py ignite/handlers/checkpoint.py