<jupyter_start><jupyter_text>Chest_Disease_Detection_Using_CNN  Development of a model that automates the process of detecting and classifying chest disease with the purpose of reducing the cost and time of detection. This project is organised as follows: (a) Data Visualization and data proccessing, (b) Build and train CNN model, (c) Evaluate trained CNN model. Introduction:* AI/ML/DL has been revolutionizing healthcare and medicine in areas such as: (a) Medical imagery, (b) Drug research, (c) Genome development* Deel learning has been proven to be superior in detecting and classifying disease using imagery data.* Skin cancer could be detected more accurately by deep learning (95%) than by dermatologists(86.6%) (2018).Reference: https://www.theguardian.com/society/2018/may/29/skin-cancer-computer-learns-to-detect-skin-cancer-more-accurately-than-a-doctor  In this case study, the operations team of a hospital has collected extensive X-Ray chest data which will be used for the development of a model that could detect and classify the diseases in less than 5 minutes. The provided data consists of 133 images that belong to 4 class: (a) Healthy, (b) Covid-19, (c) Bacterial Pneumonia, (d) Viral Pneumonia. The dataset is initially divided into training and test categories for validation purposes.  0. Import reqired libraries  (a) Import required libraries<jupyter_code>import os
import cv2
import tensorflow as tf
import numpy as np
from tensorflow.keras import layers, optimizers
from tensorflow.keras.applications.resnet50 import ResNet50
from tensorflow.keras.layers import Input, Add, Dense, Activation, ZeroPadding2D, BatchNormalization, Flatten, Conv2D, AveragePooling2D, MaxPooling2D, Dropout
from tensorflow.keras.models import Model, load_model
from tensorflow.keras import backend as K
from tensorflow.keras.preprocessing.image import ImageDataGenerator
from tensorflow.keras.callbacks import ReduceLROnPlateau, EarlyStopping, ModelCheckpoint, LearningRateScheduler
import matplotlib.pyplot as plt
import seaborn as sns
import pandas as pd<jupyter_output><empty_output><jupyter_text>1. Read dataset  (a) Specify training data directory<jupyter_code>XRay_Directory =r"C:\Users\Tam\Desktop\Data Science Projects\Chest_Disease_Detection_Using_CNN\Dataset"<jupyter_output><empty_output><jupyter_text>**Comment:** Adjust the path of the directory based on where the dataset is saved on the user's computer.<jupyter_code>os.listdir(XRay_Directory)<jupyter_output><empty_output><jupyter_text>(b) Use of image generator to generate tensor images data and normalize them using 20% of the data for cross-validation.<jupyter_code>image_generator = ImageDataGenerator(rescale = 1./255, validation_split= 0.2)<jupyter_output><empty_output><jupyter_text>(c) Generate batches of 40 images and perform shuffling and image resizing. (i) Training data<jupyter_code>train_generator = image_generator.flow_from_directory(batch_size = 40, directory= XRay_Directory, shuffle= True, target_size=(256,256), class_mode = 'categorical', subset="training")<jupyter_output>Found 428 images belonging to 4 classes.<jupyter_text>(ii) Validation data<jupyter_code>validation_generator = image_generator.flow_from_directory(batch_size = 40, directory= XRay_Directory, shuffle= True, target_size=(256,256), class_mode = 'categorical', subset="validation")<jupyter_output>Found 104 images belonging to 4 classes.<jupyter_text>(d) Generate a batch of 40 images and labels<jupyter_code>train_images, train_labels = next(train_generator)
train_images.shape
train_labels.shape<jupyter_output><empty_output><jupyter_text>(e) Create labels Translator<jupyter_code>label_names = {0 : 'Covid-19', 1 : 'Normal' , 2: 'Viral Pneumonia', 3 : 'Bacterial Pneumonia'}<jupyter_output><empty_output><jupyter_text>**Comment:** The 0 label represents a patient with Covid-19, the 1 label represents a health patient, the 2 label represents a patient with Viral Pneumonia and the 3 label represent a patient with Bacterial Pneumonia.  2. Visualize Dataset  (a) Display a grid of 36(6x6) Images from the dataset along with their corresponding labels.<jupyter_code>L = 6
W = 6

