Keras 训练中偶数 Epoch 日志全为零的排查与解决

DDD
发布: 2025-10-18 08:57:22
原创
828人浏览过

Keras 训练中偶数 Epoch 日志全为零的排查与解决

本文探讨 keras 训练过程中,偶数 epoch 出现所有日志(准确率、损失等)为零的常见问题。该现象通常源于 `tf.keras.preprocessing.image.imagedatagenerator` 配合 `model.fit` 方法时,`steps_per_epoch` 参数配置不当。教程将详细解释问题根源,并提供两种有效解决方案:精确计算 `steps_per_epoch` 或省略该参数让 keras 自动推断,以确保训练过程的稳定性和日志的正确性。

Keras 训练日志异常:偶数 Epoch 结果为零

在使用 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 的值设置不正确,例如:

  1. 小于实际所需批次数量: 如果 steps_per_epoch 小于 总样本数 / 批次大小,那么每个 epoch 都会提前结束,导致并非所有训练数据都被使用。这可能导致生成器在下一个 epoch 开始时处于一个不稳定的状态,或者 Keras 在某些 epoch 中无法从生成器中获取到有效的批次数据,从而记录为零。
  2. 与生成器内部状态不匹配: ImageDataGenerator 在内部维护其状态,包括当前读取到的文件索引。不正确的 steps_per_epoch 值可能导致生成器在某些 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:

方法一:精确计算 steps_per_epoch 和 validation_steps

这是最推荐和最稳健的方法。您需要明确计算出训练集和验证集所需的批次数量,并将其传递给 model.fit。

简篇AI排版
简篇AI排版

AI排版工具,上传图文素材,秒出专业效果!

简篇AI排版 554
查看详情 简篇AI排版

步骤:

  1. 获取 ImageDataGenerator 报告的训练和验证样本总数。
  2. 根据 batch_size 计算 steps_per_epoch 和 validation_steps。通常使用 math.ceil 来确保即使最后一个批次不完整也能被处理。

示例代码:

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)] # 示例回调
    )
登录后复制

方法二:省略 steps_per_epoch 和 validation_steps

对于 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 的步数。

注意事项与总结

  1. 理解 steps_per_epoch: 它是定义一个 epoch 的关键。当使用生成器时,steps_per_epoch 告诉 Keras 从生成器中取多少个批次的数据来完成一个 epoch 的训练。
  2. validation_steps 同理: 对于验证集,validation_steps 决定了在验证阶段从验证数据生成器中取多少个批次。同样需要精确计算或让 Keras 自动推断。
  3. ImageDataGenerator.samples: flow_from_directory 方法返回的生成器对象具有 samples 属性,可以用来获取目录中的总样本数,这对于计算 steps_per_epoch 和 validation_steps 至关重要。
  4. Batch Normalization: 虽然与日志为零问题不是直接相关,但在使用 BatchNormalization 层时,批次大小的选择也很重要。过小的批次可能导致统计信息不稳定,影响模型的泛化能力。
  5. 回调函数 确保您的自定义回调函数没有意外地干扰训练过程或日志记录。在大多数情况下,它们不会导致这种规律性的零日志问题。

通过正确配置 steps_per_epoch 和 validation_steps,无论是通过精确计算还是让 Keras 自动推断,都可以有效解决 Keras 训练中偶数 epoch 日志全为零的问题,确保训练过程的稳定性和日志的准确性。

以上就是Keras 训练中偶数 Epoch 日志全为零的排查与解决的详细内容,更多请关注php中文网其它相关文章!

最佳 Windows 性能的顶级免费优化软件
最佳 Windows 性能的顶级免费优化软件

每个人都需要一台速度更快、更稳定的 PC。随着时间的推移,垃圾文件、旧注册表数据和不必要的后台进程会占用资源并降低性能。幸运的是,许多工具可以让 Windows 保持平稳运行。

下载
来源:php中文网
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系admin@php.cn
最新问题
开源免费商场系统广告
热门教程
更多>
最新下载
更多>
网站特效
网站源码
网站素材
前端模板
关于我们 免责申明 意见反馈 讲师合作 广告合作 最新更新 English
php中文网:公益在线php培训,帮助PHP学习者快速成长!
关注服务号 技术交流群
PHP中文网订阅号
每天精选资源文章推送
PHP中文网APP
随时随地碎片化学习

Copyright 2014-2025 https://www.php.cn/ All Rights Reserved | php.cn | 湘ICP备2023035733号