TF model performs worse on the training images during testing

I use tf keras to build a neural network that classifies images of covid-19 rapid tests into three classes (Negative, Positive, Empty).

During training the tensorboard logs denote a validation accuracy of around 90%. But when I test the network after being trained with the same images it was trained on, the classification performance is way worse (~60%). I observed the same behavior when I trained the network with different images.

During training the images are preprocessed to grayscale and resized before being fed into the model.

image = cv2.cvtColor(image, cv2.COLOR_BGR2GRAY)
image = cv2.resize(image, (height, width))

To augment the sparse data that I have (~450 images) I am using the keras.preprocessing.image.ImageDataGenerator and its parameters are: width_shift_range=0.1, brightness_range=[0.9, 1.1], height_shift_range=0.1, zoom_range=0.2, horizontal_flip=True, rotation_range=10, shear_range=0.2, fill_mode="nearest", samplewise_center=True, samplewise_std_normalization=True

I am converting the model to tflite because we need it for mobile platforms. I am using this code snippet:

model = tf.keras.models.load_model(model_path)

converter = tf.lite.TFLiteConverter.from_keras_model(model) # path to the SavedModel directory
# converter.optimizations = [tf.lite.Optimize.DEFAULT] # optimizations
tflite_model = converter.convert()

# Save the model.
with open('rapid_test_strip_cleaned_model.tflite', 'wb') as f:
  f.write(tflite_model)

What I have tried:

  • crop the images to the strip of the casette, train and test the network again
  • check in the testing (inference) script if the labels are correct
  • check if the images are converted to grayscale and resized correctly before being fed into the network during testing
  • test the model before converting it to tflite, using tensorflow.keras.models

Model:

img_width, img_height = (256, 256)

model = Sequential()
inputShape = (img_width, img_height, 1)
model.add(Conv2D(32, (3, 3), activation="relu", input_shape=inputShape))
# to prevent overfitting
model.add(Dropout(0.25))
model.add(MaxPooling2D(pool_size=(2, 2), strides=(2, 2)))

model.add(Conv2D(64, (3, 3), activation="relu"))
# to prevent overfitting
model.add(Dropout(0.25))
model.add(MaxPooling2D(pool_size=(2, 2), strides=(2, 2)))

model.add(Conv2D(128, (3, 3), activation="relu"))
# to prevent overfitting
model.add(Dropout(0.25))
model.add(MaxPooling2D(pool_size=(2, 2), strides=(2, 2)))
  
model.add(Flatten())
model.add(Dense(512, activation="relu"))
# to prevent overfitting
model.add(Dropout(0.5))
model.add(Dense(3, activation="softmax"))

opt = Adam(learning_rate=INIT_LR, decay=INIT_LR / EPOCHS)

model.compile(loss="categorical_crossentropy", optimizer=opt,
            metrics=["accuracy"])

This is the Tensorboard graph of the training. The straight line is from another training run.

Testing/Inference script:

interpreter = tf.lite.Interpreter(model_path=model_path)

# Load TFLite model and allocate tensors.
interpreter.allocate_tensors()

# Get input and output tensors.
input_details = interpreter.get_input_details()
output_details = interpreter.get_output_details()

height = input_details[0]['shape'][1]
width = input_details[0]['shape'][2]

labels = ["positive", "negative", "initial"]

# load image into numpy array
image = cv2.imread(image_path)
image = cv2.cvtColor(image, cv2.COLOR_BGR2GRAY)
image = cv2.resize(image, (height, width))
input_arr = img_to_array(image)

input_arr = np.array([input_arr])
# normalize values
input_arr = input_arr / 255.0

interpreter.set_tensor(input_details[0]['index'], input_arr)

interpreter.invoke()

# The function `get_tensor()` returns a copy of the tensor data.
output_data = interpreter.get_tensor(output_details[0]['index'])

results = np.squeeze(output_data)
top_k = results.argsort()[-5:][::-1]

print(labels[top_k[0]])

Ideas about where the problem may be are very appreciated. I am stuck with this problem for two months now.

Thank you!

Hi @Sohrab_Tawana, Please try by normalizing the test data in a way that you have done for the training data. Thank You.