fig, axes = plt.subplots(L, W, figsize = (12, 12))
axes = axes.ravel()

for i in np.arange(0, L*W):
    axes[i].imshow(train_images[i])
    axes[i].set_title(label_names[np.argmax(train_labels[i])])
    axes[i].axis('off')

plt.subplots_adjust(wspace = 0.5)<jupyter_output><empty_output><jupyter_text>3. Import a pretrained ResNet50 model tha has been trained with Imagenet dataset  (a) Import the trained ResNet50 model<jupyter_code>basemodel = ResNet50(weights = 'imagenet', include_top = False, input_tensor = Input(shape=(256,256,3)))<jupyter_output><empty_output><jupyter_text>**Comment:** The model has been trained using the imagenet dataset.  (b) Imported model summary<jupyter_code>basemodel.summary()<jupyter_output>Model: "resnet50"
__________________________________________________________________________________________________
Layer (type)                    Output Shape         Param #     Connected to                     
==================================================================================================
input_1 (InputLayer)            [(None, 256, 256, 3) 0                                            
__________________________________________________________________________________________________
conv1_pad (ZeroPadding2D)       (None, 262, 262, 3)  0           input_1[0][0]                    
__________________________________________________________________________________________________
conv1_conv (Conv2D)             (None, 128, 128, 64) 9472        conv1_pad[0][0]                  
__________________________________________________________________________________________________
conv1_bn (BatchNormalization)   (None, 128, 128, 64) 256         conv1_conv[0][0]          [...]<jupyter_text>(c) Freeze the model's layers but leave only the last 10 layers of the model to be trainable<jupyter_code>for layer in basemodel.layers[:-10]:
  layers.trainable = False<jupyter_output><empty_output><jupyter_text>**Comment:** The last 10 layers of the model are then able to be trained with the new X-ray deep learning model.  4. Build and train the deep learning model **Comment:** The model will be built on top of the previous pretrained model.   (a) Model building<jupyter_code>#Use pretrained model
headmodel = basemodel.output
#Add average pooling layer
headmodel = AveragePooling2D(pool_size = (4,4))(headmodel)
#Add flattening layer
headmodel = Flatten(name= 'flatten')(headmodel)
# Add dense layer with 256 neurons and apply relu activation function
headmodel = Dense(256, activation = "relu")(headmodel)
#Drop 30% of the neurons to avoid Codependency
headmodel = Dropout(0.3)(headmodel)
# Add dense layer with 256 neurons and apply relu activation function
headmodel = Dense(256, activation = "relu")(headmodel)
#Drop 30% of the neurons to avoid Codependency
headmodel = Dropout(0.3)(headmodel)
# Add dense layer with 256 neurons and apply relu activation function
headmodel = Dense(256, activation = "relu")(headmodel)
#Drop 30% of the neurons to avoid Codependency
headmodel = Dropout(0.3)(headmodel)
#Add final dense layer with 4 outputs and apply softmax activation function
headmodel = Dense(4, activation = 'softmax')(headmodel)

model = Model(inputs = basemodel.input, outputs = headmodel)<jupyter_output><empty_output><jupyter_text>(b) Model configuration for training (i) Compile model<jupyter_code>model.compile(loss = 'categorical_crossentropy', optimizer=optimizers.RMSprop(lr = 1e-4, decay = 1e-6), metrics= ["accuracy"])<jupyter_output><empty_output><jupyter_text>(ii) Use early stopping to exit training if validation loss is not decreasing after a certain number of epochs<jupyter_code>earlystopping = EarlyStopping(monitor='val_loss', mode='min', verbose=1, patience=20)<jupyter_output><empty_output><jupyter_text>(iii) Save the best model with the lowest validation loss<jupyter_code>checkpointer = ModelCheckpoint(filepath="weights.hdf5", verbose=1, save_best_only=True)<jupyter_output><empty_output><jupyter_text>**Commment:** The best model is everytime saved as "weights.hdf5"  (c) Generate images<jupyter_code>train_generator = image_generator.flow_from_directory(batch_size = 4, directory= XRay_Directory, shuffle= True, target_size=(256,256), class_mode= 'categorical', subset="training")
val_generator = image_generator.flow_from_directory(batch_size = 4, directory= XRay_Directory, shuffle= True, target_size=(256,256), class_mode= 'categorical', subset="validation")<jupyter_output>Found 104 images belonging to 4 classes.<jupyter_text>(d) Fit the model into the training data (25 epochs)<jupyter_code>history = model.fit(train_generator, steps_per_epoch= train_generator.n // 4, epochs = 25, validation_data= val_generator, validation_steps= val_generator.n // 4, callbacks=[checkpointer, earlystopping])<jupyter_output>Epoch 1/25
107/107 [==============================] - 200s 2s/step - loss: 1.2789 - accuracy: 0.4489 - val_loss: 6.6809 - val_accuracy: 0.2500

Epoch 00001: val_loss improved from inf to 6.68086, saving model to weights.hdf5
Epoch 2/25
107/107 [==============================] - 213s 2s/step - loss: 0.4945 - accuracy: 0.8361 - val_loss: 4.7973 - val_accuracy: 0.2500

Epoch 00002: val_loss improved from 6.68086 to 4.79728, saving model to weights.hdf5
Epoch 3/25
107/107 [==============================] - 218s 2s/step - loss: 0.3347 - accuracy: 0.8917 - val_loss: 85.4227 - val_accuracy: 0.2500

Epoch 00003: val_loss did not improve from 4.79728
Epoch 4/25
107/107 [==============================] - 218s 2s/step - loss: 0.3825 - accuracy: 0.8839 - val_loss: 59.5228 - val_accuracy: 0.2500

Epoch 00004: val_loss did not improve from 4.79728
Epoch 5/25
107/107 [==============================] - 223s 2s/step - loss: 0.2914 - accuracy: 0.9278 - val_loss: 12.9556 - val_accuracy: 0.2404

Epoch 000[...]<jupyter_text>5. Evaluate trained deep learning model  (a) Plot history of model training<jupyter_code>history.history.keys()<jupyter_output><empty_output><jupyter_text>(i) Accuracy and loss<jupyter_code>plt.plot(history.history['accuracy'])
plt.plot(history.history['loss'])
plt.xlabel('Epochs')
plt.ylabel('Training accuracy and loss')<jupyter_output><empty_output><jupyter_text>**Comment:** In this figure it is plotted the history for loss(orange) and accuracy(blue) for the 25 epochs. (ii) Validation loss<jupyter_code>plt.plot(history.history['val_loss'])
plt.xlabel('Epochs')
plt.ylabel('Validation loss')<jupyter_output><empty_output><jupyter_text>**Comment:** In this figure it is plotted the validation loss over the 25 epochs. (iii) Validation accuracy<jupyter_code>plt.plot(history.history['val_accuracy'])

plt.xlabel('Epochs')
plt.ylabel('Validation accuracy')<jupyter_output><empty_output><jupyter_text>**Comment:** In this figure it is plotted the validation accuracy over the 25 epochs.  (b) Import and proccess testing data<jupyter_code>test_directory =r"C:\Users\Tam\Desktop\Data Science Projects\Chest_Disease_Detection_Using_CNN\Test"<jupyter_output><empty_output><jupyter_text>**Comment:** We are going to use the initially seperated testing data to validate our trained model.  (c) Evaluate model's accuracy (i) Generate the testing dataset<jupyter_code>test_gen=ImageDataGenerator(rescale=1./255)
test_generator=test_gen.flow_from_directory(batch_size=40,directory=test_directory,shuffle=True,target_size=(256,256),class_mode='categorical')<jupyter_output>Found 40 images belonging to 4 classes.<jupyter_text>(ii) Evaluate the model<jupyter_code>evaluate=model.evaluate(test_generator,steps=test_generator.n //4, verbose=1)<jupyter_output>1/10 [==>...........................] - ETA: 37s - loss: 4.4485 - accuracy: 0.8250WARNING:tensorflow:Your input ran out of data; interrupting training. Make sure that your dataset or generator can generate at least `steps_per_epoch * epochs` batches (in this case, 10 batches). You may need to use the repeat() function when building your dataset.
10/10 [==============================] - 4s 6ms/step - loss: 4.4485 - accuracy: 0.8250<jupyter_text>(iii) Calculate accuracy during testing<jupyter_code>print('Accuracy Test: {}'.format(evaluate[1]))<jupyter_output>Accuracy Test: 0.824999988079071<jupyter_text>(d) Model's scikit-learn metrics<jupyter_code>from sklearn.metrics import confusion_matrix, classification_report, accuracy_score

prediction = []
original = []
image = []

for i in range(len(os.listdir(test_directory))):
  for item in os.listdir(os.path.join(test_directory,str(i))):
    img= cv2.imread(os.path.join(test_directory,str(i),item))
    img = cv2.resize(img,(256,256))
    image.append(img)
    img = img / 255
    img = img.reshape(-1,256,256,3)
    predict = model.predict(img)
    predict = np.argmax(predict)
    prediction.append(predict)
    original.append(i)<jupyter_output><empty_output><jupyter_text>**Comment:** In this step we go through every image and we read it , resize it and then append it to the image list. Then we  normalize it and reshape it and finally we make predictions and add these predictions to the prediction accumulator. Finally the model's metrics are going to be calculated by comparing the two developed lists, one containing the real life results(original) and the other one containing the predictions. (i) Accuracy<jupyter_code>score=accuracy_score(original,prediction)
print('Test Accuracy: {}'.format(score))<jupyter_output>Test Accuracy: 0.85<jupyter_text>**Comment:** 85% accuracy was achieved on the testing dataset. (ii) Classification Report<jupyter_code>print(classification_report(np.asarray(original),np.asarray(prediction)))<jupyter_output>precision    recall  f1-score   support

           0       0.91      1.00      0.95        10
           1       0.77      1.00      0.87        10
           2       1.00      0.50      0.67        10
           3       0.82      0.90      0.86        10

    accuracy                           0.85        40
   macro avg       0.87      0.85      0.84        40
weighted avg       0.87      0.85      0.84        40<jupyter_text>(iii) Confusion Matrix<jupyter_code>cm = confusion_matrix(np.asarray(original), np.asarray(prediction))
ax = plt.subplot()
sns.heatmap(cm, annot = True, ax = ax)

ax.set_xlabel('Predicted')
ax.set_ylabel('Original')
ax.set_title('Confusion_matrix')<jupyter_output><empty_output><jupyter_text>(e) Display a sample of the model's predictions<jupyter_code>#Development of a 25 picture grid (5x5)
L = 5
W = 5

fig, axes = plt.subplots(L, W, figsize = (12, 12))
axes = axes.ravel()

for i in np.arange(0, L*W):
    axes[i].imshow(image[i])
    axes[i].set_title('Guess={}\nTrue={}'.format(str(label_names[prediction[i]]), str(label_names[original[i]])))
    axes[i].axis('off')

plt.subplots_adjust(wspace = 1.2)<jupyter_output><empty_output>
{'fraction_non_alphanumeric': 0.11838926174496645, 'fraction_numerical': 0.04369127516778523, 'mean_word_length': 5.4984736153510685, 'pattern_counts': {'":': 0, '<': 115, '<?xml version=': 0, '>': 116, 'https://': 1, 'lorem ipsum': 0, 'www.': 1, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 10, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'chain_length': '31', 'dir': 'jupyter-structured-clean-dedup', 'id': '446607', 'license': 'MIT', 'n_tokens_mistral': 5063, 'n_tokens_neox': 4495, 'n_words': 1308, 'path': 'Chest_Disease_Detection_Using_CNN.ipynb', 'repo_name': 'Panostam/Chest_Disease_Detection_Using_CNN', 'size': '14900'}