ResNet50迁移学习做车型细粒度分类训练正常但新图预测仅输出单类
问题原因及解决方案
1. 预处理逻辑冲突(核心错误)
你训练阶段的图像输入是通过ImageDataGenerator的rescale=1./255将像素值归一化到0-1区间,但预测阶段的处理逻辑存在冲突:
- 先执行
x = x/255.得到0-1区间的数值 - 又调用了
preprocess_input,而TensorFlow内置的ResNet50预处理函数默认针对0-255的原始RGB图像做通道均值减去操作,输出数值范围在[-127.5, 127.5]区间,和训练时的输入分布完全错位,模型拿到分布异常的输入自然会输出错误结果。
修复方案:训练和推理的预处理逻辑必须完全对齐,二选一即可:
- 方案1:推理阶段删除
preprocess_input调用,仅保留x = x/255.的归一化操作 - 方案2:训练阶段删除
ImageDataGenerator中的rescale=1./255参数,训练和推理都统一用preprocess_input做预处理
2. 迁移学习微调策略不合理
你直接冻结了ResNet50的全部层,仅训练最后一层全连接层,对于车型细粒度分类这种类间差异极小的任务,仅靠顶层线性层很难学到有效的区分特征,泛化能力极差,容易出现拟合数据噪声、所有样本都输出占比最高类别的情况。
修复方案:
- 先冻结整个ResNet50 backbone,训练10-20个epoch让顶层分类头收敛
- 解冻ResNet50最后2-3个残差块,使用更小的学习率(如1e-5)继续微调,让 backbone 适配当前的车型分类任务
3. 过拟合风险
你训练了200个epoch,且没有加入任何正则化策略,极容易出现过拟合:表现为训练集、验证集准确率都很高,但新样本推理效果极差,甚至全部预测为同一类别。
修复方案:
- 在Flatten层和最终的Dense分类层之间加入Dropout层(如
Dropout(0.5)) - 加入早停回调(
EarlyStopping),监控验证集损失,连续5-10个epoch没有下降就停止训练 - 适当减少训练epoch数
4. 其他可排查点
- 检查训练集各类别样本量是否平衡,如果某一类样本占比远超其他类别,模型会倾向于全部预测为该类来获得更高的训练准确率,可通过加入类别权重、少样本类过采样解决
- 检查
training_set.class_indices的类别索引映射是否和你推理时的预期一致,避免索引对应错误导致误判预测结果异常
内容的提问来源于stack exchange,提问作者Muntha
相关产品推荐
相关产品推荐

