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

Keras单模型双损失函数实现及模型截断训练权重问题问询

关于Keras双任务MinMax训练的权重一致性与可行性解答

首先直接回应你的核心问题:

一、model_1和model_2的权重默认不一致

在你当前的代码里,model_1和model_2是完全独立的Keras Model实例——虽然它们初始时共享相同的层结构和初始权重,但一旦你开始训练model_1,只有model_1内部的层权重会被更新,model_2的权重会停留在初始状态,不会自动同步。

这是因为Keras中每个Model对象都维护自己的权重副本,除非你显式让它们共享层(比如先定义层变量,再在两个模型中复用),否则两者的权重是完全分开的。

二、可以完成MinMax博弈训练,但需要手动同步权重

要实现你的MinMax训练逻辑(先训CTC任务的model_1,再训截断得到的分类任务model_2),你需要手动处理权重同步,具体步骤如下:

1. 修复代码中的层定义问题

你的代码里有个明显的笔误:inner_act = Flatten()(inner_act)这行中,inner_act还未定义,应该改为:

inner_act = Flatten()(inner)  # inner是经过两次MaxPooling后的特征层

否则代码会直接抛出未定义变量的错误。另外,Model(inputs=input_data, outputs=y_pred)这行没有赋值给变量,属于无效代码,可以删除。

2. 训练model_1后同步权重到model_2

当你完成model_1的CTC任务训练后,需要把model_1中与model_2重叠的层的权重复制到model_2中。比如model_2用到的conv1、max1、conv2、max2、Flatten这些层,和model_1里的对应层结构一致,可以通过以下方式同步:

# 遍历model_2的每一层,从model_1中获取对应层的权重并赋值
for layer_2, layer_1 in zip(model_2.layers, model_1.layers[:len(model_2.layers)-2]):
    # 注意model_2的最后两层是dense3和sigmoid,model_1里没有,所以只同步前面的共享层
    layer_2.set_weights(layer_1.get_weights())

或者更优雅的方式:在定义模型时就共享层对象,比如先把共享的卷积池化层定义为变量,再在两个模型中复用:

# 先定义共享的基础特征提取层
input_data = Input(name='the_input', shape=input_shape, dtype='float32')
conv1 = Conv2D(conv_filters, kernel_size, padding='same', activation=act, kernel_initializer='he_normal', name='conv1')(input_data)
max1 = MaxPooling2D(pool_size=(pool_size, pool_size), name='max1')(conv1)
conv2 = Conv2D(conv_filters, kernel_size, padding='same', activation=act, kernel_initializer='he_normal', name='conv2')(max1)
max2 = MaxPooling2D(pool_size=(pool_size, pool_size), name='max2')(conv2)

# 构建model_2的分支(分类任务)
inner_act = Flatten()(max2)
inner_2 = Dense(1, name='dense3')(inner_act)
inner_out = Activation('sigmoid')(inner_2)
model_2 = Model(inputs=input_data, outputs=inner_out)

# 构建model_1的CTC分支
conv_to_rnn_dims = (img_w // (pool_size ** 2), (img_h // (pool_size ** 2)) * conv_filters)
reshape = Reshape(target_shape=conv_to_rnn_dims, name='reshape')(max2)
dense1 = Dense(time_dense_size, activation=act, name='dense1')(reshape)
# ... 后续GRU和CTC相关层定义 ...
model_1 = Model(inputs=[input_data, labels, input_length, label_length], outputs=loss_out)

这样定义的话,model_1和model_2会共享conv1、max1、conv2、max2这些层的权重——训练model_1时,这些层的权重会自动同步到model_2,不需要手动复制。

3. 按需控制训练时的可训练层

在MinMax博弈训练中,你可能希望训练model_2时,只更新分类分支的层(比如dense3),而保持基础特征层和model_1一致;或者反过来。可以通过设置层的trainable属性实现:

# 冻结model_2的基础特征层,只训练分类分支
for layer in model_2.layers[:-2]:  # 前几层是共享的卷积池化层
    layer.trainable = False
# 重新编译model_2
model_2.compile(optimizer='adam', loss='binary_crossentropy', metrics=['accuracy'])
# 然后训练model_2

总结

  • 默认情况下model_1和model_2权重不一致,因为是独立模型;
  • 通过共享层定义或者手动权重复制,可以实现两者权重同步,进而完成MinMax博弈训练;
  • 训练时可以通过冻结层来控制哪些权重被更新,匹配你的博弈训练逻辑。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.15 08:16:33