3

I have implemented an EfficientNet in Keras for a binary problem using image generator. In the test case when i predict the output it return an array with a set of probability but referred to only one class, here the code and the output:

test_image_generator = ImageDataGenerator(
rescale=1./255
)
real_test=test_image_generator.flow_from_directory(
directory='/content/real_test',
target_size=(224, 224),
color_mode="rgb",
batch_size=1,
class_mode=None,
shuffle=False,
#seed=42
)

The output is:

real_test.reset()
from keras.models import load_model
efficient_net_custom_model = load_model('model_efficientnet4.h5',compile=False)
pred = efficient_net_custom_model.predict_(real_test, steps = len(real_test), verbose = 1)
print (pred)

Now when printing the prediction for 4 different images it returns:

[[0.45415235]
[0.52390164]
[0.9999932 ]
[0.99946016]]

Basically only one output probability (I think) for each image, and it is impossible to say which is the actual class. isn't it? How can I do to solve that issue?

Thank you

Edit:

Including model code

def output_custom_model(prebuilt_model):
print(f"Processing {prebuilt_model}")
prebuilt = prebuilt_model(include_top=False,
                        input_shape=(224, 224, 3),
                        weights='imagenet')
output = prebuilt.output
output = GlobalMaxPooling2D()(output)
output = Dense(128, activation='relu')(output)
output = Dropout(0.2)(output)
output = Dense(1, activation='sigmoid')(output)

model = Model(inputs=prebuilt.input, outputs=output)
model.compile(optimizer='sgd', loss='binary_crossentropy',
          metrics=METRICS)
return model


efficient_net_custom_model = output_custom_model(EfficientNetB4)
filepath='model_efficientnet4.h5'


efficient_net_history = 
efficient_net_custom_model.fit_generator(train_generator,
                             epochs=20,
                             validation_data=validation_generator,
                             )
fflpdqqoeit
  • 65
  • 1
  • 10
  • can you please put the model definition code? you may have 4 output layers or an aux output – Skander HR Jul 09 '20 at 10:14
  • 1
    for a binary problem, your output is a probability between 0 and 1, high is one of the class and 0 is the other class. If you want 2, you will have to put 2 neurons on last dense layer – SajanGohil Jul 09 '20 at 10:14
  • @SkanderHR I have included the code – fflpdqqoeit Jul 09 '20 at 10:35
  • @SajanGohil I agree. but when I included 2 neurons in the dense layer I received: ValueError: Error when checking target: expected dense_18 to have shape (2,) but got array with shape (1,) – fflpdqqoeit Jul 09 '20 at 10:36
  • 1
    @fflpdqqoeit for that, you will have to set class_mode in generator to 'categorical' which is default. With single value you can round it to closest int (0 or 1) and consider that as two classes. – SajanGohil Jul 09 '20 at 10:39
  • @SajanGohil Ok thank you. So you are saying that I should include 'categorical0 in train_generator leaving Dense(1, sigmoid) and then try to predict. Isn't it? – fflpdqqoeit Jul 09 '20 at 10:53
  • 1
    if you set class_mode='categorical' , you should put two neurons, if you put 1 neuron (Dense(1)), you have to set class_mode='binary'. You can read more bout it in the documentation https://keras.io/api/preprocessing/image/ – SajanGohil Jul 09 '20 at 10:56
  • @SajanGohil, thank you. I have set class_mode='categorical', Dense(2, softmax), but it returns an error as well as: expected dense_26 to have shape (2,) but got array with shape (1,) – fflpdqqoeit Jul 09 '20 at 11:04
  • 1
    your loss is still binary ('binary_crossentropy') set that to 'categorical_crossentropy' – SajanGohil Jul 09 '20 at 11:06
  • @SajanGohil it works. absolutely great. – fflpdqqoeit Jul 09 '20 at 11:22

2 Answers2

2

In some type of networks, the binary output is just one and it represents the first class of the training data. We assume that your training data is like this:

img1data, class1
img2data, class1
..
imgNdata, class2

Your network has accepted the class1 as default class and the given results are the scores of that class. So these results show the scores of class1.

[[0.45415235]
[0.52390164]
[0.9999932 ]
[0.99946016]]

Due to binary classification, the first result shows that the score of class1 is 0.45, so the class2 must be 0.55, the image is belongs to the class2. The last result shows that the score of class1 is 0.999, so the class2 must be 0.0006, the image is belong to the class1. And so on...

You can write a method to make these operations and to find the class which the image is belong to.

def find_class(result):
    if result >= 0.5:
        return "class1"
    else:
        return "class2"

find_class(result[0])
Emrah Tema
  • 335
  • 3
  • 9
0

Your line output = Dense(1, activation='sigmoid')(output) specifies only a single probability of output. You will need two neurons like a softmax to indicate what you wanted to do.

ABCD
  • 7,914
  • 9
  • 54
  • 90