迁移学习图像分类:训练准确率高但验证损失大、预测准确率低原因
问题诊断与解决方案
从你的代码和训练日志来看,核心问题是严重过拟合,同时存在数据预处理的错误,导致验证和测试表现极差。以下是针对性的修复方案:
1. 修复验证集的数据预处理错误
你给验证集也应用了数据增强(旋转、平移等),这是完全错误的。验证/测试集应该保持数据的原始分布,只做归一化处理,不能加任何增强操作。
修改代码如下:
# 训练集用带增强的生成器 train_data_generator = keras.preprocessing.image.ImageDataGenerator( rescale=1./255, rotation_range=30, width_shift_range=0.2, height_shift_range=0.2, shear_range=0.2, zoom_range=0.2, horizontal_flip=True, ) # 验证集只用归一化,不做增强 val_data_generator = keras.preprocessing.image.ImageDataGenerator( rescale=1./255 ) # 加载训练数据 train_data_flow = train_data_generator.flow_from_directory( dataset_path, target_size=(224, 224), batch_size=32, class_mode='categorical', subset='training' ) # 加载验证数据,注意这里用单独的生成器,并且指定subset val_data_flow = val_data_generator.flow_from_directory( dataset_path, target_size=(224, 224), batch_size=32, class_mode='categorical', subset='validation' )
2. 调整模型,避免过拟合并提升特征适配性
- 你当前冻结了ResNet50的所有层,预训练特征可能和你的任务匹配度不足,建议微调顶层几层,让模型学习到任务相关的特征。
- 调整Dropout和BatchNorm的位置:BatchNorm应该放在Dense层之后、激活函数之前;同时减少Dropout的比例,避免过度抑制模型学习。
修改模型加载代码:
# 加载ResNet50特征层,设置trainable=True以支持微调 model_url = "https://tfhub.dev/tensorflow/resnet_50/feature_vector/1" hub_layer = hub.KerasLayer(model_url, input_shape=(224, 224, 3), trainable=True) # 调整模型结构:优化BatchNorm位置,降低Dropout比例 model = keras.Sequential([ hub_layer, layers.BatchNormalization(), # 先对预训练特征做归一化 layers.Dropout(0.3), layers.Dense(256), layers.BatchNormalization(), layers.Activation('relu'), # BatchNorm后加激活 layers.Dropout(0.3), layers.Dense(9, activation='softmax') ])
3. 优化训练策略,抑制过拟合
- 添加早停机制,当验证损失连续多轮不下降时停止训练,防止模型在训练集上过度拟合。
- 调整学习率:微调预训练模型时,学习率不能太高,建议用较小的学习率(比如1e-4),避免破坏预训练的特征。
修改编译和训练代码:
# 编译模型,指定较小的学习率 model.compile( optimizer=keras.optimizers.Adam(learning_rate=1e-4), loss='categorical_crossentropy', metrics=['accuracy'] ) # 添加早停回调 early_stopping = keras.callbacks.EarlyStopping( monitor='val_loss', patience=3, # 连续3轮验证损失不下降就停止 restore_best_weights=True # 恢复到验证损失最低的权重 ) # 训练模型 history = model.fit( train_data_flow, validation_data=val_data_flow, epochs=15, callbacks=[early_stopping] )
4. 检查测试集的数据处理逻辑
你的测试准确率极低,大概率是测试集的预处理和训练集不一致。确保测试集只做rescale=1./255,并且target_size、class_mode和训练/验证集完全一致,同时注意测试集的类别顺序要和flow_from_directory生成的类别映射匹配。
示例测试集处理代码:
test_data_generator = keras.preprocessing.image.ImageDataGenerator(rescale=1./255) test_data_flow = test_data_generator.flow_from_directory( test_dataset_path, target_size=(224, 224), batch_size=32, class_mode='categorical', shuffle=False # 关闭打乱,方便对应标签 ) # 评估模型 test_loss, test_acc = model.evaluate(test_data_flow) print(f"Model Accuracy on Test Set: {test_acc}")
额外建议
- 检查数据集的类别分布,如果存在严重的类别不平衡,会导致模型偏向多数类,测试时准确率骤降。可以用
class_weight参数在训练时加权。 - 减小训练集和验证集的拆分比例,比如设置
validation_split=0.2,让训练集有更多数据学习通用特征。
内容的提问来源于stack exchange,提问作者angryhorse
相关产品推荐
相关产品推荐

