Developing a Convolutional Neural Network Model Using the Unlabeled Image Files Directly From the Image Directories
Convolutional Neural Network

Developing a Convolutional Neural Network Model Using the Unlabeled Image Files Directly From the Image Directories

Convolutional Neural Network is a great tool for Image classification. It can perform other artificial intelligence tasks as well. But this article will focus primarily on image recognition. I have a detailed article on how a forward pass of a Convolutional Neural Network works and also how to implement a Convolutional Neural Network in Tensorflow and Keras. Please feel free to check that one here.

In the example of the above article, each image is labeled for us. But in the real world Images are not always labeled and labeling them takes money and time. So, this article will use a different technique.

Problem Overview

The example in this article will not have the labeled data. We will have image files as input and the model will take image files directly from the directories and learn about the images. And at the end, if we input an image file the model should classify it with a significant level of accuracies.

Dataset

If you are searching around for the Image Classification using Convolutional Neural Network tutorials, you probably found a lot of examples on Image Classification on chest X-ray images to detect Pneumonia.

I am also using a open source binary dataset from Kaggle that contains chest X-ray images. Here is the lisencing information of the dataset. Please feel free to download the data folder from this link and follow along.

In this exercise, X-ray images will come in as image files. For training, we will have 1349 image files for normal chest condition and 3883 image files for the chest with pneumonia. For testing, we have 124 image files for normal and 390 image files for pneumonia.

Data Preprocessing

The dataset in Kaggle is already organized in training and test folders separately. So, we don’t have to split the files for training and testing. Also, In the training folder, normal chest images and pneumonia chest images are separated into separate subfolders. I downloaded the data to my computer and used them directly from there.

Here is the mail folder and this folder contain the following two subfolders:




Each of these subfolders has these two subfolders:

The name of these subdirectories will be used as the labels for the data in our model. When the name of the subdirectory is ‘NORMAL’ the label is also ‘NORMAL’ and when the name of the subdirectory is ‘PNEUMONIA’, the label is ‘PNEUMONIA’.

Before diving into the model, let’s check some of the images from the sub-directories. For that first we need to save the path of the directories for normal and pneumonia X-ray images. I am only printing from the training directory. These are the folder location in my laptop. You need to mention the folder location in your laptop.

import os
train_normal = os.path.join (r"C:\Users\rashi\OneDrive\Desktop\New folder 1\Launchcode\Tensorflow\chest_x-ray_CNN\Pediatric Chest X-ray Pneumonia\train\NORMAL")
train_pneumonia= os.path.join(r"C:\Users\rashi\OneDrive\Desktop\New folder 1\Launchcode\Tensorflow\chest_x-ray_CNN\Pediatric Chest X-ray Pneumonia\train\PNEUMONIA")


Now, we can simply join the name of the files with the path of the directory to find the path of the files and plot them. os.listdir gives you the names of the files in the directory.

import matplotlib.image as mpimg
normal_img = [os.path.join(train_normal, file)
              for file in os.listdir(train_normal)[:3]]
plt.figure(figsize=(12, 3))
for i, img_path in enumerate(normal_img):
    sp = plt.subplot(1, 3, i+1)
    sp.axis('Off')
    img = mpimg.imread(img_path)
    plt.imshow(img)

plt.show()

Image By Author

Some images from the Pneumonia directory:

pneumonia_img = [os.path.join(train_pneumonia, file)
              for file in os.listdir(train_pneumonia)[:3]]
plt.figure(figsize=(12, 3))
for i, img_path in enumerate(pneumonia_img):
    sp = plt.subplot(1, 3, i+1)
    sp.axis('Off')
    img = mpimg.imread(img_path)
    plt.imshow(img)

plt.show()

Image By Author

We need to use the ImageDataGenerator function from TensorFlow to identify the files as normal or pneumonia. The ImageDataGenerator function can rescale the data if necessary. And then the image files will flow directly from the directory. We will specify the target size of the image files as 300×300 and the files will automatically be resized for us.

Here is the total code for all that:

import numpy as np
import tensorflow as tf
from tensorflow import keras
from tensorflow.keras import layers
from tensorflow.keras.preprocessing.image import ImageDataGenerator
train_generator = train_datagen.flow_from_directory( r'C:\\Users\\rashi\\OneDrive\\Desktop\New folder 1\\Launchcode\\Tensorflow\\chest_x-ray_CNN\\Pediatric Chest X-ray Pneumonia\\train', target_size=(300, 300), batch_size=128, class_mode='binary' )

