2D CNN & MaxPool2D dimension issue

Viewed 101

I'm trying to build up a 2D CNN model with MaxPooling2D, however I am running into issues with the dimensions. I believe I get the idea of what MaxPool2D is doing (shrinking the image based on the max value in the pool_size) but I'm not understanding the dimension issue, and I'm hoping someone can help me see the light.

So my input data is in the order of batch_size, rows, columns, depth - (14,000, 96, 96, 1) Since the data is scaled between 0 and 1, it's essentially a black and white image. I am feeding that into a Conv2D layer:

Conv2D(filters=32, kernels_size=(3,3), activation='relu', padding='same', input_shape=(96,96,1)),

I can feed this layer into another Conv2D layer, and no problems. But I'm trying to place a MaxPool2D layer between those Conv2D layers. When I try to add that however:

MaxPool2D(pool_size=(2,2))

I end up getting

"ValueError:  Dimensions must be equal, but are 48 and 96 for '{{node mean_squared_error/SquaredDifference}} = SquaredDifference[T=DT_FLOAT](sequential/conf2d_2/Relu, IteratorGetNext:1)' with input shapes: [?,48,48,1],[?,96,96,1]."

Is there a rule for how you should set up padding? (both in the conv2d layer as well as the MaxPool2D layer) It doesn't seem to matter what I set the padding to for the MaxPooling2D layer (same or valid) I always get the dimensions error.

Every tutorial/how-to I've looked at seems to just glance over any requirements and explain things like it should be common knowledge. I get that the pooling set to (2,2) should cut the image in half, hence the 48x48 output shape. And I get that the input is 96,96,32 because I set my filters to 32 in the previous Conv2D layer. My understanding is the MaxPooling is just shrinking the dataset by looking at the max value in the 2x2 sub-region, so I would expect the 48x48x32 dimension, so where is the dimension issue coming from that ties back to the original 96 value? Is it because it's shrinking the training set but not the other set of data that it's trying to compare to? Do I need to do a batch normalization? None of the examples I try to follow never seem to do that though.

Hopefully someone can shed some light on this for me - I'm a total noob. And if anyone has some good resources regarding implementing 2D CNN's and the approach to building/optimizing your model, I'd love to see it. I feel like I'm doing a lot of wandering around in the dark. Thanks!

Model Summary:
 Model: "sequential"
_________________________________________________________________
Layer (type)                 Output Shape              Param #  
=================================================================
conv2d (Conv2D)              (None, 96, 96, 32)        320      
_________________________________________________________________
max_pooling2d (MaxPooling2D) (None, 48, 48, 32)        0        
_________________________________________________________________
conv2d_1 (Conv2D)            (None, 48, 48, 64)        18496    
_________________________________________________________________
conv2d_2 (Conv2D)            (None, 48, 48, 1)         577      
=================================================================
Total params: 19,393
Trainable params: 19,393
Non-trainable params: 0
_________________________________________________________________ 
model = Sequential([
Conv2D(filters=32, kernel_size=(3,3), activation='relu', padding = 'same', input_shape=(96,96,1)),
MaxPool2D(pool_size=(2,2)),
Conv2D(filters=64, kernel_size=(3,3), activation='relu', padding = 'same'),
Conv2D(filters=1, kernel_size=(3,3), activation='relu', padding='same')
])
3 Answers

There is no error in the definition of the model and it should compile fine.

To answer all your questions simply: YES, dimensions matching takes the most time in implementation and no amount of reading can make you a master at it.

Refer the raw sources along with critical thinking as your starting point: https://www.tensorflow.org/api_docs/python/tf

EDIT: (adding clarity and sample code)

The output that is compared against should also have (height, width) as (48,48). If it doesn't, then model.fit() would error out.

A sample program for reference:

import tensorflow as tf
from tensorflow import keras
from keras import Sequential, layers
from keras.layers import Conv2D, MaxPool2D

x = tf.ones((1400, 96, 96, 1))

model = Sequential([
Conv2D(filters=32, kernel_size=(3,3), activation='relu', padding = 'same', input_shape=(96,96,1)),
MaxPool2D(pool_size=(2,2), padding='valid'),
Conv2D(filters=32, kernel_size=(3,3), activation='relu', padding = 'same'),
Conv2D(filters=1, kernel_size=(3,3), activation='relu', padding='same'), 
])

keras.utils.plot_model(model)

model.summary()

y = model(x)
model.compile(optimizer='adam', 
    loss='mean_absolute_error', 
    metrics=['mean_absolute_error'])

y = tf.ones((1400, 48, 48, 1))

model.fit(x, y, epochs=50)

A maxpool layer reduces the inputs' spatial dimensions by a factor of the pool_size.

The error was caused by the mismatch of prediction and target size when computing the MSE loss. The model output was 48x48x1 due to the MaxPool2D, but the target was still the original 96x96x1 size. In order to fix the issue an upsample layer was added to bring it back to 96x96.

model = Sequential([
Conv2D(filters=32, kernel_size=(3,3), activation='relu', padding = 'same', input_shape=(96,96,1)),
MaxPool2D(pool_size=(2,2), padding='valid'),
Conv2D(filters=32, kernel_size=(3,3), activation='relu', padding = 'same'),
UpSampling2D(size=(2,2), data_format=None, interpolation='bilinear'),
Conv2D(filters=1, kernel_size=(3,3), activation='relu', padding='same'), 
])

you just change the model to this below code:


model = Sequential([
Conv2D(filters=32, kernel_size=(3,3), activation='relu', padding= 'same', input_shape=(96,96,1)),
MaxPool2D(pool_size=(2,2), padding='valid'),
Conv2D(filters=32, kernel_size=(3,3), activation='relu', padding= 'same'),
Conv2D(filters=1, kernel_size=(3,3), activation='relu', padding='same'), 
])

Related