简体   繁体   中英

Keras model giving constantly same output class?

I've been trying to build a keras model following the "cats vs dogs" tutorials but unfortunately I'm always getting the same output class "cat". I know there's been a few posts where people have the same struggle. I've tried every approach but I still couldn't figure out what I'm doing wrong. A friend of mine told me I'm not labeling the classes correctly since my accuracy ratio changes based on how many images I have for each class , but I read on the tutorials that if I have sub-directories using the "flow_from_directory" method it already labels my classes based on the name of my folders, if someone could enlighten me on what I'm doing wrong here that'd be quite helpful. Here's a small code sample of my prototype:

# MODEL CONSTRUCTION -----------------------------------------
model = Sequential()
model.add(Conv2D(32, (3, 3), input_shape=(128,128,3))) #(3, 150, 150)
model.add(Activation('relu'))
model.add(MaxPooling2D(pool_size=(2, 2)))

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

model.add(Flatten())  # this converts all 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('sigmoid')) #sigmoid for binary outcome, softmax for more than two outcomes

model.compile(loss='binary_crossentropy', #since its a binary classification
              optimizer='rmsprop',
              metrics=['accuracy'])


#-------------------------------------------------------------

#augmentation configuration for training
train_datagen = ImageDataGenerator(
        rotation_range=40,
        width_shift_range=0.2,
        height_shift_range=0.2,
        #rescale=1. / 255,
        shear_range=0.2,
        zoom_range=0.2,
        horizontal_flip=True,
        fill_mode='nearest')

#augmentation configuration for validating
valid_datagen = ImageDataGenerator(
        rotation_range=60,
        width_shift_range=0.4,
        height_shift_range=0.1,
        zoom_range=0.1,
        vertical_flip=True,)

#augmentation configuration for testing
test_datagen = ImageDataGenerator(
    rescale=1. / 255)

train_generator = train_datagen.flow_from_directory(
        directory='data/train',  # this is the target directory
        target_size=(img_width, img_height), # all images will be resized to the given dimensions
        color_mode="rgb",
        #classes = ['dog', 'cat'], 
        batch_size=batch_size,
        class_mode='binary')  # since we use binary_crossentropy loss, we need binary labels

# this is a similar generator, for validation data
validation_generator = valid_datagen.flow_from_directory(
        directory='data/validation',
        target_size=(img_width, img_height),
        color_mode="rgb",
        #classes = ['dog', 'cat'], 
        batch_size=batch_size,
        class_mode='binary',
        seed=42)

test_generator = test_datagen.flow_from_directory(
    directory='data/test',
    target_size=(img_width, img_height),
    color_mode="rgb",
    batch_size=1,
    class_mode=None,
    #shuffle=False,
)

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)

model.evaluate_generator(
    generator=validation_generator
)

test_generator.reset()
pred=model.predict_generator(test_generator,verbose=1)
predicted_class_indices=np.argmax(pred,axis=1)

labels = (train_generator.class_indices)
labels = dict((v,k) for k,v in labels.items())
predictions = [labels[k] for k in predicted_class_indices]

Here's an image of the result when I test with some random images: model_output

Output layer in your model is having 1 node that is activated with sigmoid activation function.

The output the model makes will be of 1 dimensional. Where each value will be less than 1 since the activation is sigmoid .

You are making predictions like this.

pred=model.predict_generator(test_generator,verbose=1)
predicted_class_indices=np.argmax(pred,axis=1)

You are making predictions with the model and then you are taking argmax on that. Since your output corresponding to each image will be a single value like 0.99 or 0.001.

Taking argmax on it will give always output 0. Hence the output you always get is 0. Which corresponds to cat.

If you want your model to make predictions properly, you must take the prediction made by the model and then map it to the class based on the threshold you need like this if you are keeping threshold as 0.5

pred=model.predict_generator(test_generator,verbose=1)
predicted_class_indices=[1 if x >= 0.5 else 0 for x in preds]

当您搞乱事情并且不知道要解决什么问题时,为什么不使用教程中的确切代码和确切的培训数据呢?这是解决此类问题的推荐方法。

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM