После нескольких часов чтения исходного кода keras я сдался и сделал ошибку в keras Github. https://github.com/keras-team/keras/issues/12840
Просто тренируйся снова, на этот раз умнее. Проблема в том, что обратный вызов Checkpoint работает только с эпохами. И моя эпоха заняла 25 часов:)
Решение состоит в том, чтобы сделать обработчик сигнала:
Вот мой код для пользовательского обратного вызова, который останавливает обучение и сохраняет мою модель, нажав CTRL + Z:
class SignalStopping(keras.callbacks.Callback):
'''Stop training when an interrupt signal (or other) was received
# Arguments
sig: the signal to listen to. Defaults to signal.SIGTSTP.
doubleSignalExits: Receiving the signal twice exits the python
process instead of waiting for this epoch to finish.
patience: number of epochs with no improvement
after which training will be stopped.
verbose: verbosity mode.
'''
# SBW 2018.10.15 Since ctrl-c trapping isn't working, watch for existence of file, e.g. .\path\_StopTraining.txt.
def __init__(self, sig=signal.SIGTSTP, doubleSignalExits=False, verbose=1):
super(SignalStopping, self).__init__()
self.signal_received = False
self.verbose = verbose
self.doubleSignalExits = doubleSignalExits
def signal_handler(sig, frame):
self.model.stop_training = True
#if self.signal_received and self.doubleSignalExits:
# if self.verbose > 0:
# print('') #new line to not print on current status bar. Better solution?
# print('Received signal to stop ' + str(sig)+' twice. Exiting..')
# exit(sig)
#self.signal_received = True
#if self.verbose > 0:
# print('') #new line to not print on current status bar. Better solution?
# print('Received signal to stop: ' + str(sig))
signal.signal(signal.SIGTSTP, signal_handler)
self.stopped_epoch = 0
def on_epoch_end(self, epoch, logs={}):
if self.signal_received:
self.stopped_epoch = epoch
self.model.stop_training = True
print("stop_training=true")
def on_train_end(self, logs={}):
print("on_train_end")
if self.stopped_epoch > 0 and self.verbose > 0:
print('Epoch %05d: stopping due to signal' %
(self.stopped_epoch))
И я называю это с:
stop_cb = SignalStopping()
Затем поместите его в список обратных вызовов, который передается в fit_generator.