-
Notifications
You must be signed in to change notification settings - Fork 3
Adds functionality to save best model in CheckpointingCallback and fixes a typo #3
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: master
Are you sure you want to change the base?
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -158,7 +158,7 @@ def __init__(self, keys=None, val_keys=None, smoothing=0.999): | |
| self.keys = keys | ||
|
|
||
| if val_keys is None: | ||
| self.val_keys = [] | ||
| self.val_keys = [] | ||
| else: | ||
| self.val_keys = val_keys | ||
|
|
||
|
|
@@ -184,7 +184,7 @@ class VisdomLoggingCallback(KeyedCallback): | |
| 0.0 disables smoothing. | ||
| """ | ||
|
|
||
| def __init__(self, keys=None, val_keys=None, frequency=100, server=None, | ||
| def __init__(self, keys=None, val_keys=None, frequency=100, server=None, | ||
| port=8097, base_url="/", env="main", log=False, smoothing=0.99): | ||
| super(VisdomLoggingCallback, self).__init__( | ||
| keys=keys, val_keys=val_keys, smoothing=smoothing) | ||
|
|
@@ -460,14 +460,23 @@ class CheckpointingCallback(Callback): | |
|
|
||
| PERIODIC_PREFIX = "periodic_" | ||
| EPOCH_PREFIX = "epoch_" | ||
| BEST_MODEL_FILENAME = "best" | ||
|
|
||
| def __init__(self, checkpointer, interval=600, | ||
| max_files=5, max_epochs=10): | ||
| max_files=5, max_epochs=10, | ||
| best_val_key=None, best_val_value=None): | ||
|
Owner
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. do we need to initialize best_val_value externally? could that be handled by the load/save mechanism so we only have one parameter? |
||
| super(CheckpointingCallback, self).__init__() | ||
| self.checkpointer = checkpointer | ||
| self.interval = interval | ||
| self.max_files = max_files | ||
| self.max_epochs = max_epochs | ||
| self.best_val_key = best_val_key | ||
|
|
||
| if best_val_value is not None: | ||
| LOG.info("Loaded best model ({}={})".format(best_val_key, best_val_value)) | ||
|
Owner
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. "loaded" be misleading, since the load does not happen at init time |
||
| self.best_val_value = best_val_key | ||
| else: | ||
| self.best_val_value = float('inf') | ||
|
|
||
| self.last_checkpoint_time = time.time() | ||
|
|
||
|
|
@@ -506,6 +515,22 @@ def batch_end(self, batch_data, train_step_data): | |
| self.checkpointer.save(filename, extras={"epoch": self.epoch}) | ||
|
Owner
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. here and elsewhere were |
||
| self.__purge_old_files() | ||
|
|
||
| def validation_end(self, val_data): | ||
| """Save a best model checkpoint if value for best_val_key is lowest so far.""" | ||
|
|
||
| super(CheckpointingCallback, self).validation_end(val_data) | ||
|
|
||
| if self.best_val_key is None: | ||
| return | ||
| if val_data[self.best_val_key] > self.best_val_value: | ||
|
Owner
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. we should probably document that the "best" is implicitly a min value (e.g. if someone uses accuracy instead of loss) |
||
| return | ||
|
|
||
| self.best_val_value = val_data[self.best_val_key] | ||
|
|
||
| LOG.debug("Best model checkpoint ({}={})".format(self.best_val_key, self.best_val_value)) | ||
| self.checkpointer.save(CheckpointingCallback.BEST_MODEL_FILENAME, | ||
| extras={"epoch": self.epoch, "best_val_value": self.best_val_value}) | ||
|
|
||
| def __purge_old_files(self): | ||
| """Delete checkpoints that are beyond the max to keep.""" | ||
|
|
||
|
|
@@ -635,7 +660,7 @@ def training_end(self): | |
| print("end logging experiment", self.epoch, self.batch) | ||
|
|
||
| def _get_commit(self): | ||
| return subprocess.check_output(["git", "rev-parse", "HEAD"]) | ||
| return subprocess.check_output(["git", "rev-parse", "HEAD"]) | ||
|
|
||
|
|
||
| class CSVLoggingCallback(KeyedCallback): | ||
|
|
||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
maybe add a couple doc entries