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

为何TensorFlow搭建的二分类神经网络会将所有图片误判为同一类别?

问题根因与修复方案

你遇到的固定输出问题本质是过拟合+数据泄露共同导致的,模型没有学到“是否有物品”的核心特征,反而记住了训练集的噪声特征,泛化能力完全失效,具体修复步骤如下:


1. 修复数据拆分的逻辑漏洞

你当前数据加载代码存在严重的数据泄露问题:两次调用image_dataset_from_directory时,分别用了validation_split=0.2和validation_split=0.3,相同种子下生成的训练集和验证集存在大量重叠,模型训练时已经见过验证集数据,验证指标完全没有参考意义,也不可能学到可泛化的特征。
修复方案二选一:

  • 手动把100张原图按8:2比例拆成独立的train和val文件夹,每类样本占比保持一致,分别加载两个文件夹的数据集
  • 两次调用image_dataset_from_directory时使用相同的validation_split参数(比如都设为0.2),分别取subset='training'和subset='validation',保证两个数据集无重叠

2. 启用数据增强解决小样本+高相似度问题

你预先定义的数据增强代码被注释没有生效,100张小样本+空台面样本高度相似的情况下,模型必然会直接记住空台面的像素细节,而不是学习物品存在的特征。
把模型定义中注释掉的data_augmentation层放开,放在Rescaling层前面,训练时会自动对输入图像做随机翻转、旋转、缩放,强制模型学习核心特征。

3. 调整模型适配二分类任务

当前用2输出的多分类逻辑实现二分类不是最优选择,建议调整为更适配的结构:

def creat_model():
    model = Sequential([
        data_augmentation, # 取消注释启用增强
        layers.Rescaling(1. / 255, input_shape=(img_height, img_width, 3)),
        layers.Conv2D(16, 3, padding='same', activation='relu'),
        layers.MaxPooling2D(),
        layers.Conv2D(32, 3, padding='same', activation='relu'),
        layers.MaxPooling2D(),
        layers.Conv2D(64, 3, padding='same', activation='relu'),
        layers.Conv2D(64, 3, padding='same', activation='relu'),
        layers.MaxPooling2D(),
        layers.Flatten(),
        layers.Dropout(0.5), # 新增Dropout层减少过拟合
        layers.Dense(128, activation='relu'),
        layers.Dense(1, activation='sigmoid') # 改为单输出+sigmoid适配二分类
    ])

    model.compile(optimizer='adam',
                  loss=tf.keras.losses.BinaryCrossentropy(), # 更换二分类损失
                  metrics=['accuracy'])
    return model

4. 调整训练参数避免过拟合

  • 新增早停回调,避免训练过度:
early_stop = tf.keras.callbacks.EarlyStopping(patience=3, restore_best_weights=True)
william.fit(train_data, validation_data=val_data, epochs=20, callbacks=[tensorboard, early_stop])
  • 把batch_size调整到8~16,小样本场景下更小的batch更容易收敛。

5. 对应调整测试代码

如果改成单输出sigmoid结构,测试代码不需要再做softmax计算,调整如下:

predictions = william.predict(img_array)[0][0]
if predictions > 0.5:
    category = 'no empty'
    confidence = predictions * 100
else:
    category = 'empty'
    confidence = (1 - predictions) * 100
print(f"This image most likely belongs to {category} with a {confidence:.2f} percent confidence.")

内容的提问来源于stack exchange,提问作者Artem Meller

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.10.01 21:24:03