CNN过度卷积致张量尺寸异常的解决方案咨询
解决CNN特征图尺寸过小引发的报错问题
我想用CNN检测特定模式,但启用代码中注释的最后两组Conv2D层及后续MaxPooling2D层时会报错,目前只能把这些层注释掉。输入张量尺寸为(256,256,27),代码里每轮MaxPooling2D前都配一次Conv2D层,多轮处理后张量尺寸变成了(None,2,2,394),推测是过度卷积导致尺寸太小才触发的错误,求解决办法。
原代码
inputs = tf.keras.layers.Input(shape=(256, 256, 27), name='input_layer') lambda_layer = tf.keras.layers.Lambda(lambda value: value / 255)(inputs) xp = tf.keras.layers.Conv2D(64, 3, padding='same', activation=tf.nn.relu)(lambda_layer) xp = tf.keras.layers.MaxPooling2D()(xp) # 默认池化窗口2x2 xp = tf.keras.layers.BatchNormalization()(xp) xp = tf.keras.layers.Conv2D(94, 3, padding='same', activation=tf.nn.relu)(xp) xp = tf.keras.layers.MaxPooling2D()(xp) xp = tf.keras.layers.BatchNormalization()(xp) xp = tf.keras.layers.Conv2D(128, 3, padding='same', activation=tf.nn.relu)(xp) xp = tf.keras.layers.MaxPooling2D()(xp) xp = tf.keras.layers.BatchNormalization()(xp) xp = tf.keras.layers.Conv2D(156, 3, padding='valid', activation=tf.nn.relu)(xp) xp = tf.keras.layers.MaxPooling2D()(xp) xp = tf.keras.layers.BatchNormalization()(xp) xp = tf.keras.layers.Conv2D(256, 3, padding='same', activation=tf.nn.relu)(xp) xp = tf.keras.layers.MaxPooling2D()(xp) xp = tf.keras.layers.BatchNormalization()(xp) xp = tf.keras.layers.Conv2D(394, 3, padding='same', activation=tf.nn.relu)(xp) xp = tf.keras.layers.MaxPooling2D()(xp) xp = tf.keras.layers.BatchNormalization()(xp) xp = tf.keras.layers.Conv2D(458, 3, padding='same', activation=tf.nn.relu)(xp) xp = tf.keras.layers.MaxPooling2D()(xp) xp = tf.keras.layers.BatchNormalization()(xp) # xp = tf.keras.layers.Conv2D(516, 3, padding='same', activation=tf.nn.relu)(xp) # xp = tf.keras.layers.Conv2D(516, 3, padding='same', activation=tf.nn.relu)(xp) # xp = tf.keras.layers.MaxPooling2D()(xp) # xp = tf.keras.layers.BatchNormalization()(xp) xp = tf.keras.layers.Dropout(0.25)(xp) xp = tf.keras.layers.Flatten()(xp) xp = tf.keras.layers.Dense(1024, activation=tf.nn.relu)(xp) xp = tf.keras.layers.BatchNormalization()(xp) xp = tf.keras.layers.Dropout(0.25)(xp) xp = tf.keras.layers.Dense(512, activation=tf.nn.relu)(xp) xp = tf.keras.layers.Dropout(0.25)(xp)
报错信息
Call arguments received: • inputs=tf.Tensor(shape=(None, 2, 2, 394), dtype=float32)
解决思路及方案
- 取消最后一次MaxPooling2D:当前特征图已经是2x2大小,再用默认的2x2池化窗口会把尺寸压缩到1x1,后续3x3卷积根本无法计算(哪怕padding=same也会触发尺寸不兼容)。直接删掉注释层里的
MaxPooling2D(),只保留两组Conv2D层即可。 - 改用1x1卷积核:把注释里的Conv2D层卷积核从3x3改成1x1,这样在2x2特征图上能正常运算,既保留了通道维度的变换,又不会因为卷积核过大导致尺寸问题。
- 减少前面的池化次数:前面已经做了7次MaxPooling(256→128→64→32→16→8→4→2),可以注释掉前面1-2次MaxPooling,让中间特征图尺寸更大,再添加注释的层就不会出现尺寸过小的问题。比如把某一轮的
MaxPooling2D()注释掉,特征图尺寸会翻倍。 - 修改池化窗口大小:把注释部分的
MaxPooling2D()改成MaxPooling2D(pool_size=(1,1)),这样不会改变特征图尺寸,只是做一个空的池化操作,避免尺寸过度压缩。
修改后的代码示例(取消最后一次MaxPooling)
xp = tf.keras.layers.Conv2D(458, 3, padding='same', activation=tf.nn.relu)(xp) xp = tf.keras.layers.MaxPooling2D()(xp) xp = tf.keras.layers.BatchNormalization()(xp) # 启用注释层,去掉MaxPooling2D xp = tf.keras.layers.Conv2D(516, 3, padding='same', activation=tf.nn.relu)(xp) xp = tf.keras.layers.Conv2D(516, 3, padding='same', activation=tf.nn.relu)(xp) # xp = tf.keras.layers.MaxPooling2D()(xp) xp = tf.keras.layers.BatchNormalization()(xp)
内容的提问来源于stack exchange,提问作者Tenks
相关产品推荐
相关产品推荐

