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

加载模型后修改优化器或学习率出现异常结果的问题排查

解决Keras加载模型后继续训练的优化器问题

我之前也碰到过类似的坑,咱们一步步拆解问题出在哪,再给你对应解决方案:

问题1:加载模型直接继续训练,准确率卡在86%不动

这是因为你加载的模型不仅包含权重,还保存了原优化器的训练状态(比如Adam的一阶矩、二阶矩,或者SGD的动量)。之前训练到86%时,优化器已经进入收敛平台期,再加上你设置了decay=0.02,学习率经过衰减后已经非常小,几乎无法再更新权重,所以继续训练准确率没变化。

问题2:重新编译换优化器后,准确率暴跌到15%-20%

这是Keras的正常机制:重新调用model.compile()时,会完全重置优化器的状态——哪怕你用了和原模型一样的权重,新优化器是从头初始化的(没有之前训练积累的动量、矩信息)。对于Adam这种依赖历史状态的优化器来说,新优化器的更新方向会和已收敛的权重完全不匹配,导致模型性能骤降;就算是SGD,没有之前的动量状态,初始更新也会非常“生硬”,表现很差。

问题3:直接赋值model.optimizer = sgd不生效

这是很多人踩的坑:Keras在第一次编译模型时,会把优化器的更新逻辑(比如梯度计算、权重更新步骤)绑定到模型的训练函数中。之后直接修改model.optimizer属性,只是替换了一个变量,但实际训练时调用的还是编译时生成的旧训练函数,根本不会用到新的优化器实例,所以你调大学习率也没反应。


针对性解决方案

方案1:不想换优化器,只是想调整学习率突破平台

不用重新编译,直接修改现有优化器的学习率参数即可,这样能保留原优化器的训练状态:

from keras import backend as K

model = load_model(load_path)

# 查看当前学习率
print("Current LR:", K.get_value(model.optimizer.lr))

# 修改学习率(比如调到0.001)
K.set_value(model.optimizer.lr, 0.001)
# 或者用TensorFlow的assign方法(TensorFlow后端更推荐)
model.optimizer.lr.assign(0.001)

# 直接继续训练,此时学习率已经更新,会看到准确率/损失的波动
history = model.fit_generator(...)

方案2:必须更换优化器(比如从Adam换SGD)

不能直接重新编译,要分两步走:先保存模型权重,再用新优化器编译新模型后加载权重,最后用小学习率warm-up过渡:

# 1. 加载原有模型,只保存权重(不保存优化器状态)
old_model = load_model(load_path)
old_model.save_weights("trained_weights.h5")

# 2. 重新定义和原模型完全一致的模型结构
def build_your_model():
    # 这里复制你原来的模型构建代码,比如:
    # model = Sequential()
    # model.add(Dense(...))
    # ...
    return model

new_model = build_your_model()

# 3. 用新优化器编译模型,加载权重
new_optimizer = optimizers.SGD(lr=0.00001)  # 先用极小学习率warm up
new_model.compile(optimizer=new_optimizer, loss='categorical_crossentropy', metrics=['accuracy'])
new_model.load_weights("trained_weights.h5")

# 4. 先warm up训练2-3个epoch,再逐步提高学习率
new_model.fit_generator(train_gen, epochs=3, ...)

# 之后可以用回调函数调整学习率,比如:
from keras.callbacks import LearningRateScheduler
def adjust_lr(epoch):
    if epoch < 5:
        return 0.00001
    elif epoch < 10:
        return 0.0001
    else:
        return 0.001

lr_scheduler = LearningRateScheduler(adjust_lr)
new_model.fit_generator(train_gen, epochs=20, callbacks=[lr_scheduler], ...)

方案3:自定义训练循环(进阶)

如果你不想重新构建模型,可以手动用Keras后端的函数定义训练步骤,强制使用新优化器:

from keras import backend as K

model = load_model(load_path)
new_optimizer = optimizers.Adam(lr=0.001)

# 定义损失函数和训练步骤
loss_fn = K.categorical_crossentropy
inputs = [model.input, model.targets[0], K.learning_phase()]
loss = loss_fn(model.output, model.targets[0])
updates = new_optimizer.get_updates(model.trainable_weights, model.constraints, loss)

# 构建训练函数
train_fn = K.function(inputs, [loss], updates=updates)

# 然后自己写训练循环(示例)
for epoch in range(r_epochs):
    print(f"Epoch {epoch+1}/{r_epochs}")
    total_loss = 0.0
    for step in range(r_steps_per_epoch):
        x_batch, y_batch = next(train_gen)
        loss_val = train_fn([x_batch, y_batch, 1])[0]
        total_loss += loss_val
    print(f"Train loss: {total_loss/r_steps_per_epoch:.4f}")
    # 可以自己加验证逻辑

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.28 09:23:24