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

基于预训练模型的双输入迁移学习构建报错求助

问题根源与解决方案

这个报错的核心原因很简单:你把同一个预训练模型实例直接赋值给了u_model和v_model,这本质上是同一个模型对象的引用,导致两个分支共享同一个输入张量。Keras明确不允许输入列表中存在重复的张量,所以才抛出了ValueError。

另外注意到你提到需求是拼接两个模型最后一层之前的输出,但原代码里取的是layers[-1].output(也就是原模型的最终输出层),这和你的需求不符,我会在解决方案里一并纠正。

修改后的代码方案

这里提供两种实现方式,都能解决输入重复的问题:

方式1:两次加载模型(简单直观)

直接加载两次预训练模型,得到两个完全独立的实例,它们的输入张量自然是不同的:

from tensorflow.keras.models import load_model, Model
from tensorflow.keras.layers import concatenate, Dense
from tensorflow.keras.optimizers import SGD

def combined_net():
    # 加载两个独立的预训练模型实例
    u_model = load_model('best_weight.h5')
    v_model = load_model('best_weight.h5')
    
    # 获取最后一层之前的特征输出(对应原模型的Dense(256)层)
    u_output = u_model.layers[-2].output
    v_output = v_model.layers[-2].output
    
    # 拼接两个分支的特征
    concat = concatenate([u_output, v_output])
    
    # 添加新的最终输出层
    main_output = Dense(1, activation='sigmoid', name='main_output')(concat)
    
    # 构建双输入模型,此时两个输入是独立张量
    model = Model(inputs=[u_model.input, v_model.input], outputs=main_output)
    
    # 编译模型
    opt = SGD(lr=0.001, nesterov=True)
    model.compile(loss='binary_crossentropy', optimizer=opt, metrics=['accuracy'])
    
    return model

方式2:克隆模型(节省内存)

如果不想加载两次模型占用额外内存,可以先加载一次,再克隆模型结构并复制权重:

from tensorflow.keras.models import load_model, Model, clone_model
from tensorflow.keras.layers import concatenate, Dense
from tensorflow.keras.optimizers import SGD

def combined_net():
    # 仅加载一次预训练模型
    base_model = load_model('best_weight.h5')
    
    # 克隆出两个独立的模型结构
    u_model = clone_model(base_model)
    v_model = clone_model(base_model)
    
    # 把原模型的权重复制给克隆模型
    u_model.set_weights(base_model.get_weights())
    v_model.set_weights(base_model.get_weights())
    
    # 后续步骤和方式1一致
    u_output = u_model.layers[-2].output
    v_output = v_model.layers[-2].output
    concat = concatenate([u_output, v_output])
    main_output = Dense(1, activation='sigmoid', name='main_output')(concat)
    model = Model(inputs=[u_model.input, v_model.input], outputs=main_output)
    
    opt = SGD(lr=0.001, nesterov=True)
    model.compile(loss='binary_crossentropy', optimizer=opt, metrics=['accuracy'])
    
    return model

可选优化:冻结预训练层(迁移学习常用策略)

如果你希望只训练新添加的层和预训练模型的顶层,可以在构建分支后添加冻结代码:

# 在加载/克隆模型后添加
for layer in u_model.layers[:15]:
    layer.trainable = False
for layer in v_model.layers[:15]:
    layer.trainable = False

训练代码保持不变

你原来的训练代码不需要修改,直接调用combined_net()即可:

best_weights_file="weights_best_of_pretrained_dual.hdf5"
checkpoint = ModelCheckpoint(best_weights_file, monitor='val_acc', verbose=1, save_best_only=True, mode='max')
callbacks = [checkpoint]
base_model = combined_net()
print(base_model.summary())  # 这里注意要加括号调用summary方法
history = base_model.fit([x_train_u, x_train_v], y_train, batch_size=batch_size, epochs=epochs, callbacks=callbacks, verbose=1, validation_data=([x_test_u, x_test_v], y_test), shuffle=True)

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.08 21:48:10