使用预训练Keras模型时遭遇维度形状错误
VGG16+自定义CNN组合:MaxPooling2D负维度错误快速修复
问题背景
需要基于带预训练权重的VGG16模型,追加自定义简易CNN结构,参考Keras教程改造后,训练时出现MaxPooling2D负维度错误,希望保留MaxPooling层以对比模型结果,寻求快速修复方案。
原自定义CNN代码
model = Sequential() model.add(Rescaling(1.0 / 255)) model.add(Conv2D(32, kernel_size=(3, 3), activation='relu', input_shape=(256,256,3))) model.add(MaxPool2D(pool_size=(2, 2), strides=2)) model.add(Conv2D(64, kernel_size=(3, 3), activation='relu')) model.add(MaxPool2D(pool_size=(2, 2), strides=2)) model.add(Flatten()) model.add(Dense(units=5, activation='softmax'))
改造后代码
x = base_model.output x = Rescaling(1.0 / 255)(x) x = Conv2D(32, kernel_size=(3, 3), activation='relu', input_shape=(256,256,3))(x) x = MaxPool2D(pool_size=(2, 2), strides=2)(x) x = Conv2D(64, kernel_size=(3, 3), activation='relu')(x) x = MaxPool2D(pool_size=(2, 2), strides=2)(x) x = GlobalAveragePooling2D()(x) predictions = Dense(units=5, activation='softmax')(x)
错误信息
ValueError: Exception encountered when calling layer "max_pooling2d_7" (type MaxPooling2D). Negative dimension size caused by subtracting 2 from 1 for '{{node model/max_pooling2d_7/MaxPool}} = MaxPool[T=DT_FLOAT, data_format="NHWC", explicit_paddings=[], ksize=[1, 2, 2, 1], padding="VALID", strides=[1, 2, 2, 1]](model/conv2d_10/Relu)' with input shapes: [?,1,1,64]. Call arguments received: • inputs=tf.Tensor(shape=(None, 1, 1, 64), dtype=float32)
快速修复方案
错误本质是VGG16输出的特征图经过自定义CNN的卷积、池化后,尺寸缩小到1x1,此时再执行2x2的MaxPooling就会出现负维度。以下是几种保留MaxPooling层的修复方法:
方法1:给卷积层添加padding='same'
让卷积操作不缩小特征图尺寸,仅通过池化层降低维度,避免过早出现1x1的特征图:
# 初始化VGG16时指定输入形状(匹配你的256x256输入) base_model = VGG16(weights='imagenet', include_top=False, input_shape=(256,256,3)) x = base_model.output # 移除多余的Rescaling:VGG16预训练权重对应输入无需额外归一化,改用preprocess_input处理数据 x = Conv2D(32, kernel_size=(3, 3), activation='relu', padding='same')(x) # 添加padding='same',去掉无用的input_shape x = MaxPool2D(pool_size=(2, 2), strides=2)(x) x = Conv2D(64, kernel_size=(3, 3), activation='relu', padding='same')(x) # 添加padding='same' x = MaxPool2D(pool_size=(2, 2), strides=2)(x) x = GlobalAveragePooling2D()(x) predictions = Dense(units=5, activation='softmax')(x)
方法2:给MaxPooling2D添加padding='same'
即使特征图尺寸不足2x2,通过填充保证池化后维度为正:
x = base_model.output x = Conv2D(32, kernel_size=(3, 3), activation='relu')(x) x = MaxPool2D(pool_size=(2, 2), strides=2, padding='same')(x) # 添加padding='same' x = Conv2D(64, kernel_size=(3, 3), activation='relu')(x) x = MaxPool2D(pool_size=(2, 2), strides=2, padding='same')(x) # 添加padding='same' x = GlobalAveragePooling2D()(x) predictions = Dense(units=5, activation='softmax')(x)
额外注意事项
- 初始化VGG16时必须指定
input_shape=(256,256,3)且include_top=False,这样输出的特征图尺寸为8x8x512,足够支撑后续的卷积池化操作; - 移除
Rescaling(1.0/255),改用tf.keras.applications.vgg16.preprocess_input处理输入数据,匹配VGG16预训练权重的输入要求。
内容的提问来源于stack exchange,提问作者brosefzai
相关产品推荐
相关产品推荐

