Adds the option of saving the last model on checkpoint (#1908)

* saves model every epoch

* implement test for save_last

* Update CHANGELOG.md

* Update CHANGELOG.md

* changes test description

Co-authored-by: Jeremy Jordan <13970565+jeremyjordan@users.noreply.github.com>

Co-authored-by: Jeremy Jordan <13970565+jeremyjordan@users.noreply.github.com>
This commit is contained in:
Lucas Vazquez
2020-05-25 07:47:44 -04:00
committed by GitHub
co-authored by Jeremy Jordan
parent a34eb9e169
commit 112dd5c4f6
3 changed files with 20 additions and 9 deletions
+2
View File
@@ -14,6 +14,8 @@ The format is based on [Keep a Changelog](http://keepachangelog.com/en/1.0.0/).
- Allow dataloaders without sampler field present ([#1907](https://github.com/PyTorchLightning/pytorch-lightning/pull/1907))
- Added option `save_last` to save the model at the end of every epoch in `ModelCheckpoint` [(#1908)](https://github.com/PyTorchLightning/pytorch-lightning/pull/1908)
### Changed
- Allow user to select individual TPU core to train on ([#1729](https://github.com/PyTorchLightning/pytorch-lightning/pull/1729))
@@ -43,6 +43,7 @@ class ModelCheckpoint(Callback):
monitor: quantity to monitor.
verbose: verbosity mode. Default: ``False``.
save_last: always saves the model at the end of the epoch. Default: ``False``.
save_top_k: if `save_top_k == k`,
the best k models according to
the quantity monitored will be saved.
@@ -83,7 +84,7 @@ class ModelCheckpoint(Callback):
"""
def __init__(self, filepath: Optional[str] = None, monitor: str = 'val_loss', verbose: bool = False,
save_top_k: int = 1, save_weights_only: bool = False,
save_last: bool = False, save_top_k: int = 1, save_weights_only: bool = False,
mode: str = 'auto', period: int = 1, prefix: str = ''):
super().__init__()
if save_top_k > 0 and filepath is not None and os.path.isdir(filepath) and len(os.listdir(filepath)) > 0:
@@ -103,6 +104,7 @@ class ModelCheckpoint(Callback):
else:
self.dirpath, self.filename = os.path.split(filepath)
os.makedirs(self.dirpath, exist_ok=True)
self.save_last = save_last
self.save_top_k = save_top_k
self.save_weights_only = save_weights_only
self.period = period
@@ -217,6 +219,10 @@ class ModelCheckpoint(Callback):
self.epoch_last_check = epoch
if self.save_last:
filepath = os.path.join(self.dirpath, self.prefix + 'last.ckpt')
self._save_model(filepath)
filepath = self.format_checkpoint_name(epoch, metrics)
version_cnt = 0
while os.path.isfile(filepath):
+11 -8
View File
@@ -229,19 +229,21 @@ def test_dp_output_reduce():
assert reduced['b']['c'] == out['b']['c']
@pytest.mark.parametrize(["save_top_k", "file_prefix", "expected_files"], [
pytest.param(-1, '', {'epoch=4.ckpt', 'epoch=3.ckpt', 'epoch=2.ckpt', 'epoch=1.ckpt', 'epoch=0.ckpt'},
@pytest.mark.parametrize(["save_top_k", "save_last", "file_prefix", "expected_files"], [
pytest.param(-1, False, '', {'epoch=4.ckpt', 'epoch=3.ckpt', 'epoch=2.ckpt', 'epoch=1.ckpt', 'epoch=0.ckpt'},
id="CASE K=-1 (all)"),
pytest.param(1, 'test_prefix_', {'test_prefix_epoch=4.ckpt'},
pytest.param(1, False, 'test_prefix_', {'test_prefix_epoch=4.ckpt'},
id="CASE K=1 (2.5, epoch 4)"),
pytest.param(2, '', {'epoch=4.ckpt', 'epoch=2.ckpt'},
pytest.param(2, False, '', {'epoch=4.ckpt', 'epoch=2.ckpt'},
id="CASE K=2 (2.5 epoch 4, 2.8 epoch 2)"),
pytest.param(4, '', {'epoch=1.ckpt', 'epoch=4.ckpt', 'epoch=3.ckpt', 'epoch=2.ckpt'},
pytest.param(4, False, '', {'epoch=1.ckpt', 'epoch=4.ckpt', 'epoch=3.ckpt', 'epoch=2.ckpt'},
id="CASE K=4 (save all 4 base)"),
pytest.param(3, '', {'epoch=2.ckpt', 'epoch=3.ckpt', 'epoch=4.ckpt'},
pytest.param(3, False, '', {'epoch=2.ckpt', 'epoch=3.ckpt', 'epoch=4.ckpt'},
id="CASE K=3 (save the 2nd, 3rd, 4th model)"),
pytest.param(1, True, '', {'epoch=4.ckpt', 'last.ckpt'},
id="CASE K=1 (save the 4th model and the last model)"),
])
def test_model_checkpoint_options(tmpdir, save_top_k, file_prefix, expected_files):
def test_model_checkpoint_options(tmpdir, save_top_k, save_last, file_prefix, expected_files):
"""Test ModelCheckpoint options."""
def mock_save_function(filepath, *args):
@@ -250,7 +252,8 @@ def test_model_checkpoint_options(tmpdir, save_top_k, file_prefix, expected_file
# simulated losses
losses = [10, 9, 2.8, 5, 2.5]
checkpoint_callback = ModelCheckpoint(tmpdir, save_top_k=save_top_k, prefix=file_prefix, verbose=1)
checkpoint_callback = ModelCheckpoint(tmpdir, save_top_k=save_top_k, save_last=save_last,
prefix=file_prefix, verbose=1)
checkpoint_callback.save_function = mock_save_function
trainer = Trainer()