Search code examples
tensorflowkerasdeep-learningtransfer-learningvgg-net

Deep learning Vgg16 why is my model not fitting?


I am learning deep learning. I try transfer learning because I use vgg16 model. but, I face error: Shapes (None, 1) and (None, 2) are incompatible. I don't know why incompatible. help me. sorry, I can't speak English well. but I want to know why the error. My code. I already know that if I use sigmod(activation) I can classify data. but I want to classify three or more (dog, cat, horse, mouse.....) so I use softmax. help me.

ValueError: Shapes (None, 1) and (None, 2) are incompatible

Where is the problem?

    def save_bottlebeck_features():
    datagen = ImageDataGenerator(rescale=1. / 255)

    # build the VGG16 network
    model = applications.VGG16(include_top=False, weights='imagenet')

    generator = datagen.flow_from_directory(
        train_data_dir,
        target_size=(150, 150),
        batch_size=batch_size,
        class_mode='categorical',
        shuffle=False)

    bottleneck_features_train = model.predict_generator(
        generator)
    np.save('bottleneck_features_train.npy',bottleneck_features_train)

    generator = datagen.flow_from_directory(
        validation_data_dir,
        target_size=(150, 150),
        batch_size=batch_size,
        class_mode='categorical',
        shuffle=False)

    bottleneck_features_validation = model.predict_generator(
        generator)
  

    np.save('bottleneck_features_validation.npy',bottleneck_features_validation)
 

    def train_top_model():
    train_data = np.load('bottleneck_features_train.npy') 
    train_labels = np.array(
        [0] * 682 + [1] * 403) # dog: 682 cat : 403

    validation_data = np.load('bottleneck_features_validation.npy')
    validation_labels = np.array(
        [0] * 63 + [1] * 70 )

    model = Sequential()
    model.add(Flatten(input_shape=train_data.shape[1:]))
    model.add(Dense(256, activation='relu'))
    model.add(Dropout(0.5))
    model.add(Dense(2, activation='softmax'))
    model.summary()

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

    model.fit(train_data, train_labels,
              epochs=epochs,
              steps_per_epoch=1000 // batch_size,
              validation_data=(validation_data, validation_labels))
    model.save_weights(top_model_weights_path)

Solution

  • The problem in your case is that you created the ground truth in the form of [0]s and [1]s.

    However, you use a loss function which is categorical_crossentropy, that expects your input targets to be a 2-dimensional array in this case (n classes => n dimension), not a 1-dimensional one.

    Practically, your network expects as a ground truth a [0,1] if the picture belongs to cat and to [1,0] if the picture is a dog.

    However, you feed it only [0] and [1] instead of [0,1] or [1,0].

    The solution to your problem is:

    1. Either convert your ground truth labels to [0,1] and [1,0] (hint : use tf.keras.utils.to_categorical() or keras.utils.to_categorical() if you use plain keras.
    2. Use sparse_categorical_crossentropy as a loss function, which allows you to use plain integers e.g. 0,1,2,3 as labels.