Keras实现ADDA时Target Generator未更新的技术问询
从你的描述和代码来看,Target Model的预测始终和Source一致,核心问题是Target Generator的权重没有在训练过程中得到更新,大概率是模型构建时的权重共享、可训练状态设置或者训练流程的问题。我帮你梳理了几个关键问题和对应的修复方案:
1. Target Generator未复制Source的预训练权重
你提到已经加载了预训练的Source模型,但代码里self.target_generator = self.build_generator(modelInput)是重新初始化了一个新的Generator,并没有继承Source Generator的预训练权重。这会导致初始状态下Target和Source的Generator权重相同(因为初始化方式一致),但后续训练如果没关联上,权重也不会更新。
修复:在预训练完Source模型后,把Source Generator的权重复制给Target Generator:
# 假设你已经完成了Source模型的预训练 self.target_generator.set_weights(self.source_generator.get_weights())
2. Combined Model的构建方式导致权重不共享
你用Sequential来组合Target Generator和Discriminator,这种方式在嵌套Model层时可能会出现权重不共享的问题——训练Combined Model时的更新没有同步到你定义的self.target_generator实例上。
建议改用Functional API构建Combined Model,确保权重完全共享:
# 替换原有的Combined Model构建代码 target_input = layers.Input(shape=self.img_shape) # 使用同一个target_generator实例 target_features = self.target_generator(target_input) disc_output = self.discriminator_model(target_features) self.combined_model = Model(target_input, disc_output) # 固定Discriminator的权重,只训练Target Generator self.discriminator_model.trainable = False self.combined_model.compile(optimizer=optimizer, loss='binary_crossentropy', metrics=['acc'])
3. 训练Discriminator时未冻结Generator权重
ADDA的流程要求训练Discriminator时,Source和Target Generator的权重必须固定,否则Discriminator的训练会无意中改变Generator的特征提取能力,破坏Domain Adaptation的逻辑。
修复:在训练Discriminator之前,冻结两个Generator的权重:
# 训练Discriminator阶段 self.source_generator.trainable = False self.target_generator.trainable = False self.discriminator_model.trainable = True # 重新编译Discriminator(因为修改了trainable状态) self.discriminator_model.compile(optimizer=optimizer, loss='binary_crossentropy', metrics=['acc']) # 然后用Source特征和Target特征训练Discriminator # 示例:获取Source和Target的特征 source_feats = self.source_generator.predict(source_data) target_feats = self.target_generator.predict(target_data) # 构造标签:Source为[1,0],Target为[0,1](对应Discriminator的2类输出) source_labels = np.zeros((len(source_feats), 2)) source_labels[:, 0] = 1 target_labels = np.zeros((len(target_feats), 2)) target_labels[:, 1] = 1 # 合并数据并训练 X_disc = np.concatenate([source_feats, target_feats]) y_disc = np.concatenate([source_labels, target_labels]) self.discriminator_model.fit(X_disc, y_disc, epochs=..., batch_size=...)
4. Target Model中的Classifier未固定
ADDA中Source Classifier是预训练好的固定模块,用来评估Target Generator的特征适配效果。你的Target Model中直接使用了self.source_classificator,但默认它是可训练的,这会导致训练Target Model时(如果有的话)更新Classifier权重,而不是只更新Target Generator。
修复:固定Source Classifier的权重,重新编译Target Model:
self.source_classificator.trainable = False self.target_model.compile(optimizer=optimizer, loss='categorical_crossentropy', metrics=['acc'])
5. 训练Combined Model的标签逻辑要正确
训练Combined Model时,我们的目标是让Target Generator生成的特征被Discriminator误判为Source特征,所以输入Target图像时,标签应该设置为Source对应的类别(即[1,0],和Discriminator训练时的Source标签一致):
# 训练Combined Model阶段 self.discriminator_model.trainable = False self.target_generator.trainable = True # 重新编译Combined Model(可选,确保trainable状态生效) self.combined_model.compile(optimizer=optimizer, loss='binary_crossentropy', metrics=['acc']) # 构造标签:全部设为Source的类别 y_combined = np.zeros((len(target_data), 2)) y_combined[:, 0] = 1 # 用Target数据训练Combined Model self.combined_model.fit(target_data, y_combined, epochs=..., batch_size=...)
按照这些修改调整后,Target Generator的权重应该会在训练过程中得到更新,Target Model的预测结果也会逐渐和Source Model产生差异,最终在Target域上获得更好的适配效果。
内容的提问来源于stack exchange,提问作者JecaJeca

