基于预训练模型的双输入迁移学习构建报错求助
问题根源与解决方案
这个报错的核心原因很简单:你把同一个预训练模型实例直接赋值给了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
相关产品推荐
相关产品推荐

