Keras迁移学习求助:损失值无下降,模型未产生训练效果
解决迁移学习中损失值无法下降的问题
我仔细排查了你的代码,发现几个关键问题,这应该就是模型损失一直卡在50%(随机猜测水平)的核心原因:
1. 损失函数与输出层激活严重不匹配(最关键问题)
你的模型最后一层用了sigmoid激活,但编译时却设置了loss = tf.keras.losses.BinaryCrossentropy(from_logits= True)——这完全冲突了!
from_logits=True是告诉损失函数:模型输出的是未经过激活的原始logits值(范围覆盖全体实数)- 但你的
sigmoid已经把输出压缩到了0-1的概率区间,此时必须把from_logits设为False(或者直接省略,因为默认值就是False)
这个错误会让损失计算完全失真,模型根本无法学到任何有用的特征,自然一直保持随机猜测的水平。
2. 验证集错误使用数据增强
你的valid_gen添加了大量数据增强操作(剪切、缩放、翻转等),这是完全不合理的:
- 验证集的作用是评估模型在真实未见过的原始数据上的性能,数据增强只应该用在训练集,用来扩充训练数据、提升模型泛化能力
- 验证集只需要做符合预训练模型要求的预处理即可,否则会干扰验证结果,让你无法准确判断模型的真实表现
3. 冗余的Flatten层与未使用的全局池化层
你定义了global_avg_layer = tf.keras.layers.GlobalAveragePooling2D()但没在模型里使用,反而用了Flatten:
- 对于MobileNetV2这类预训练CNN模型,
GlobalAveragePooling2D可以更高效地提取全局特征,同时大幅减少参数数量,避免过拟合 - 去掉多余的
Flatten层,改用全局池化层是更合理的选择
4. 未使用预训练模型的专用预处理函数
MobileNetV2在训练时用的是专门的预处理逻辑,不是简单的1.0/255.0归一化。你应该使用tf.keras.applications.mobilenet_v2.preprocess_input来处理输入图像,这样才能和预训练模型的特征提取逻辑匹配,发挥预训练权重的作用。
修正后的关键代码片段
修正数据生成器
# 训练集使用数据增强+专用预处理 train_gen = ImageDataGenerator( preprocessing_function=tf.keras.applications.mobilenet_v2.preprocess_input, shear_range=0.2, zoom_range=0.3, width_shift_range=0.2, height_shift_range=0.2, horizontal_flip=True, rotation_range=45, validation_split=0.2 ) # 验证集只做专用预处理,不做数据增强 valid_gen = ImageDataGenerator( preprocessing_function=tf.keras.applications.mobilenet_v2.preprocess_input, validation_split=0.2 )
修正模型结构与编译
tf.keras.backend.clear_session() base_model = tf.keras.applications.MobileNetV2( input_shape=(160,160,3), weights='imagenet', include_top=False ) base_model.trainable = False # 使用全局平均池化层,去掉冗余的Flatten model = tf.keras.Sequential([ base_model, tf.keras.layers.GlobalAveragePooling2D(), tf.keras.layers.Dense(512, activation='relu'), tf.keras.layers.Dropout(0.5), tf.keras.layers.Dense(1, activation='sigmoid') ]) # 修正损失函数参数 model.compile( optimizer=tf.keras.optimizers.Adam(learning_rate=0.0001), loss=tf.keras.losses.BinaryCrossentropy(), # 默认from_logits=False,无需额外设置 metrics=['accuracy'] )
先修正这些核心问题,再重新训练模型,应该就能看到损失值开始下降了。如果之后想要微调(设置base_model.trainable=True),记得要把学习率降到1e-5左右,避免破坏预训练好的特征。
内容的提问来源于stack exchange,提问作者Satinder Pal Singh
相关产品推荐
相关产品推荐

