
本文探讨 keras 训练过程中,偶数 epoch 出现所有日志(准确率、损失等)为零的常见问题。该现象通常源于 `tf.keras.preprocessing.image.imagedatagenerator` 配合 `model.fit` 方法时,`steps_per_epoch` 参数配置不当。教程将详细解释问题根源,并提供两种有效解决方案:精确计算 `steps_per_epoch` 或省略该参数让 keras 自动推断,以确保训练过程的稳定性和日志的正确性。
在使用 Keras 进行深度学习模型训练时,尤其是在处理图像数据并结合 tf.keras.preprocessing.image.ImageDataGenerator 进行数据增强和批量加载时,可能会遇到一个不寻常的现象:训练日志(包括准确率、损失、验证准确率和验证损失)在偶数个 epoch 中全部显示为零,而奇数个 epoch 则正常进行。这种规律性的异常表明训练流程中存在某种周期性错误,而非随机的训练不稳定。
以下是一个典型的日志输出示例,展示了这种偶数 epoch 为零的问题:
Epoch 1/20 90/90 ━━━━━━━━━━━━━━━━━━━━ 170s 2s/step - accuracy: 0.9974 - loss: 0.4769 - val_accuracy: 0.7968 - val_loss: 0.9699 Epoch 2/20 90/90 ━━━━━━━━━━━━━━━━━━━━ 0s 1ms/step - accuracy: 0.0000e+00 - loss: 0.0000e+00 - val_accuracy: 0.0000e+00 - val_loss: 0.0000e+00 Epoch 3/20 90/90 ━━━━━━━━━━━━━━━━━━━━ 175s 2s/step - accuracy: 0.9988 - loss: 0.4260 - val_accuracy: 0.8052 - val_loss: 0.9283 Epoch 4/20 90/90 ━━━━━━━━━━━━━━━━━━━━ 0s 728us/step - accuracy: 0.0000e+00 - loss: 0.0000e+00 - val_accuracy: 0.0000e+00 - val_loss: 0.0000e+00
此问题的核心通常在于 model.fit 方法中 steps_per_epoch 参数的设置不当,尤其是在与 ImageDataGenerator 结合使用时。ImageDataGenerator 的 flow_from_directory 方法会创建一个无限循环的生成器,它会不断地从数据集中生成批次数据。steps_per_epoch 参数的作用就是告诉 Keras 在一个 epoch 中从这个生成器中取多少个批次数据。
如果 steps_per_epoch 的值设置不正确,例如:
在提供的案例中,训练数据有 25000 张图片,batch_size 设置为 250。因此,每个 epoch 实际需要 25000 / 250 = 100 个批次。然而,steps_per_epoch 被设置为 90。这意味着每个 epoch 只处理了 90 * 250 = 22500 张图片,剩余的 2500 张图片未被处理。这种不完整的迭代可能导致生成器在下一个 epoch 的开始时出现状态异常,进而引发偶数 epoch 的日志为零。
解决此问题主要有两种方法,都围绕着正确配置 steps_per_epoch 和 validation_steps:
这是最推荐和最稳健的方法。您需要明确计算出训练集和验证集所需的批次数量,并将其传递给 model.fit。
步骤:
示例代码:
import math
import tensorflow as tf
from tensorflow.keras.preprocessing.image import ImageDataGenerator
from tensorflow.keras import layers, models, regularizers
from tensorflow.keras.optimizers import Adam
# 假设您的模型结构和编译部分与原代码相同
model1 = models.Sequential([
layers.Conv2D(16,(3,3), activation='relu', input_shape=(150, 150, 3)),
layers.MaxPooling2D(2,2),
layers.BatchNormalization(),
layers.Conv2D(32,(3,3), activation='relu'),
layers.MaxPooling2D(2,2),
layers.BatchNormalization(),
layers.Conv2D(64,(3,3), activation='relu'),
layers.MaxPooling2D(2,2),
layers.BatchNormalization(),
layers.Flatten(),
layers.Dense(512, activation='relu', kernel_regularizer=regularizers.l2(0.001)),
layers.Dropout(0.2),
layers.Dense(1, activation='sigmoid')
])
model1.compile(optimizer=Adam(learning_rate=0.0002), loss='binary_crossentropy', metrics=['accuracy'])
# 数据生成器设置
train_CD = ImageDataGenerator(rescale=1.0/255.)
train_generator_CD = train_CD.flow_from_directory(
'./images/cat_dog/train_data/',
target_size = (150, 150),
batch_size = 250,
class_mode = 'binary')
test_CD = ImageDataGenerator(rescale=1.0/255.)
test_generator_CD = test_CD.flow_from_directory(
'./images/cat_dog/test_data/',
target_size = (150, 150),
batch_size = 250,
class_mode = 'binary')
# 获取样本总数
total_train_samples = train_generator_CD.samples
total_validation_samples = test_generator_CD.samples
batch_size = train_generator_CD.batch_size # 或者直接使用 250
# 计算 steps_per_epoch 和 validation_steps
steps_per_epoch = math.ceil(total_train_samples / batch_size)
validation_steps = math.ceil(total_validation_samples / batch_size)
print(f"Total training samples: {total_train_samples}, Batch size: {batch_size}, Steps per epoch: {steps_per_epoch}")
print(f"Total validation samples: {total_validation_samples}, Batch size: {batch_size}, Validation steps: {validation_steps}")
# 训练模型(修正后的 fit 调用)
history1=model1.fit(
train_generator_CD,
validation_data = test_generator_CD,
epochs = 20,
steps_per_epoch = steps_per_epoch, # 使用计算出的值
validation_steps = validation_steps, # 使用计算出的值
callbacks=[tf.keras.callbacks.EarlyStopping(monitor='val_loss', patience=3)] # 示例回调
)对于 ImageDataGenerator 返回的生成器,如果它正确实现了 __len__ 方法(flow_from_directory 通常会实现),Keras 能够自动推断出每个 epoch 所需的步数。在这种情况下,您可以完全省略 steps_per_epoch 和 validation_steps 参数。
示例代码:
import tensorflow as tf
from tensorflow.keras.preprocessing.image import ImageDataGenerator
from tensorflow.keras import layers, models, regularizers
from tensorflow.keras.optimizers import Adam
# 模型和数据生成器设置同上...
# 训练模型(省略 steps_per_epoch 和 validation_steps)
history1=model1.fit(
train_generator_CD,
validation_data = test_generator_CD,
epochs = 20,
# steps_per_epoch 和 validation_steps 被省略,Keras 将自动推断
callbacks=[tf.keras.callbacks.EarlyStopping(monitor='val_loss', patience=3)] # 示例回调
)这种方法通常更简洁,并且可以避免手动计算可能导致的错误。Keras 会通过调用生成器的 __len__ 方法来确定每个 epoch 的步数。
通过正确配置 steps_per_epoch 和 validation_steps,无论是通过精确计算还是让 Keras 自动推断,都可以有效解决 Keras 训练中偶数 epoch 日志全为零的问题,确保训练过程的稳定性和日志的准确性。
以上就是Keras 训练中偶数 Epoch 日志全为零的排查与解决的详细内容,更多请关注php中文网其它相关文章!
每个人都需要一台速度更快、更稳定的 PC。随着时间的推移,垃圾文件、旧注册表数据和不必要的后台进程会占用资源并降低性能。幸运的是,许多工具可以让 Windows 保持平稳运行。
Copyright 2014-2025 https://www.php.cn/ All Rights Reserved | php.cn | 湘ICP备2023035733号