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

Keras加载模型后损失函数骤增问题求助(自定义数据+强增强)

Keras模型续训时损失骤升但准确率正常的排查建议

我碰到过类似的情况,这种损失数值暴增但模型准确率维持正常的现象,基本可以排除模型权重损坏的可能,问题大概率出在损失计算的环节——也就是模型加载后,损失函数的组成部分(比如正则化项、类别权重)和训练时不一致了。结合你的代码和日志,给你几个优先排查的方向:

1. 重点检查动态添加的L2正则化器是否被正确保存/加载

你在训练时手动给MobileNetV2的层添加了L2正则化:

for layer in l:
    if 'kernel_regularizer' in layer.get_config():
        layer.kernel_regularizer=l2(l=0.1)
    # ... 偏置正则化同理

但Keras的save()方法对这种模型构建后动态修改的层属性支持不好,序列化时无法完整保存这些后续添加的正则化器。加载模型后,这些正则化项可能丢失,或者出现异常,导致损失计算时正则化部分的数值暴增(或者和训练时的计算逻辑不一致)。

你可以做这几步验证:

  • 加载模型后,打印每一层的正则化器,确认是否和训练时一致:
    for layer in model_mod.layers:
        print(f"层名称:{layer.name},kernel正则化器:{layer.kernel_regularizer}")
    
  • 尝试在续训时暂时移除所有正则化操作,或者在模型构建阶段就把正则化器加入层配置(而不是事后修改),看损失是否恢复正常。

2. 确认数据生成器的完全一致性

虽然你训练和续训用了相同的生成器代码,但有几个细节要核对:

  • 检查get_random_eraser里的random_crop和norm函数在续训时是否和训练时完全一致,比如归一化后的图像值范围是否是[-1, 1],随机裁剪的逻辑有没有误改。
  • 确认flow_from_directory的validation_split划分是否和训练时完全一致:Keras的这个划分是基于文件名哈希的,理论上不会变,但你可以手动对比训练和续训时验证集的类别分布,避免出现数据划分异常。

3. 避免续训时重新compile重置优化器状态

你的续训代码里调用了model_mod.compile(...),这会覆盖加载的优化器状态——虽然你用了和训练时相同的优化器参数,但save()保存的动量缓存、学习率衰减状态等都会被重置。虽然这通常会导致准确率下降,但也可能间接影响损失计算的稳定性。

你可以试试:

  • 加载模型后,不调用compile,直接执行fit_generator续训,看损失是否正常。
  • 如果必须compile,确保compile时的参数和训练时完全一致,包括损失函数、优化器的所有超参数。

4. 验证类别权重(class_weight)的影响

你用了class_weight.compute_class_weight来平衡类别,虽然续训时重新计算了一次,但可能出现计算逻辑的细微差异(比如训练时和续训时的train_generator.classes是否完全一致)。

可以先暂时去掉class_weight,续训一轮看损失是否恢复正常。如果去掉后损失正常,说明是类别权重和加载后的模型损失计算不兼容,你可以尝试手动把类别权重加入损失函数,而不是通过fit_generator的参数传递。

5. 手动计算损失定位问题

最直接的方式是手动计算损失,和模型输出的损失对比:

import tensorflow as tf
from tensorflow.keras import losses

# 取一个验证集batch
x_val, y_val = next(validation_generator)
# 模型预测
preds = model_mod.predict(x_val)

# 计算分类交叉熵损失
ce_loss = losses.categorical_crossentropy(y_val, preds).numpy().mean()

# 计算L2正则化损失
l2_loss = 0.0
for layer in model_mod.layers:
    if hasattr(layer, 'kernel_regularizer') and layer.kernel_regularizer is not None:
        l2_loss += layer.kernel_regularizer(layer.kernel).numpy()
    if hasattr(layer, 'bias_regularizer') and layer.bias_regularizer is not None:
        l2_loss += layer.bias_regularizer(layer.bias).numpy()

# 总损失
total_loss = ce_loss + l2_loss
print(f"手动计算总损失:{total_loss},模型输出val_loss:{49.8441}")

如果手动计算的损失和模型输出差异极大,基本可以确定是正则化项的加载问题;如果差异很小,那就要检查类别权重或者生成器的问题。

另外,你提到MNIST数据集上没有这个问题,也侧面印证了是这个特定模型(MobileNetV2动态添加正则化)的序列化/加载问题,优先排查第一点应该就能解决。

内容的提问来源于stack exchange,提问作者Vojtech Molek

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.13 09:23:42