Output:

Found 5232 images belonging to 2 classes.
Found 624 images belonging to 2 classes.

You can see that it detects two subfolders (NORMAL and PNEUMONIA) as two classes for both training and test data.

Data processing is done.




Model Building

In this model, I am using four convolution layers with 32 filters of size 3×3 and 2×2 max-pooling layers. After that one dense layer with 512 neurons. The activation function is ‘relu’ except for the output layer. If you want to learn how all these elements work please see the article mentioned in the beginning.

Here is the model:

model = tf.keras.models.Sequential([
#Note the input shape is the size of the image 300x300 with 3 bytes color

tf.keras.layers.Conv2D(16, (3,3), activation='relu', input_shape=(300, 300, 3)),
tf.keras.layers.MaxPooling2D(2, 2),

tf.keras.layers.Conv2D(32, (3,3), activation='relu'),
tf.keras.layers.MaxPooling2D(2,2),

tf.keras.layers.Conv2D(64, (3,3), activation='relu'),
tf.keras.layers.MaxPooling2D(2,2),

tf.keras.layers.Conv2D(64, (3,3), activation='relu'),
tf.keras.layers.MaxPooling2D(2,2),

tf.keras.layers.Conv2D(64, (3,3), activation='relu'),
tf.keras.layers.MaxPooling2D(2,2),

# Flatten the results to feed into a DNN
tf.keras.layers.Flatten(),

tf.keras.layers.Dense(512, activation='relu'),
tf.keras.layers.Dense(512, activation='relu'),

tf.keras.layers.Dense(1, activation='sigmoid')
])

The model is ready. The model summary looks like this:

model.summary()

The next step is to compile the model. I used RMSprop optimizer and a learning rate of 0.0001. You may find the accuracies oscillating a bit. If necessary please try a smaller learning rate.

from tensorflow.keras.optimizers import RMSprop
model.compile(loss="binary_crossentropy",
             optimizer=RMSprop(learning_rate=0.0001),
             metrics=['accuracy'])

It’s training time. The model is ready for training. I will only run it for 15 epochs. The steps_per_epoch is used 8 here. That means there will 8 steps before one epoch is done. The batch size will be the input data divided by 8.

history = model.fit(
    train_generator,
    steps_per_epoch=8,
    epochs=15,
    verbose=1,
    validation_data = validation_generator,
    validation_steps = 8
)

In 15 epochs how accuracies changed:

import matplotlib.pyplot as plt
plt.plot(history.history['accuracy'])
plt.plot(history.history['val_accuracy'])
plt.title('Model Accuracies')
plt.ylabel('Accuracy')
plt.xlabel('Epoch')
plt.legend(['train', 'test'], loc='best')
plt.show()
Image By Author

As you can see validation accuracies oscillated pretty bad. Let’s see how losses changed over the 15 epochs:

plt.plot(history.history['loss'])
plt.plot(history.history['val_loss'])
plt.title('Model Loss')
plt.ylabel('Loss')
plt.xlabel('Epoch')
plt.legend(['train', 'test'], loc='best')
plt.show()
Image By Author

As expected Validation losses also oscillated a lot.

The reason for that could be too large a learning rate. I would try with a smaller learning rate. Also, it is possible to keep changing the learning rate throughout the epochs. That is out of the scope of this article. I will work on it in a separate exercise some other day. The overall accuracy was good. So, I am stopping with the tutorial here.

Please feel free to design some different models. Here are some ideas:

  1. Try different numbers of convolution and MaxPooling layers.
  2. You can use different numbers and sizes of filters.
  3. Use a different activation function instead of ‘relu’.
  4. Please feel free to try with a different number of neurons and add more dense layers.
  5. Use a different optimizer instead of RMSprop.
  6. I already talked about the learning rate before.
  7. Also, try with some more epochs. I only ran it for 15 epochs. And feel free to use callbacks as mentioned in the article mentioned in the beginning.

Conclusion

Hopefully, this article was helpful! If you are trying different ideas and getting better and more stable results, please feel free to share in the comment section. There are a lot of other ways to improve a model. I will come back with some more ideas soon.

Feel free to follow me on Twitter and check out my new YouTube channel.




#MachineLearning #DeepLearning #ArtificialInteligence #tensorflow #python #ComputerVision

Leave a Reply

Close Menu