TensorFlow中Input has undefined rank错误的原因及修复方案
DenseNet自定义模型报错:Input has undefined rank的原因与修复
问题描述
自定义DenseNet模型时已明确指定输入形状,但运行时触发ValueError: Input has undefined rank. Received: input_shape=<unknown>.错误。
代码实现
def densenet(input_shape, n_classes, filters = 32): #batch norm + relu + conv def bn_rl_conv(x,filters,kernel=1,strides=1): x = BatchNormalization()(x) x = ReLU()(x) x = Conv2D(filters, kernel, strides=strides,padding = 'same')(x) return x def dense_block(x, repetition): for _ in range(repetition): y = bn_rl_conv(x, 4*filters) y = bn_rl_conv(y, filters, 3) x = concatenate([y,x]) return x def transition_layer(x): x = bn_rl_conv(x, K.int_shape(x)[-1] //2 ) x = AvgPool2D(2, strides = 2, padding = 'same')(x) return x inp = Input (input_shape) x = Conv2D(64, 7, strides = 2, padding = 'same')(inp) x = MaxPool2D(3, strides = 2, padding = 'same')(x) for repetition in [2,4,6,4]: d = dense_block(x, repetition) x = transition_layer(d) x = GlobalAveragePooling2D()(x) output = Dense(n_classes, activation = 'softmax')(x) model = Model(inp, output) return model input_shape = (1024,2,1) num_classes = 24 model = densenet(input_shape,num_classes)
报错信息
/usr/local/lib/python3.7/dist-packages/keras/utils/traceback_utils.py in error_handler(*args, **kwargs) 65 except Exception as e: # pylint: disable=broad-except 66 filtered_tb = _process_traceback_frames(e.__traceback__) ---> 67 raise e.with_traceback(filtered_tb) from None 68 finally: 69 del filtered_tb /usr/local/lib/python3.7/dist-packages/keras/layers/normalization/batch_normalization.py in build(self, input_shape) 296 if not input_shape.ndims: 297 raise ValueError( --> 298 f'Input has undefined rank. Received: input_shape={input_shape}.') 299 ndims = len(input_shape) 300 ValueError: Input has undefined rank. Received: input_shape=<unknown>.
原因分析
错误核心在transition_layer函数中的K.int_shape(x)[-1] //2:
- 在Keras函数式API的模型构建阶段,张量
x的静态形状尚未完全固化,K.int_shape(x)[-1]返回的是符号化张量而非具体整数。 - 当这个符号化值被传入
bn_rl_conv作为Conv2D的filters参数时,Conv2D层无法确定输入维度(rank),进而导致后续BatchNormalization层触发输入rank未知的错误。
修复方案
将transition_layer中获取通道数的方式改为直接读取张量的静态形状属性x.shape[-1],它能在模型构建阶段返回确定的整数值:
修改后的transition_layer函数:
def transition_layer(x): # 直接读取静态通道数并减半 current_channels = x.shape[-1] x = bn_rl_conv(x, current_channels // 2) x = AvgPool2D(2, strides = 2, padding = 'same')(x) return x
若你的Keras版本对x.shape[-1]支持有限,也可改用tf.keras.backend.int_shape(x)[-1],确保在构建时能解析为整数:
def transition_layer(x): current_channels = tf.keras.backend.int_shape(x)[-1] x = bn_rl_conv(x, current_channels // 2) x = AvgPool2D(2, strides = 2, padding = 'same')(x) return x
修改后重新运行代码,模型即可正常构建。
内容的提问来源于stack exchange,提问作者nechi
相关产品推荐
相关产品推荐

