KerasTensor下使用Binary Crossentropy报错的解决方法及疑问
问题描述
我尝试在tf/keras中实现VAE模型,但binary_crossentropy出现问题。代码片段如下:
import tensorflow as tf from tensorflow.keras import backend as K from tensorflow.keras.layers import Lambda, Input, Dense from tensorflow.keras.losses import binary_crossentropy from tensorflow.keras.models import Model ... def build_vae(): ... reconstruction_loss = binary_crossentropy(inputs, outputs) * image_size 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 vae_loss = K.mean(reconstruction_loss + kl_loss)
已确认inputs和outputs为KerasTensor类型,报错信息:
ValueError: A KerasTensor cannot be used as input to a TensorFlow function. A KerasTensor is a symbolic placeholder for a shape and dtype, used when constructing Keras Functional models or Keras Functions. You can only use it as input to a Keras layer or a Keras operation (from the namespaces
keras.layersandkeras.operations).
我尝试用keras Layer子类包装binary_crossentropy可解决该行报错,但后续所有K函数都会报错,不想对所有K函数重复此操作。
修复方案
方案1:改用Keras后端的二元交叉熵函数
直接替换为K.binary_crossentropy,它是专门为KerasTensor这类符号张量设计的,能直接兼容:# 替换原reconstruction_loss计算行 reconstruction_loss = K.binary_crossentropy(inputs, outputs) * image_size方案2:使用keras.operations下的对应函数
TensorFlow 2.10+版本中,Keras新增了keras.operations命名空间,里面的操作完全兼容KerasTensor:from tensorflow.keras.operations import binary_crossentropy # 正常使用即可 reconstruction_loss = binary_crossentropy(inputs, outputs) * image_size
疑问解答
为什么tensorflow.keras.losses.binary_crossentropy不接受KerasTensor?
tensorflow.keras.losses下的损失函数本质是被tf.function包装的TensorFlow函数,它们的设计目标是接收实际运行时的数值张量,而非模型构建阶段的符号占位符KerasTensor。
而keras.backend(即K)下的函数、keras.operations下的操作,是专门为Keras的符号计算图设计的,能识别并处理KerasTensor这类符号占位符,所以在构建Functional模型的自定义损失时,必须使用这类Keras原生的符号操作函数。
内容的提问来源于stack exchange,提问作者BBrooklyn

