VAE添加自定义分类损失编译时出现类型错误求助
问题原因
你触发报错的核心原因是当前Keras/TensorFlow版本不支持混合使用add_loss接口和compile参数传入损失字典的写法,你提前通过add_loss添加的VAE基础损失(重构+KL散度)被框架识别为未调用的函数对象,而非可计算的浮点张量,因此报类型错误。
可行解决方法
方案1:统一使用add_loss添加所有损失(推荐,适配性最高)
把分类损失也合并到总损失中,统一通过add_loss添加,compile阶段不再传入损失参数,修改代码如下:
# 原有计算重构、KL损失的代码不变 reconstruction_loss = binary_crossentropy(inputs, outputs[0]) reconstruction_loss *= original_dim kl_loss = 1 + z_log_var - K.square(z_mean) - K.exp(z_log_var) kl_loss = K.sum(kl_loss, axis=-1) kl_loss *= -0.5 base_vae_loss = K.mean((reconstruction_loss + kl_loss) /100.0) # 新增计算分类损失 clf_loss = K.mean(categorical_crossentropy(y_train, outputs[1])) # 合并总损失后统一添加 total_loss = base_vae_loss + clf_loss vae.add_loss(total_loss) # 编译阶段仅指定优化器即可 vae.compile(optimizer='adam') # 训练阶段也不需要传入损失字典,标签已经包含在损失计算逻辑中 svae_history = vae.fit(x_train, epochs=epochs, batch_size=batch_size)
方案2:统一使用compile传入所有损失
取消add_loss的写法,把VAE基础损失封装为自定义损失函数,和分类损失一起通过compile的损失字典传入,修改代码如下:
# 定义VAE基础损失函数 def vae_base_loss(y_true, y_pred): reconstruction_loss = binary_crossentropy(y_true, y_pred) reconstruction_loss *= original_dim kl_loss = 1 + z_log_var - K.square(z_mean) - K.exp(z_log_var) kl_loss = K.sum(kl_loss, axis=-1) kl_loss *= -0.5 return K.mean((reconstruction_loss + kl_loss) /100.0) # 给VAE的两个输出指定明确的名称 outputs = [ decoder(encoder(inputs)[2], name='recon_output'), clf_supervised(encoder(inputs)[2], name='clf_output') ] vae = Model(inputs, outputs, name='vae_mlp') # 编译时传入对应输出的损失字典 vae.compile(optimizer='adam', loss={ 'recon_output': vae_base_loss, 'clf_output': 'categorical_crossentropy' }) # 训练时传入对应输出的标签 svae_history = vae.fit(x_train, { 'recon_output': x_train, 'clf_output': y_train }, epochs=epochs, batch_size=batch_size)
注意事项
两种方案选其一即可,不要混合使用两种加损失的方式,即可解决类型报错问题。
内容的提问来源于stack exchange,提问作者Johnny Tam
相关产品推荐
相关产品推荐

