1

New to Keras, trying to reimplement this following binary image classification example from: https://blog.keras.io/building-powerful-image-classification-models-using-very-little-data.html

It works for binary classification for me. Rebuilding it for a 3-class classification I am getting the following dimensions mismatch error:

     60         epochs=50,
     61         validation_data=validation_generator,
---> 62         validation_steps=250 // batch_size)
ValueError: Error when checking target: expected activation_50 to have shape (None, 1) but got array with shape (16, 3)

This is my current implementation:

from keras.preprocessing.image import ImageDataGenerator
from keras.models import Sequential
from keras.layers import Conv2D, MaxPooling2D
from keras.layers import Activation, Dropout, Flatten, Dense
from keras import backend as K
K.set_image_dim_ordering('th')
batch_size = 16

# this is the augmentation configuration we will use for training
train_datagen = ImageDataGenerator(
        rescale=1./255,
        shear_range=0.2,
        zoom_range=0.2,
        horizontal_flip=True)

# this is the augmentation configuration we will use for testing:
# only rescaling
test_datagen = ImageDataGenerator(rescale=1./255)

# this is a generator that will read pictures found in
# subfolers of 'data/train', and indefinitely generate
# batches of augmented image data
train_generator = train_datagen.flow_from_directory(
        'F://train_data//',  # this is the target directory
        target_size=(150, 150),  # all images will be resized to 150x150
        batch_size=batch_size,
        class_mode='categorical')  # since we use binary_crossentropy loss, we need binary labels

# this is a similar generator, for validation data
validation_generator = test_datagen.flow_from_directory(
        'F://validation_data//',
        target_size=(150, 150),
        batch_size=batch_size,
        class_mode='categorical')

model = Sequential()

model.add(Conv2D(32, (3, 3), input_shape=(3, 150, 150)))
model.add(Activation('relu'))
model.add(MaxPooling2D(pool_size=(2, 2), data_format="channels_first"))

model.add(Conv2D(32, (3, 3)))
model.add(Activation('relu'))
model.add(MaxPooling2D(pool_size=(2, 2), data_format="channels_first"))

model.add(Conv2D(64, (3, 3)))
model.add(Activation('relu'))
model.add(MaxPooling2D(pool_size=(2, 2), data_format="channels_first"))

model.add(Flatten())  # this converts our 3D feature maps to 1D feature vectors
model.add(Dense(64))
model.add(Activation('relu'))
model.add(Dropout(0.5))
model.add(Dense(1))
model.add(Activation('softmax')) # instead of sigmoid

model.compile(loss='mean_squared_error',
              optimizer='adam',
              metrics=['accuracy'])

# another loss: sparse_categorical_crossentropy

model.fit_generator(
        train_generator,
        steps_per_epoch=1800 // batch_size,
        epochs=50,
        validation_data=validation_generator,
        validation_steps=250 // batch_size)

So far I have changed the activation function of the output layer from sigmoid to softmax. Changed class_mode from binary to categorical. Can't seem to find the problem.

Also, I am aware of similar questions on StackOverflow: Multi-Output Multi-Class Keras Model

Train multi-class image classifier in Keras

Multi-class classification using keras

But none of the solutions helped me.

Ivan Bilan
  • 2,379
  • 5
  • 38
  • 58

1 Answers1

4

You need to change the final Dense layer to model.add(Dense(3)). Softmax activation expects the units in the Dense layer to match the number of classes.

Also, if you are going to use loss='sparse_categorical_crossentropy', remember to change class_mode into 'sparse'. Your current setting, class_mode='categorical', should be used with loss='categorical_crossentropy'.

Yu-Yang
  • 14,539
  • 2
  • 55
  • 62