简体   繁体   中英

Negative dimension size caused by subtracting 5 from 2 for 'conv2d_4/convolution' (op: 'Conv2D') with input shapes: [?,5,2,64], [5,5,64,64]

My input shape is (20, 10, 1)

my non working model looks like this:

num_classes = 2

model.add(Conv2D(32, (5, 5),
          padding='same',
          data_format='channels_last',
          input_shape=input_shape))
model.add(BatchNormalization())
model.add(Activation('relu'))
model.add(Conv2D(32, (5, 5)))
model.add(BatchNormalization())
model.add(Activation('relu'))
model.add(MaxPooling2D(pool_size=(3, 3)))
model.add(Dropout(0.25))

model.add(Conv2D(64, (5, 5), padding='same'))
model.add(BatchNormalization())
model.add(Activation('relu'))
model.add(Conv2D(64, (5, 5)))
model.add(Activation('relu'))
model.add(MaxPooling2D(pool_size=(3, 3)))
model.add(Dropout(0.25))

model.add(Flatten())
model.add(Dense(512))
model.add(Activation('relu'))
model.add(Dropout(0.5))

model.add(Dense(num_classes))
model.add(Activation('softmax'))

self.model = model

Which gives me the following error: Negative dimension size caused by subtracting 5 from 2 for 'conv2d_4/convolution' (op: 'Conv2D') with input shapes: [?,5,2,64], [5,5,64,64].

However the error disappears if I did one of two things:
1. remove all three model.add(Conv2D(64, (5, 5)))
or
2. Change ^ three Conv2D layers from (5,5)to (3,3) and change all
pool_size(2,2)

I understand that the dimensions at end of 4th layer is causing the trouble.

What should I do to make ^ model work in the present state?

Basically I want to compare performance of this model (filter size 5x5 with pool_size(3,3) with another model that uses a 3x3 filter with pool_size(2,2). Thanks

The problems is that the output of layer conv2d_4 became zero or negative. To solve this problem, you must design the network so that the input data would not be highly downsampled.

Here are some possible solutions:

  • Use less layers. Especially remove a max-pooling layer, which downsamples a lot (by one third under this setting).
  • Use smaller max-pooling, eg pool_size=(2, 2) , which results in downsampling by a half.
  • Use "same padding" for Conv2D layer, which results in no downsampling during the convolution step.

Change the strides values to 1,1 as shown below. That resolves my problem

model.add(MaxPooling2D(pool_size=(2, 2),strides=(1,1),padding='same',name = 'pool2'))

The full layer diagram for my code is

def getModel():

    optim = Adam(lr= LR, decay=0)

    model =Sequential()
    model.add(Conv2D(32,(3,3),activation = 'relu',input_shape =[28,28,1],kernel_initializer='he_uniform',
                                kernel_regularizer=regularizers.l2(l2_labmda),data_format='channels_last',name='1st'))
    model.add(BatchNormalization())
    model.add(MaxPooling2D(pool_size=(2, 2),strides=(1,1),padding='same',name = 'pool1'))
    model.add(Dropout(0.2,name='2'))


    model.add(Conv2D(64,(3,3),activation = 'relu',kernel_initializer='he_uniform',
                                kernel_regularizer=regularizers.l2(l2_labmda),name='3'))
    model.add(BatchNormalization())
    model.add(MaxPooling2D(pool_size=(2, 2),strides=(1,1),padding='same',name = 'pool2'))
    model.add(Dropout(0.2,name='4'))

    model.add(Conv2D(64,(5,5),activation = 'relu',kernel_initializer='he_uniform',
                                kernel_regularizer=regularizers.l2(l2_labmda),name='5'))

    model.add(BatchNormalization())
    model.add(MaxPooling2D(pool_size=(2, 2),strides=(1,1),padding='same',name = 'pool3'))

    model.add(Dropout(0.2, name='6'))

# =============================================================================
    model.add(Conv2D(128,(3,3),activation = 'relu',kernel_initializer='he_uniform',
                                kernel_regularizer=regularizers.l2(l2_labmda),name='7'))
    model.add(BatchNormalization())
    model.add(MaxPooling2D(pool_size=(2, 2),strides=(2,2),padding='same',name = 'pool5'))
    model.add(Dropout(0.2,name='8'))
#    
# =============================================================================
    model.add(Conv2D(128,(3,3),activation = 'relu',kernel_initializer='he_uniform',
                                kernel_regularizer=regularizers.l2(l2_labmda),name='9'))
    model.add(BatchNormalization())
    model.add(MaxPooling2D(pool_size=(2, 2),strides=(2,2),padding='same',name = 'pool6'))

    model.add(Dropout(0.2))


    model.add(Flatten(name='12'))

    model.add(Dense(512,activation='relu',kernel_initializer='he_uniform',
                                kernel_regularizer=regularizers.l2(l2_labmda), name='13'))
    model.add(Dropout(0.2,name='14'))


    model.add(Dense(512,activation='relu',kernel_initializer='he_uniform',
                                kernel_regularizer=regularizers.l2(l2_labmda),name='15'))
    model.add(Dropout(0.2,name='16'))

    model.add(Dense(40,activation='softmax',kernel_initializer='glorot_uniform    ',
                                kernel_regularizer=regularizers.l2(l2_labmda),name='17'))

    model.compile(optimizer=optim,loss='categorical_crossentropy',metrics=['accuracy'])
    print(model.summary())

    return model

model = getModel()

Max pooling reduces the width and height of your output, for example if you apply pool_size = (4, 4) and a stride of 4 to an input of shape (20, 20, 1), then your output shape would be (5, 5, 1) right?, but what if you input the same pool_size = (4, 4) and a stride of 4' to an input of (10, 10, 1), then you see that that doesn't work because your output shape would now have to be (-10, -10, 1) which doesn't make any sense, and causes an error. So consider reducing the pool_sizes of your MaxPooling2D so that the input to that layer doesn't produce negative output dimensions.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM