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

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.11 08:06:16