You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

神经网络训练异常:Loss恒为0.0、Accuracy恒为1.0问题排查

训练神经网络时异常指标的问题排查

问题现象

尝试用10个epoch训练神经网络,初始训练时出现异常输出:

35/300 [==>...........................] - ETA: 1:09 - loss: 0.0000e+00 - accuracy: 1.0000
 36/300 [==>...........................] - ETA: 1:09 - loss: 0.0000e+00 - accuracy: 1.0000
 37/300 [==>...........................] - ETA: 1:08 - loss: 0.0000e+00 - accuracy: 1.0000 

调整后训练指标出现无规律波动,甚至出现准确率极低的情况:

5/300 [..............................] - ETA: 1:12 - loss: 0.1564 - accuracy: 0.9750
  6/300 [..............................] - ETA: 1:15 - loss: 0.1311 - accuracy: 0.8333
  7/300 [..............................] - ETA: 1:13 - loss: 0.1124 - accuracy: 0.7143
  8/300 [..............................] - ETA: 1:13 - loss: 0.0984 - accuracy: 0.6250
  9/300 [..............................] - ETA: 1:12 - loss: 0.0874 - accuracy: 0.5556

后续出现:

51/300 [====>.........................] - ETA: 1:04 - loss: 0.0154 - accuracy: 0.0980

完整训练代码

batch_size = 32
img_height = 150
img_width = 150

dataset_url = "http://cnrpark.it/dataset/CNR-EXT-Patches-150x150.zip"
print(dataset_url)
data_dir = tf.keras.utils.get_file(origin=dataset_url,
                                   fname='CNR-EXT-Patches-150x150',
                                   untar=True)

train_ds = tf.keras.utils.image_dataset_from_directory(
  data_dir,
  validation_split=0.2,
  subset="training",
  seed=123,
  image_size=(img_height, img_width),
  batch_size=batch_size)
num_classes = 1

val_ds = tf.keras.utils.image_dataset_from_directory(
  data_dir,
  validation_split=0.2,
  subset="validation",
  seed=123,
  image_size=(img_height, img_width),
  batch_size=batch_size)

class_names = train_ds.class_names
print(class_names)

for image_batch, labels_batch in train_ds:
  print(image_batch.shape)
  print(labels_batch.shape)
  break

normalization_layer = tf.keras.layers.Rescaling(1./255)

normalized_ds = train_ds.map(lambda x, y: (normalization_layer(x), y))
image_batch, labels_batch = next(iter(normalized_ds))
first_image = image_batch[0]
print(np.min(first_image), np.max(first_image))

model = tf.keras.Sequential([
  tf.keras.layers.Rescaling(1./255),
  tf.keras.layers.Conv2D(32, 3, activation='relu'),
  tf.keras.layers.MaxPooling2D(),
  tf.keras.layers.Conv2D(32, 3, activation='relu'),
  tf.keras.layers.MaxPooling2D(),
  tf.keras.layers.Conv2D(32, 3, activation='relu'),
  tf.keras.layers.MaxPooling2D(),
  tf.keras.layers.Flatten(),
  tf.keras.layers.Dense(1, activation='sigmoid'),
  tf.keras.layers.Dense(num_classes)
])

AUTOTUNE = tf.data.AUTOTUNE

train_ds = train_ds.cache().prefetch(buffer_size=AUTOTUNE)
val_ds = val_ds.cache().prefetch(buffer_size=AUTOTUNE)

model.compile(
  optimizer='adam',
  loss=tf.keras.losses.BinaryCrossentropy(),
  metrics=['accuracy'])

model.fit(
  train_ds,
  validation_data=val_ds,
  epochs=10
)

问题根源分析

1. 输出层结构错误

模型最后连续叠加了两个全连接层:

tf.keras.layers.Dense(1, activation='sigmoid'),
tf.keras.layers.Dense(num_classes)
  • 第一个Dense(1, activation='sigmoid')已经输出了二分类所需的0-1概率值,完全匹配BinaryCrossentropy损失函数的要求。
  • 第二个Dense(num_classes)(num_classes=1)是多余的,且没有设置激活函数,会将sigmoid输出的0-1值映射为任意实数,导致损失计算逻辑完全混乱,直接引发loss为0、准确率异常波动等问题。

2. 类别数设置矛盾

CNR-EXT-Patches数据集是二分类任务(停车场空位/非空位),image_dataset_from_directory会根据数据集文件夹数量自动识别类别(class_names应该是两个类别),但你手动将num_classes设为1,虽然二分类用单节点输出是合理的,但结合多余的输出层,进一步加剧了训练逻辑的错误。

修复方案

  1. 移除多余的输出层:删除模型中的tf.keras.layers.Dense(num_classes),保留tf.keras.layers.Dense(1, activation='sigmoid')作为唯一输出层。
  2. 可选优化:使用logits输出:如果想避免sigmoid激活可能带来的饱和问题,可以将输出层改为tf.keras.layers.Dense(1),并在编译时设置:
    model.compile(
      optimizer='adam',
      loss=tf.keras.losses.BinaryCrossentropy(from_logits=True),
      metrics=['accuracy'])
    
  3. 确认类别数:无需手动设置num_classes=1,可以通过num_classes = len(class_names)自动获取真实类别数,二分类场景下不影响单节点输出的逻辑。

内容的提问来源于stack exchange,提问作者Jan Tuđan

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.20 20:12:49