Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

ValueError: Error when checking target: expected dense_2 to have shape (None, 2) but got array with shape (1, 1)

Hi I am new in Keras with back-end tensorflow. I have build my training and validation set of images of two possible classes; my network has to end with two classes yes or not. I have used ImageDatagenerator to read the images from the folders and prepare the training and the validation set. At the end I get the issue described in the Title. My guess is that the ImageDatagenerator is not preparing the data as I would like; Any body can explain to me how to solve it, here is the code (THANKS):

# Data Preparation
# dimensions of our images.
img_width, img_height = 256, 256

#top_model_weights_path = 'bottleneck_fc_model.h5'
train_data_dir = 'data/train'
validation_data_dir = 'data/validation'
nb_train_samples = 2
nb_validation_samples = 2
epochs = 50
batch_size = 1
num_classes = 2

# prepare data augmentation configuration
train_datagen = ImageDataGenerator(
                                   rescale=1. / 255,
                                   shear_range=0.2,
                                   zoom_range=0.2,
                                   data_format=K.image_data_format(),
                                   horizontal_flip=True)

test_datagen = ImageDataGenerator(
                                  rescale=1. / 255,
                                  data_format=K.image_data_format())

train_generator = train_datagen.flow_from_directory(
                                                    train_data_dir,
                                                    target_size=(img_height, img_width),
                                                    batch_size=batch_size,
                                                    class_mode='binary')

validation_generator = test_datagen.flow_from_directory(
                                                        validation_data_dir,
                                                        target_size=(img_height, img_width),
                                                        batch_size=batch_size,
                                                        class_mode='binary')

# create the CNN model
model = Sequential()
model.add(Conv2D(24, kernel_size=(20, 20), strides=(2,2), padding='valid', activation='relu', input_shape=(256,256,3)))

model.add(MaxPooling2D(pool_size=(7, 7), strides=(2,2), padding='valid'))

# Avoiding overfitting
model.add(Dropout(0.5))
model.add(Flatten())
model.add(Dense(64, activation='relu'))

# Avoiding overfitting
model.add(Dropout(0.5))
model.add(Dense(num_classes, activation='softmax'))

print(model.summary())

# Compile model
sgd = optimizers.SGD(lr=0.01, decay=1e-6, momentum=0.9, nesterov=True)
model.compile(loss='mean_squared_error', optimizer='sgd', metrics=['accuracy'])

# Fit the model
model.fit_generator(
                    train_generator,
                    steps_per_epoch=nb_train_samples // batch_size,
                    epochs=epochs,
                    validation_data=validation_generator,
                    validation_steps=nb_validation_samples // batch_size,
                    verbose=0)

# Save the weights
model.save_weights('first_try.h5')
like image 621
user8071890 Avatar asked May 26 '17 19:05

user8071890


2 Answers

Specifically for "two classes", there are two ways of doing it:

  • One result, 0 or 1, yes or no.
  • Two results, being one the probability of class A and the other the probability of class B.

Each one requires a different model output:

  • 1D output, with Dense(1,....)
  • 2D output, with Dense(2,....)

You seem to be in the first case, so, change your last layer.

What does that error mean?

Your model outputs things with shape (BatchSize, 2), but your class labels have shape (BatchSize,1).

like image 198
Daniel Möller Avatar answered Oct 18 '22 06:10

Daniel Möller


If you need a single output that predicts either 0 or 1 then just change your last layer to

model.add(Dense(1, activation='softmax'))

However, if you need two outputs per each of your classes then use categorical class mode for your train and validation generators, namely,

train_generator = train_datagen.flow_from_directory(
                                                    train_data_dir,
                                                    target_size=(img_height, img_width),
                                                    batch_size=batch_size,
                                                    class_mode='categorical')


validation_generator = test_datagen.flow_from_directory(
                                                        validation_data_dir,
                                                        target_size=(img_height, img_width),
                                                        batch_size=batch_size,
                                                        class_mode='categorical')
<...>
model.add(Dense(2, activation='softmax'))

To summarize:

  • "binary" class mode represents 1D binary labels
  • "categorical" represents 2D one-hot encoded labels
like image 23
Michael Glazunov Avatar answered Oct 18 '22 04:10

Michael Glazunov