模型经超参数调优后仍始终以高置信度将所有图像判定为猫
看起来你的模型遇到了典型的“所有样本预测同一类别”问题,我来帮你一步步排查可能的原因,以及对应的解决办法:
1. 首先排查数据集路径的致命错误
你在开头提到,PetImages下的子文件夹是Cats和Dogs,但训练代码里的filter_corrupted_images函数,遍历的文件夹名称是("Cat", "Dog")——这两个路径根本不存在!
这会导致两个严重问题:
- 损坏图片过滤函数完全没起作用,数据集中的坏图会干扰模型学习;
- 更关键的是,你得确认
image_dataset_from_directory加载数据时的输出:如果控制台打印的是“Found X files belonging to 1 class”,说明函数只识别到了一个类别的数据(比如只有Cats被加载),模型自然只会一直预测这个类别。
修复方法:把filter_corrupted_images里的folder_name改成("Cats", "Dogs"),和你的实际目录结构完全匹配。
2. 验证集被错误应用了数据增强
你的configure_for_performance函数里包含了随机翻转、旋转、缩放等数据增强操作,这些是只应该给训练集用的——验证集的作用是评估模型的真实泛化能力,不能加随机变换,否则验证结果完全失真,早停机制也会失效,导致模型根本学不到有效的区分特征。
修复方法:修改主函数里的数据集处理逻辑,只对训练集做增强,验证集只做预取优化:
if __name__ == "__main__": filter_corrupted_images() model = load_model_if_exists("model_best.keras") train_ds, val_ds = generate_datasets(image_size=(180, 180), batch_size=BATCH_SIZE) # 仅训练集应用数据增强 train_ds = configure_for_performance(train_ds) # 验证集只做prefetch,不做增强 val_ds = val_ds.prefetch(buffer_size=tf.data.AUTOTUNE) train_model(model, train_ds, val_ds, epochs=EPOCHS) model.save("model_best.keras")
3. 检查模型是否真的在“学习”
训练时一定要盯着控制台的loss和accuracy变化:
- 如果训练集accuracy一直徘徊在50%左右:说明模型完全没学到特征,要么是数据集加载错误(比如只有一个类别),要么是学习率过高/过低,或者网络结构太复杂/简单;
- 如果训练集accuracy很快到100%,但验证集accuracy一直很低:这是过拟合,需要减少网络层数、增加Dropout比例,或者降低数据增强的强度;
- 如果两者都卡在50%左右:大概率是数据集加载出了问题,比如只有一个类别的数据被训练。
你可以在generate_datasets函数后加一段代码,统计训练集的类别分布,确认两个类别的样本数量是否平衡:
train_ds, val_ds = generate_datasets(...) # 打印类别名称和样本数 class_names = train_ds.class_names print(f"识别到的类别:{class_names}") import numpy as np train_counts = np.zeros(len(class_names)) for _, y in train_ds: train_counts += np.bincount(y, minlength=len(class_names)) print(f"训练集类别样本数:{dict(zip(class_names, train_counts))}")
如果某个类别的样本数为0,那问题根源就在这里了。
4. 标签映射与预测逻辑是否匹配
image_dataset_from_directory会按文件夹名称的字母顺序分配标签:Cats会被映射为0,Dogs映射为1。你的模型用sigmoid输出,结果代表样本属于类别1(Dogs)的概率,所以你测试代码里1 - predictions[0][0]是Cat的置信度、predictions[0][0]是Dog的置信度,这部分逻辑是对的——但如果模型根本没学到区分特征,就会一直输出偏向某一类的结果。
最后,尝试简化模型重新训练
如果前面的问题都修复了,还是出现同样的情况,可以先简化模型结构(比如减少卷积层数量,把FILTER_SIZES改成[32, 64, 128]),降低训练轮数,用小一点的学习率(比如1e-4)重新训练,先让模型学到基本的区分能力,再逐步调优。
备注:内容来源于stack exchange,提问作者Akagami Shanks

