-1

I am creating a neural network that classifies photos into two classes. One class is photos with an empty surface, the other class is photos with this surface, but with an object. I want to make the neural network understand whether there is an object or not. I use tensorflow and Python. But in the end, when the model finishes training, it says to all the photos: There is an 88% probability that there is an object. Even in photos where there is no object. The photos of an empty table are all similar, because the table will always be like this in the photo. There are about 50 photos of objects on the table. There are also about 50 photos without objects. I made photos myself.

import numpy as np
import os
import tensorflow as tf
from tensorflow import keras
from tensorflow.keras import layers
from tensorflow.keras.models import Sequential
import pathlib
from tensorflow.keras.callbacks import TensorBoard
from keras.constraints import maxnorm


def load_data():
    data_dir = 'C:\\Users\\User\\AI\\training'
    data_dir = pathlib.Path(data_dir)  # dataset

    # training
    train_ds = tf.keras.preprocessing.image_dataset_from_directory(
        data_dir,
        validation_split=0.2,
        subset='training',
        seed=123,
        image_size=(img_height, img_width),
        batch_size=batch_size
    )

    # validation
    val_ds = tf.keras.preprocessing.image_dataset_from_directory(
        data_dir,
        validation_split=0.3,
        subset='validation',
        seed=123,
        image_size=(img_height, img_width),
        batch_size=batch_size
    )

    AUTOTUNE = tf.data.AUTOTUNE
    train_ds = train_ds.cache().shuffle(1000).prefetch(buffer_size=AUTOTUNE)
    val_ds = val_ds.cache().prefetch(buffer_size=AUTOTUNE)
    normalization_layer = layers.experimental.preprocessing.Rescaling(1. / 255)
    normalized_ds = train_ds.map(lambda x, y: (normalization_layer(x), y))
    image_batch, labels_batch = next(iter(normalized_ds))
    return train_ds, val_ds


def creat_model():
    model = Sequential([
        #data_augmentation,
        #layers.experimental.preprocessing.Rescaling(1. / 255),
        layers.Rescaling(1. / 255, input_shape=(img_height, img_width, 3)),
        layers.Conv2D(16, 3, padding='same', activation='relu'),
        layers.MaxPooling2D(),
        layers.Conv2D(32, 3, padding='same', activation='relu'),
        layers.MaxPooling2D(),
        layers.Conv2D(64, 3, padding='same', activation='relu'),
        layers.Conv2D(64, 3, padding='same', activation='relu'),
        layers.MaxPooling2D(),
        layers.Flatten(),
        layers.Dense(128, activation='relu'),
        layers.Dense(num_classes)
    ])

    model.summary()

    model.compile(optimizer='adam',
                  loss=tf.keras.losses.SparseCategoricalCrossentropy(from_logits=True),
                  metrics=['accuracy'])
    return model


batch_size = 35  
num_classes = 2  # classes
epochs = 10  
img_height, img_width = 511, 351

data_augmentation = keras.Sequential(
  [
    layers.experimental.preprocessing.RandomFlip("horizontal",
                                                 input_shape=(img_height,
                                                              img_width,
                                                              3)),
    layers.experimental.preprocessing.RandomRotation(0.1),
    layers.experimental.preprocessing.RandomZoom(0.1),
  ]
)

train_data, val_data = load_data()

logdir = os.path.join('logs', 'WilliamV1')
tensorboard = TensorBoard(log_dir=logdir)
if not os.path.isdir('results_WilliamV1'):
    os.mkdir('results_WilliamV1')

william = creat_model()
william.fit(train_data, validation_data=val_data, epochs=epochs, callbacks=[tensorboard])
william.save('results_WilliamV1/c')

To check neural network I use this code:

william = tf.keras.models.load_model('results_WilliamV1/WilliamV1.h5', compile=True)
path = input()
img = keras.preprocessing.image.load_img(
    path, target_size=(511, 351)
)
categories = {
    0: 'empty',
    1: 'no empty'
}
img_array = keras.preprocessing.image.img_to_array(img)
img_array = tf.expand_dims(img_array, 0)  # Create a batch
predictions = william.predict(img_array)
score = tf.nn.softmax(predictions[0])
print(np.argmax(score))
print(
    "This image most likely belongs to {} with a {:.2f} percent confidence."
        .format(categories[np.argmax(score)], 100 * np.max(score)))
desertnaut
  • 57,590
  • 26
  • 140
  • 166

2 Answers2

1

You need the same preprocessing steps in the training and validation. You didn't rescale your test data. You can start by dividing it by 255:

img_array = keras.preprocessing.image.img_to_array(img) / 255
Nicolas Gervais
  • 33,817
  • 13
  • 115
  • 143
0

You have a problem with your rescaling. In load_data(), you are rescaling the train and val datasets. In your model you have a rescaling layer which rescales the val and train again when they are fed into the model. Your test dataset is rescaled only when it's fed into to model. You need to delete the rescaling part in load_data() so the test and train will be treated equally.

In addition, your last Dense layer has no activation function, its default to None, since you are using every unit to represent the likelihood of the data to belong to that class you should use a SoftMax activation. Notice that you won't need to use softmax on your predictions outcome anymore since it's calculated in the model itself.

In your case you only have 2 classes (labeled 1 or 0), so you can use a Dense layer with only 1 unit with a sigmoid activation and a binarycrossentropy loss function.

Alex Waygood
  • 6,304
  • 3
  • 24
  • 46