Incompatible Dims with GlobalAveragePooling2D() - python

I'm trying to run a few different models, which ran fine until I added a GlobalAveragePooling2D() which now throws the following error:
ValueError: Input 0 is incompatible with layer flatten_105: expected min_ndim=3, found ndim=2
I feel it has something to do with a GlobalAveragePooling2D() layer not being compatible with a flatten() layer and my understand is lacking, but I'm not sure.
My code is below. Could anyone enlighten me on what they think is going on? It ran fine without the GlobalAveragePooling2D layer. I was hoping to experiment with it though.
dense_layers = [1,2,3]
layer_sizes = [32, 64, 128]
con_layers = [1,2,3]
con_layer_sizes = [32, 64, 128, 512]
for dense_layer in dense_layers:
for layer_size in layer_sizes:
for conv_layer in con_layers:
for con_layer_size in con_layer_sizes:
img_size = 125
batch_size = 16
K.input_shape = (img_size, img_size)
NAME = "{}-conv-{}-con_layer_sizes-{}-nodes-{}-dense-{}".format(conv_layer, con_layer_size, layer_size, dense_layer, int(time.time()))
print(NAME)
tensorboard = TensorBoard(log_dir= 'logs/{}'.format(NAME))
mcp = ModelCheckpoint(filepath='C:\\Users\\jordan.howell\\models\\'+NAME+'_model.h5',monitor="val_loss"
, save_best_only=True, save_weights_only=False)
reduce_learning_rate = ReduceLROnPlateau(monitor='val_loss', factor=0.3,patience=2,cooldown=2
, min_lr=0.00001, verbose=1)
#start model build
model = Sequential()
model.add(Conv2D(con_layer_size, (3, 3), activation="relu", padding = 'same', input_shape=input_shape))
model.add(MaxPooling2D(pool_size = (2, 2)))
model.add(BatchNormalization())
model.add(Dropout(0.15))
for l in range(conv_layer-1):
#Convolution
model.add(Conv2D(con_layer_size, (3, 3), activation="relu", padding = 'same'))
model.add(MaxPooling2D(pool_size = (2, 2)))
model.add(BatchNormalization())
model.add(Dropout(0.15))
model.add(GlobalAveragePooling2D())
# Flatten the layer
model.add(Flatten())
for l in range(dense_layer):
model.add(Dense(layer_size, activation = 'relu'))
model.add(Dense(activation = 'sigmoid', units = 1))
model.compile(loss ='binary_crossentropy', optimizer = 'adam'
, metrics=[km.binary_precision(), km.binary_recall()])
#generators = Generators(TRAIN_DATA_DIR, VALIDATION_DATA_DIR, TEST_DATA_DIR)
#train_generator = generators.train_generator(150, batch_size=32)
#validation_generator = generators.validation_generator(150, batch_size=16)
model.fit_generator(train_generator, steps_per_epoch=5216 // batch_size
,validation_data=validation_generator, validation_steps=1
, epochs = 50, callbacks = [reduce_learning_rate, tensorboard, mcp])

From Keras docs, GlobalAveragePooling2D input shape is 4D tensor, output shape is 2D tensor. In this case, Flatten is redundant.

Related

ValueError: Input 0 of layer sequential_40 is incompatible with the layer

I'm modifying an old code, by adding attention layer to a model. But I'm not able to figure out how to stack the layers with correct input size.
The actual input data would be (200,189,1).
//I'm trying something like this
def mocap_model(optimizer='SGD'):
model = Sequential()
model.add(Conv2D(32, 3, strides=(2, 2), padding ='same', input_shape=(200, 189, 1)))
model.add(Dropout(0.2))
model.add(Activation('relu'))
model.add(Conv2D(64, 3, strides=(2, 2), padding ='same'))
model.add(Dropout(0.2))
model.add(Activation('relu'))
model.add(Conv2D(64, 3, strides=(2, 2), padding ='same'))
model.add(Dropout(0.2))
model.add(Activation('relu'))
model.add(Conv2D(128, 3, strides=(2, 2), padding ='same'))
model.add(Dropout(0.2))
model.add(Flatten())
return model
cnn = mocap_model()
main_input = Input(shape=(200, 189, 1))
rnn = Sequential()
rnn = LSTM(256, return_sequences=True, input_shape=(200,189))
model = TimeDistributed(cnn)(main_input)
model = rnn(model)
att_in=LSTM(256,return_sequences=True,dropout=0.3,recurrent_dropout=0.2)(model)
att_out=attention()(att_in)
output3=Dense(256,activation='relu',trainable=True)(att_out)
output4=Dense(4,activation='softmax',trainable=True)(output3)
model=Model(main_input,output4)
model.compile(loss='categorical_crossentropy', optimizer='adam', metrics=['accuracy'])
model.summary()
But I get this error:
----> 8 model = TimeDistributed(cnn)(main_input)
ValueError: Input 0 of layer sequential_40 is incompatible with the layer: : expected min_ndim=4, found ndim=3. Full shape received: (None, 189, 1)
Problem with Input shape. tf.keras.layers.TimeDistributed expects batch size as input. Expects inputs: Input tensor of shape (batch, time, ...).
In the main_input add batch_size
main_input = Input(shape=(10, 200, 189, 1))
Working sample code
import tensorflow as tf
cnn = tf.keras.Sequential()
cnn.add(tf.keras.layers.Conv2D(64, 1, 1, input_shape=(200, 189, 1)))
cnn.add(tf.keras.layers.Flatten())
cnn.output_shape
main_input = tf.keras.Input(shape=(10, 200, 189, 1))
outputs = tf.keras.layers.TimeDistributed(cnn)(main_input)
outputs.shape
Output
TensorShape([None, 10, 2419200])

