DeepVOG模型初始化报错:Keras符号输入不支持__len__方法
DeepVOG模型初始化错误原因分析与修复
错误核心原因
符号张量与Python条件判断冲突
在Keras函数式API构建模型时,X_jump是符号张量(Keras Tensor),仅代表计算图中的节点,没有实际数值。你在decoding_block中使用Python原生的if语句结合tf.math.reduce_all判断张量是否全零,这种操作会触发对符号张量的__len__调用——而Keras符号张量不支持该方法,直接抛出报错。混合使用NumPy数组与符号张量
代码中X_jump的默认值设为np.zeros((1))(NumPy数组),但调用时传入的是编码阶段输出的符号张量,这种混合类型的输入在函数式API构建计算图时完全不兼容,进一步加剧了张量类型冲突。
修复方案
要解决这个问题,需要完全基于Keras函数式API的规则重构decoding_block的分支逻辑,避免对符号张量做数值判断,改用参数存在性来控制分支:
1. 修改decoding_block函数
将X_jump的默认值改为None,并基于X_jump是否为None来决定是否拼接张量,而非判断张量数值:
def decoding_block(X, filter_size, filters_num, layer_num, block_type, stage, s = 1, X_jump = None, up_sampling = True): # defining name basis conv_name_base = 'conv_' + block_type + str(stage) + '_' bn_name_base = 'bn_' + block_type + str(stage) + '_' # Joining X_jump from encoding side with X_uped if X_jump is None: X_joined_input = X else: X_joined_input = Concatenate(axis = 3)([X,X_jump]) ##### MAIN PATH ##### for i in np.arange(layer_num)+1: # First component of main path X_joined_input = Conv2D(filters_num, filter_size , strides = (s,s), padding = 'same', name = conv_name_base + 'main_' + str(i), kernel_initializer = glorot_uniform())(X_joined_input) X_joined_input = BatchNormalization(axis = 3, name = bn_name_base + 'main_' + str(i))(X_joined_input) if i != layer_num: X_joined_input = Activation('relu')(X_joined_input) X_joined_input = Activation('relu')(X_joined_input) # Up-sampling layer. At the output layer, up-sampling is disabled and replaced by other stuffs manually if up_sampling == True: X_uped = Conv2DTranspose(filters_num, (2, 2), strides = (2,2), padding = 'valid', name = conv_name_base + 'up', kernel_initializer = glorot_uniform())(X_joined_input) X_uped = BatchNormalization(axis = 3, name = bn_name_base + 'up')(X_uped) X_uped = Activation('relu')(X_uped) return X_uped else: return X_joined_input
2. 修改DeepVOG_net中的调用逻辑
将第一次调用decoding_block时的X_jump=0改为X_jump=None:
# Decoding Stream print("dec0") print(type(X_jump4)) # 这里把X_jump=0改成X_jump=None X_out = decoding_block(X = X_out, X_jump = None, filter_size= filter_size, filters_num= 256, layer_num= 1, block_type = "up", stage = 1, s = 1) print("dec1") X_out = decoding_block(X = X_out, X_jump = X_jump4, filter_size= filter_size, filters_num= 256, layer_num= 1, block_type = "up", stage = 2, s = 1) # 后续调用保持不变
原理说明
Keras函数式API依赖静态计算图,所有操作需要在模型构建阶段就确定计算流程。Python的if语句是在构建时执行的,无法感知符号张量的运行时数值;而基于X_jump is None的判断是Python层面的静态判断,在构建时就能确定分支逻辑,Keras可以正确将其转换为计算图的一部分,避免了对符号张量的非法操作。
内容的提问来源于stack exchange,提问作者jkos
相关产品推荐
相关产品推荐

