import pandas as pd
import numpy as np
import tensorflow as tf
from tensorflow.keras.models import Sequential
from tensorflow.keras.layers import Dropout, Dense, MaxPool2D, Conv2D, BatchNormalization, Flatten, Activation
from tensorflow.keras.callbacks import TensorBoard
from tensorflow.keras.utils import to_categorical
import os
import time
import matplotlib.pyplot as plt
import seaborn
import pickle
This "icml_face_data.csv" contain training,validation and test data of facial expression
df = pd.read_csv("icml_face_data.csv")
def prepare_data(data):
"""
This function separates array and label(target)
:param data: data( it can be train,test,val)
:return: image_array and labels(target)
"""
image_array = np.zeros(shape=(len(data),48,48))
image_label = np.array(data["emotion"])
for i, row in enumerate(data.index):
image = np.fromstring(data.loc[row, " pixels"], dtype=int, sep=" ")
image = np.reshape(image, (48, 48))
image_array[i] = image
return image_array, image_label
training_data, training_label = prepare_data(df[df[" Usage"]=="Training"])
validation_data, validation_label = prepare_data(df[df[" Usage"]=="PublicTest"])
test_data, test_label = prepare_data(df[df[" Usage"]=="PrivateTest"])
train_data = training_data.reshape((training_data.shape[0],48,48,1))
train_data = train_data.astype("float32")/255
valid_data = validation_data.reshape((validation_data.shape[0],48,48,1))
valid_data = valid_data.astype("float32")/255
test_data = test_data.reshape((test_data.shape[0],48,48,1))
test_data = test_data.astype("float32")/255
training_label = to_categorical(training_label)
validation_label = to_categorical(validation_label)
test_label = to_categorical(test_label)
i was training convolutional model using deferent combination of dense layers,convolutional layers, and layers size when i trained on combination dense_layers = [1,2,3],layer_sizes = [32,64,128],conv_layers = [1,2,3]
It worked fine with no error and when i tried dense_layers = [1],layer_sizes = [32],conv_layers = [3,4] It still worked fine.
But when i used dense_layers = [1],layer_sizes = [32],conv_layers = [5] this combination it raise error
dense_layers = [1]
layer_sizes=[32]
conv_layers = [5]
for dense_layer in dense_layers:
for layer_size in layer_sizes:
for conv_layer in conv_layers:
NAME = f"{conv_layer}-conv-{layer_size}-layer-{dense_layer}-Dense-{int(time.time())}"
tensorboard = TensorBoard(log_dir=f"logs/{NAME}")
model = Sequential()
model.add(Conv2D(layer_size, (3,3),activation="relu",input_shape=(48,48,1)))
model.add(MaxPool2D((2,2)))
model.add(Dropout(0.2))
for _ in range(conv_layer-1):
model.add(Conv2D(layer_size, (3,3),activation="relu"))
model.add(MaxPool2D((2,2)))
model.add(Dropout(0.2))
model.add(Flatten())
for _ in range(dense_layer):
model.add(Dense(layer_size, activation="relu"))
model.add(Dropout(0.2))
model.add(Dense(7, activation="softmax"))
model.compile(loss='categorical_crossentropy',optimizer=tf.keras.optimizers.Adam(lr=1e-3),metrics=["accuracy"])
model.fit(train_data, training_label,
validation_data=(valid_data,validation_label),
epochs=20,
batch_size=32,
callbacks=[tensorboard])
error:
---------------------------------------------------------------------------
InvalidArgumentError Traceback (most recent call last)
/usr/local/lib/python3.7/dist-packages/tensorflow/python/framework/ops.py in _create_c_op(graph, node_def, inputs, control_inputs, op_def)
1879 try:
-> 1880 c_op = pywrap_tf_session.TF_FinishOperation(op_desc)
1881 except errors.InvalidArgumentError as e:
InvalidArgumentError: Negative dimension size caused by subtracting 3 from 1 for '{{node conv2d_28/Conv2D}} = Conv2D[T=DT_FLOAT, data_format="NHWC", dilations=[1, 1, 1, 1], explicit_paddings=[], padding="VALID", strides=[1, 1, 1, 1], use_cudnn_on_gpu=true](Placeholder, conv2d_28/Conv2D/ReadVariableOp)' with input shapes: [?,1,1,32], [3,3,32,32].
During handling of the above exception, another exception occurred:
ValueError Traceback (most recent call last)
17 frames
/usr/local/lib/python3.7/dist-packages/tensorflow/python/framework/ops.py in _create_c_op(graph, node_def, inputs, control_inputs, op_def)
1881 except errors.InvalidArgumentError as e:
1882 # Convert to ValueError for backwards compatibility.
-> 1883 raise ValueError(str(e))
1884
1885 return c_op
ValueError: Negative dimension size caused by subtracting 3 from 1 for '{{node conv2d_28/Conv2D}} = Conv2D[T=DT_FLOAT, data_format="NHWC", dilations=[1, 1, 1, 1], explicit_paddings=[], padding="VALID", strides=[1, 1, 1, 1], use_cudnn_on_gpu=true](Placeholder, conv2d_28/Conv2D/ReadVariableOp)' with input shapes: [?,1,1,32], [3,3,32,32].
Why this code raising error for that combination only i used google colab (runtime type = "gpu") i tried restart runtime and run all but it just raise error on that combination only i don't know why its happening? please help
CodePudding user response:
Your problem probably is, that the size of your feature maps becomes smaller and smaller with every additional layer due to your use of strides in your convolutional and max pooling layers. Your original input has shape (48, 48, 1), so if you use a conv layer on it (in your case without strides, but with padding="valid", which is the standard option) then your output will have shape (46, 46, x). The same is true for the max pooling layers, but the effect is even worse because you did not specify a stride, and by default tensorflow assumes that the stride is supposed to be equal to your kernel size. This means that the output of your max pooling layer for an input with shape (48, 48, 1) would be just (24, 24, 1).
So as a summary: With every additional layer you reduce the size of your feature maps, and at some point they will be smaller than the kernel size of your layer, which results in the error.
I assume that you want your image shape to stay the same all the time. If this is the case, then you should alter your code in the following ways:
- add padding = "same" to both your max pooling and your convolutional layers.
- add strides = (1, 1) to your max pooling layers.
For most convolutional networks, it often makes sense for the feature map to become smaller and smaller while passing through the network. So you should consider implementing my suggestions only for some layers.
CodePudding user response:
Max-pooling is reducing the size of the input to the next convolutional layer in your for-loop leading to your error. Running tf.print(model.summary)
in your for loop as shown below will reveal to you how your output shape changes after each max pooling operation.
for _ in range(conv_layer-1):
tf.print(model.summary)
model.add(Conv2D(layer_size, (3,3),activation="relu"))
model.add(MaxPool2D((2,2)))
model.add(Dropout(0.2))
For example, the output of the third convolutional layer in the loop has the following shape: (None, 2, 2, 32)
and after the max-pooling operation: (None, 1, 1, 32)
. You can clearly see that feeding this output into another convolutional layer will fail.