ValueError: Input 0 of layer sequential_1 is incompatible with the layer: : expected min_ndim=4, found ndim=3. Full shape received: [None, 256, 256]

Everything is okay until I convert my image to grayscale. So the rgb's shape is (256, 256, 3) but grayscale has (256, 256). When I feed it, I get that error.
network = Sequential()
network.add(Convolution2D(32, kernel_size=(3, 3),strides=1,activation='relu',input_shape=(256, 256)))
network.add(MaxPooling2D((2, 2)))
# network.add(Convolution2D(32, kernel_size=(3, 3), strides=1, activation='relu'))
# network.add(MaxPooling2D((2, 2)))
network.add(Convolution2D(64, kernel_size=(3, 3), strides=1, activation='relu'))
network.add(MaxPooling2D((2, 2)))
# network.add(Convolution2D(64, kernel_size=(3, 3), strides=1, activation='relu'))
# network.add(MaxPooling2D((2, 2)))
network.add(Convolution2D(128, kernel_size=(3, 3), strides=1, activation='relu'))
network.add(MaxPooling2D((2, 2)))
# network.add(Convolution2D(128, kernel_size=(3, 3), strides=1, activation='relu'))
# network.add(MaxPooling2D((2, 2)))
network.add(Flatten())
network.add(Dense(256, activation = 'relu'))
network.add(Dense(2, activation = 'softmax'))
checkpoint_path = os.path.join("/---------/grayscale", "weights.best.hdf5")
checkpoint = ModelCheckpoint(checkpoint_path, monitor='val_accuracy', verbose=1, save_best_only=True, mode='max')
es = EarlyStopping(monitor='val_loss', mode='min', verbose=1, patience=10)
callbacks_list = [checkpoint, es]
network.compile(optimizer = 'adam', loss = 'categorical_crossentropy', metrics = ['accuracy'])
You have to feed images of shape 256x256x1 in your network.
To convert your initial x_train into your new X_train:
X_train=np.reshape(x_train,(x_train.shape[0], x_train.shape[1],x_train.shape[2],1))
and finally change your input_shape from input_shape=(256,256) to input_shape=(256,256,1)

Error when checking input: expected input to have 3 dimensions, but got array with shape (50, 1)

This is killing me. Why is it saying input array was (50,1) when its clearly (50,629,160)? I initially thought the Conv1D layers were giving me the trouble but it appears it's in the input layer, right?
# keras.__version__ = 2.2.4
# X_train.shape = (50,629,160), X_train[0].shape = (629,160)
# y_train.shape = (50,)
dim = X_train[0].shape
input1 = Input(shape=dim,name='input_1')
conv1 = Conv1D(filters=32, kernel_size=2, strides=1, activation='relu', name='conv1', input_shape=dim)(input1)
maxpool1 = MaxPool1D(pool_size=2, name='maxpool1')(conv1)
conv2 = Conv1D(filters=64, kernel_size=2, strides=1, activation='relu', name='conv2')(maxpool1)
maxpool2 = MaxPool1D(pool_size=2, name='maxpool2')(conv2)
conv3 = Conv1D(filters=128, kernel_size=2, strides=1, activation='relu', name='conv3')(maxpool2)
maxpool3 = MaxPool1D(pool_size=2, name='maxpool3')(conv3)
flat1 = Flatten(name='flat1')(maxpool3)
dense1 = Dense(256, activation='relu', name='dense1')(flat1)
dense2 = Dense(128, activation='relu', name='dense2')(dense1)
output1 = Dense(1, activation='sigmoid', name='output')(dense2)
model = Model(inputs=input1,outputs=output1)
model.compile(loss='binary_crossentropy', optimizer='adam', metrics=['accuracy'])
model.fit(x=X_train,y=y_train, epochs=30, validation_split=0.1, batch_size=32)
And the error code:
Error when checking input: expected input_1 to have 3 dimensions, but got array with shape (50, 1)

