I'm trying to make a neural network that can identify if there is a cat in a picture. I found this tutorial on tensorflow website and tried to adapt it to my problem. The tutorial is for classifying cats and dogs, but since I only want to detect cats, I changed the categories to cats and non-cats.
For non-cats I downloaded a dataset of random images.
I added two generators to the code from the tutorial:
test_data_gen = test_image_generator.flow_from_directory(batch_size=batch_size,
directory=test_dir,
target_size=(IMG_HEIGHT, IMG_WIDTH),
class_mode='binary')
pred_data_gen = pred_image_generator.flow_from_directory(batch_size=batch_size,
directory=pred_dir,
target_size=(IMG_HEIGHT, IMG_WIDTH),
class_mode='binary')
And then tested the model like this:
print('\n# Evaluate on test data')
results = model.evaluate_generator(test_data_gen)
print('test loss, test acc:', results)
print('\n# Generate predictions')
predictions = model.predict(pred_data_gen)
print(len(predictions))
print(predictions)
That's the output:
# Evaluate on test data
test loss, test acc: [0.45212748232815003, 0.9324082]
# Generate predictions for custom samples
256
[[ -8.023465 ]
[ -7.781438 ]
[ 50.281197 ]
[-10.172492 ]
[ -5.1096087 ]
[ 43.0299 ]
[ 21.416649 ]
...
[-10.866359 ]
[-14.797473 ]
[ 84.72212 ]
[ 23.712345 ]
[ -6.4916744 ]
[-18.384903 ]
[ 33.10642 ]]
The test accuracy is very high, but I have no idea what these results mean. I thought they should be between 0 and 1, but these even have negative values. How should I interpret these results?
EDIT:
This is my model (before adding the sigmoid activation function to the last layer):
model = Sequential([
Conv2D(16, 3, padding='same', activation='relu', input_shape=(IMG_HEIGHT, IMG_WIDTH, 3)),
MaxPooling2D(),
Conv2D(32, 3, padding='same', activation='relu'),
MaxPooling2D(),
Conv2D(64, 3, padding='same', activation='relu'),
MaxPooling2D(),
Flatten(),
Dense(512, activation='relu'),
Dense(1)
])
I changed the last layer to Dense(1, activation='sigmoid')
and the output looks like this:
# Evaluate on test data
test loss, test acc: [0.714477022488912, 0.5949367]
# Generate predictions for custom samples
256
[[1.]
[1.]
[1.]
...
[1.]
[1.]
[1.]]
All predicted values are ones, even though only half of the images are cats in the test set.
EDIT2:
Here is how I compile and fit the model:
model.compile(optimizer='adam',
loss=tf.keras.losses.BinaryCrossentropy(from_logits=True),
metrics=['accuracy'])
model.summary()
history = model.fit_generator(
train_data_gen,
steps_per_epoch=total_train // batch_size,
epochs=epochs,
validation_data=val_data_gen,
validation_steps=total_val // batch_size
)
The last layer in your model is a Dense
layer with a single neuron. Since no parameters have been passed to it, by default it has linear activation. User @Code Pope indicated that it is a "failure" (mistake in Tensorflow docs?). It isn't, the code is perfectly fine.
Your loss function computes binary crossentropy and it can easily work with linear activation. In fact computing sigmoid is just a little extra that is not needed. The ANN will output negative values for one class and positive for the other one. They are not normalised, but are so-called logits
- that's why you are saying in your loss function from_logits=True
.
How to get predictions:
from sklearn.metrics import accuracy_score
images, actual = next(train_data_gen)
predictions = model.predict(images)
predictions = (predictions > 0).flatten()
accuracy_score(results, pred)
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With