我正在使用 Keras(带有 TensorFlow 后端)使用 train_on_batch()、evaluate() 和回调函数 on_epoch_end() 来训练模型。这是以下链接中原始代码的一部分:https://www.kaggle.com/code/kmader/pretrained-inceptionv3-for-bone-age
我没有使用给定的 fit_generator() ,而是尝试实现它的原始版本,因为由于以下链接中描述的错误, fit_generator() 无法工作:https://github.com/keras-team/keras/问题/8595
下面给出的是回调函数列表的内核-
from keras.callbacks import ModelCheckpoint, LearningRateScheduler, EarlyStopping, ReduceLROnPlateau
weight_path="/kaggle/working/{}_weights.best.hdf5".format('bone_age')
checkpoint = ModelCheckpoint(weight_path, monitor='val_loss', verbose=1,
save_best_only=True, mode='min', save_weights_only = True)
reduceLROnPlat = ReduceLROnPlateau(monitor='val_loss', factor=0.8, patience=10, verbose=1, mode='auto', epsilon=0.0001, cooldown=5, min_lr=0.0001)
early = EarlyStopping(monitor="val_loss",
mode="min",
patience=5) # probably needs to be more patient, but kaggle time is limited
callbacks_list = [reduceLROnPlat, checkpoint, early]
以及主要训练内核-
epochs = 2
steps_per_epoch = 10
for epoch in range(epochs):
print("Epoch {}/{}".format(epoch + 1, epochs))
# Training phase
for step in range(steps_per_epoch):
# Get the next batch of training data and labels
batch_X, batch_Y = next(train_gen)
# Train on batch
loss = bone_age_model.train_on_batch(batch_X, batch_Y)
print("Step {" + str(step + 1) + "}/{" + str(steps_per_epoch) + "}
# Validation phase
val_loss, accuracy = bone_age_model.evaluate(test_X, test_Y)
print("Validation Loss: " + str(round(val_loss, 4)))
# Apply callbacks
for callback in callbacks_list:
callback.on_epoch_end(epoch, logs={'val_loss': val_loss})
(注意:我在 Kaggle 上运行代码,既不在 Google Colab 上运行,也不在我的本地 PC 上运行)
我注意到以下错误:
AttributeError Traceback (most recent call last)
<ipython-input-56-28ff6d63cd15> in <module>()
27 # Apply callbacks
28 for callback in callbacks_list:
---> 29 callback.on_epoch_end(epoch, logs={'val_loss': val_loss}) # Call the callback at the end of each epoch
30
31
/opt/conda/lib/python3.6/site-packages/Keras-2.1.3-py3.6.egg/keras/callbacks.py in on_epoch_end(self, epoch, logs)
914 def on_epoch_end(self, epoch, logs=None):
915 logs = logs or {}
--> 916 logs['lr'] = K.get_value(self.model.optimizer.lr)
917 current = logs.get(self.monitor)
918 if current is None:
AttributeError: 'NoneType' object has no attribute 'optimizer'
我尝试逐一使用回调函数,即callbacks_list中只有一个回调函数,但所有回调函数都会导致错误。
---------------------------------------------------------------------------
AttributeError Traceback (most recent call last)
<ipython-input-19-28ff6d63cd15> in <module>()
27 # Apply callbacks
28 for callback in callbacks_list:
---> 29 callback.on_epoch_end(epoch, logs={'val_loss': val_loss}) # Call the callback at the end of each epoch
30
31
/opt/conda/lib/python3.6/site-packages/Keras-2.1.3-py3.6.egg/keras/callbacks.py in on_epoch_end(self, epoch, logs)
498 )
499 return
--> 500 if self.monitor_op(current - self.min_delta, self.best):
501 self.best = current
502 self.wait = 0
AttributeError: 'EarlyStopping' object has no attribute 'best'
AttributeError Traceback (most recent call last)
<ipython-input-38-28ff6d63cd15> in <module>()
27 # Apply callbacks
28 for callback in callbacks_list:
---> 29 callback.on_epoch_end(epoch, logs={'val_loss': val_loss}) # Call the callback at the end of each epoch
30
31
/opt/conda/lib/python3.6/site-packages/Keras-2.1.3-py3.6.egg/keras/callbacks.py in on_epoch_end(self, epoch, logs)
414 self.best = current
415 if self.save_weights_only:
--> 416 self.model.save_weights(filepath, overwrite=True)
417 else:
418 self.model.save(filepath, overwrite=True)
AttributeError: 'NoneType' object has no attribute 'save_weights'
我对此有点陌生,并且在理论上研究过一些。有人可以解释一下我是否使用了错误的函数或者 keras 模块中是否有错误(因为我看到很多帖子声称旧版本的模块中有错误)?由于所有模块都抛出某种错误,我相信我的实现存在问题。
PS:我不知道这是否相关,但我正在使用 InceptionV3 和 Resnet 的预训练模型。
确实,如果不访问模型权重,回调就无法保存模型权重:)
当您使用 keras fit 函数时,它会创建一个回调列表并将模型传递给它,其代码如下:
if not isinstance(callbacks, callbacks_module.CallbackList):
callbacks = callbacks_module.CallbackList(
callbacks,
add_history=True,
add_progbar=verbose != 0,
verbose=verbose,
epochs=epochs,
steps=epoch_iterator.num_batches,
model=self,
)
它本身为传递给它的每个回调设置模型,其代码如下:
def set_model(self, model):
super().set_model(model)
if self._history:
model.history = self._history
for callback in self.callbacks:
callback.set_model(model)
因此,为了手动使用回调,您需要在调用它们之前设置模型。在训练循环之前的示例中,您可以添加以下代码行来解决问题:
for callback in callback_list:
callback.set_model(bone_age_model)
然后您的检查点可以访问模型,例如您的模型检查点可以访问权重以保存它们。
备注: 您可以使用 CallbackList 类来统一回调,而无需每次都进行循环,请参阅 keras 文档 例如使用。