Dimension error when using predict method on an image in a CNN model

I am trying to predict on a single image using Keras (2.2.4) and TensorFlow (1.9.0) as the backend:
def enigne(data):
img=data
image_shape=img.shape
num_train_samples = 4206
num_val_samples = 916
train_batch_size = 10
val_batch_size = 10
IMAGE_SIZE = 64
IMAGE_CHANNELS = 3
kernel_size = (3, 3)
pool_size = (2, 2)
first_filters = 32
second_filters = 128
image_resize=cv.resize(img,(64,64))
# Loading the model
model = Sequential()
model.add(Conv2D(first_filters, kernel_size, activation='relu', input_shape=(64, 64, 3)))
model.add(Conv2D(first_filters, kernel_size, activation='relu', kernel_regularizer=regularizers.l2(0.001))
model.add(Conv2D(second_filters, kernel_size, activation='relu', kernel_regularizer=regularizers.l2(0.001)))
model.add(MaxPooling2D(pool_size=pool_size))
model.add(Dropout(dropout_conv))
model.add(Flatten())
model.add(Dense(256, activation="relu"))
model.add(Dense(1, activation="sigmoid"))
model.compile(Adam(lr=0.0001), loss='binary_crossentropy',
metrics=['accuracy'])
datagen = ImageDataGenerator(rescale=1.0 / 255)
model.load_weights('stableweights.h5')
y_pred_keras = model.predict_proba(image_resize)
p = []
for i in y_pred_keras:
for k in i:
if k <= 0.421:
p.append(0)
else:
p.append(1)
return p
I am getting an error like this:
ValueError: Error when checking input: expected conv2d_input to have 4 dimensions, but got array with shape (64, 64, 3)
How can I convert to the image to have proper dimensions to feed it into the Keras model?
Keras models expect batch of samples as input. Therefore, you need to have the first axis as the batch axis:
import numpy as np
image_resize = np.expand_dims(image_resize, axis=0) # shape would be: (1, 64, 64, 3)

Keras CNN get output from the Convolutional steps

I am beginning to build CNN models using Keras.
I have built a CNN with a fairly accurate results using the following architecture.
classifier = Sequential()
classifier.add(Convolution2D(32, (3,3), input_shape = (64, 64, 3), activation='relu'))
classifier.add(MaxPool2D(pool_size = (2,2)))
classifier.add(Convolution2D(32, (3,3), activation='relu'))
classifier.add(MaxPool2D(pool_size = (2,2)))
classifier.add(Convolution2D(32, (3,3), activation='relu'))
classifier.add(MaxPool2D(pool_size = (2,2)))
classifier.add(Convolution2D(32, (3,3), activation='relu'))
classifier.add(MaxPool2D(pool_size = (2,2)))
classifier.add(Flatten())
classifier.add(Dense(units=128, activation='relu'))
classifier.add(Dropout(rate = 0.25))
classifier.add(Dense(units=128, activation='relu'))
classifier.add(Dropout(rate = 0.25))
classifier.add(Dense(units=1, activation='sigmoid'))
classifier.compile(optimizer = 'sgd', loss = 'binary_crossentropy', metrics=['accuracy'])
What I want to do is to run my images through the model, but only the convolutional steps. I am interested in the output of the Flattening process (i.e. get the features from the convolutional steps).
Can someone help me how I can get it in Keras?
Thanks in advance
Here is one solution. If you are interested in the output of layer 'max_pooling2d_4' (You can get the layer name by classifier.summary(), but I suggest you to put names for each layer by e.g. classifier.add(MaxPool2D(pool_size=(2,2), name='pool1'))):
layer_dict = dict([(layer.name, layer) for layer in classifier.layers])
# input tensor
input_tensor = classifier.input
# output tensor of the given layer
layer_output = layer_dict['max_pooling2d_4'].output
# get the output with respect to the input
func = K.function([input_tensor], [layer_output])
# test image: [64, 64, 3]
image = np.ones((64,64,3))
# get activation for the test image
activation = func([image[np.newaxis, :, :, :]])

Categories

Resources