Cainvas

Parkinson's Disease Detection using Parkinson's Spiral Drawing and CNN

Credit: AITS Cainvas Community

Photo by Lea Filipo on Dribbble

The dataset was taken from this link

Importing the required Libraries and packages

In [1]:
import numpy as np
import cv2
from tensorflow.keras.layers import Input, Conv2D, BatchNormalization, Dropout, Flatten, Dense, MaxPool2D
from tensorflow.keras.models import Model, Sequential
from tensorflow.keras.initializers import glorot_uniform
from tensorflow.keras.optimizers import Adam, SGD
import matplotlib.pyplot as plt
from sklearn.metrics import classification_report
from tensorflow.keras.preprocessing.image import ImageDataGenerator
from sklearn.model_selection import train_test_split
from tensorflow.keras.utils import to_categorical
from sklearn.preprocessing import LabelEncoder
from sklearn.metrics import classification_report, confusion_matrix
import seaborn as sns
from tensorflow.keras.regularizers import l2
import tensorflow as tf
import pandas as pd
In [2]:
!wget https://cainvas-static.s3.amazonaws.com/media/user_data/cainvas-admin/Parkinson_disease_detection.zip
!unzip -qo Parkinson_disease_detection.zip
--2021-07-13 13:11:45--  https://cainvas-static.s3.amazonaws.com/media/user_data/cainvas-admin/Parkinson_disease_detection.zip
Resolving cainvas-static.s3.amazonaws.com (cainvas-static.s3.amazonaws.com)... 52.219.64.8
Connecting to cainvas-static.s3.amazonaws.com (cainvas-static.s3.amazonaws.com)|52.219.64.8|:443... connected.
HTTP request sent, awaiting response... 200 OK
Length: 8201907 (7.8M) [application/x-zip-compressed]
Saving to: ‘Parkinson_disease_detection.zip.1’

Parkinson_disease_d 100%[===================>]   7.82M  --.-KB/s    in 0.06s   

2021-07-13 13:11:45 (135 MB/s) - ‘Parkinson_disease_detection.zip.1’ saved [8201907/8201907]

Loading Dataset

In [3]:
data_train = np.load('Parkinson_disease_detection/train_set.npz', allow_pickle=True)
x_train = data_train['arr_0']
y_train = data_train['arr_1']

print(x_train.shape)
print(y_train.shape)
(72, 256, 256, 3)
(72,)
In [4]:
data_test = np.load('Parkinson_disease_detection/test_set.npz', allow_pickle=True)
x_test = data_test['arr_0']
y_test = data_test['arr_1']

print(x_test.shape)
print(y_test.shape)
(30, 256, 256, 3)
(30,)

Data Distribution

In [5]:
unique_train, count = np.unique(y_train, return_counts=True)
plt.figure(figsize=(20, 10))
sns.barplot(unique_train, count).set_title("Number of training images per category:")
plt.show()
/opt/tljh/user/lib/python3.7/site-packages/seaborn/_decorators.py:43: FutureWarning: Pass the following variables as keyword args: x, y. From version 0.12, the only valid positional argument will be `data`, and passing other arguments without an explicit keyword will result in an error or misinterpretation.
  FutureWarning
In [6]:
unique_test, count_test = np.unique(y_test, return_counts=True)
plt.figure(figsize=(20, 10))
sns.barplot(unique_test, count_test).set_title("Number of testing images per category:")
plt.show()
/opt/tljh/user/lib/python3.7/site-packages/seaborn/_decorators.py:43: FutureWarning: Pass the following variables as keyword args: x, y. From version 0.12, the only valid positional argument will be `data`, and passing other arguments without an explicit keyword will result in an error or misinterpretation.
  FutureWarning

As can be seen, though the dataset is balanced but contains very less data points

Augmenting the Dataset

In [7]:
train_data_generator = ImageDataGenerator(rotation_range=360, 
                                    width_shift_range=0.0, 
                                    height_shift_range=0.0, 
#                                     brightness_range=[0.5, 1.5],
                                    horizontal_flip=True, 
                                    vertical_flip=True)

x = list(x_train)
y = list(y_train)

x_aug_train = []
y_aug_train = []

for (i, v) in enumerate(y):
    x_img = x[i]
    x_img = np.array(x_img)
    x_img = np.expand_dims(x_img, axis=0)
    aug_iter = train_data_generator.flow(x_img, batch_size=1, shuffle=True)
    for j in range(70):
        aug_image = next(aug_iter)[0].astype('uint8')
        x_aug_train.append(aug_image)
        y_aug_train.append(v)
print(len(x_aug_train))
print(len(y_aug_train))

x_train = x + x_aug_train
y_train = y + y_aug_train
print(len(x_train))
print(len(y_train))

test_data_generator = ImageDataGenerator(rotation_range=360, 
                                    width_shift_range=0.0, 
                                    height_shift_range=0.0, 
#                                     brightness_range=[0.5, 1.5],
                                    horizontal_flip=True, 
                                    vertical_flip=True)

x = list(x_test)
y = list(y_test)

x_aug_test = []
y_aug_test = []

for (i, v) in enumerate(y):
    x_img = x[i]
    x_img = np.array(x_img)
    x_img = np.expand_dims(x_img, axis=0)
    aug_iter = test_data_generator.flow(x_img, batch_size=1, shuffle=True)
    for j in range(20):
        aug_image = next(aug_iter)[0].astype('uint8')
        x_aug_test.append(aug_image)
        y_aug_test.append(v)
print(len(x_aug_test))
print(len(y_aug_test))

x_test = x + x_aug_test
y_test = y + y_aug_test
print(len(x_test))
print(len(y_test))
5040
5040
5112
5112
600
600
630
630

Visualizing the Images in Train and Test Set

Images in Train Set
In [8]:
# print(y_test)
figure1 = plt.figure(figsize=(5, 5))
idx_healthy = [i for (i, v) in enumerate(y_train) if v=='healthy']
img_healthy = x_train[idx_healthy[-1]]
plt.imshow(img_healthy)
plt.title('Spiral Drawing by a Healthy Person')
plt.axis('off')
plt.show()

figure2 = plt.figure(figsize=(5, 5))
idx_parkinson = [i for (i, v) in enumerate(y_train) if v=='parkinson']
img_parkinson = x_train[idx_parkinson[-1]]
plt.imshow(img_parkinson)
plt.title("Spiral Drawing by a Person having Parkinson's Disease")
plt.axis('off')
plt.show()

Images in Test Set

In [9]:
figure1 = plt.figure(figsize=(5, 5))
idx_healthy = [i for (i, v) in enumerate(y_test) if v=='healthy']
img_healthy = x_test[idx_healthy[-1]]
plt.imshow(img_healthy)
plt.title('Spiral Drawing by a Healthy Person')
plt.axis('off')
plt.show()

figure2 = plt.figure(figsize=(5, 5))
idx_parkinson = [i for (i, v) in enumerate(y_test) if v=='parkinson']
img_parkinson = x_test[idx_parkinson[-1]]
plt.imshow(img_parkinson)
plt.title("Spiral Drawing by a Person having Parkinson's Disease")
plt.axis('off')
plt.show()

Preprocessing the Images

In [10]:
for i in range(len(x_train)):
    img = x_train[i]
    img = cv2.resize(img, (128, 128))
    img = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
    x_train[i] = img
    
for i in range(len(x_test)):
    img = x_test[i]
    img = cv2.resize(img, (128, 128))
    img = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
    x_test[i] = img

x_train = np.array(x_train)
x_test = np.array(x_test)

x_train = x_train/255.0
x_test = x_test/255.0

label_encoder = LabelEncoder()
y_train = label_encoder.fit_transform(y_train)
print(y_train.shape)

label_encoder = LabelEncoder()
y_test = label_encoder.fit_transform(y_test)
print(y_test.shape)
(5112,)
(630,)

Data Distribution after Augmentation

In [11]:
unique_train, count = np.unique(y_train, return_counts=True)
plt.figure(figsize=(20, 10))
sns.barplot(unique_train, count).set_title("Number of training images per category after augmentation:")
plt.show()
/opt/tljh/user/lib/python3.7/site-packages/seaborn/_decorators.py:43: FutureWarning: Pass the following variables as keyword args: x, y. From version 0.12, the only valid positional argument will be `data`, and passing other arguments without an explicit keyword will result in an error or misinterpretation.
  FutureWarning
In [12]:
unique_test, count_test = np.unique(y_test, return_counts=True)
plt.figure(figsize=(20, 10))
sns.barplot(unique_test, count_test).set_title("Number of test set images per category after augmentation:")
plt.show()
/opt/tljh/user/lib/python3.7/site-packages/seaborn/_decorators.py:43: FutureWarning: Pass the following variables as keyword args: x, y. From version 0.12, the only valid positional argument will be `data`, and passing other arguments without an explicit keyword will result in an error or misinterpretation.
  FutureWarning
In [13]:
y_train = to_categorical(y_train)
y_test = to_categorical(y_test)

x_train = np.expand_dims(x_train, axis=-1)
x_test = np.expand_dims(x_test, axis=-1)

print(x_train.shape)
print(y_train.shape)
print(x_test.shape)
print(y_test.shape)
(5112, 128, 128, 1)
(5112, 2)
(630, 128, 128, 1)
(630, 2)

Defining the Model

In [14]:
def parkinson_disease_detection_model(input_shape=(128, 128, 1)):
    regularizer = tf.keras.regularizers.l2(0.001)
    model = Sequential()
    model.add(Input(shape=input_shape))
    model.add(Conv2D(128, (5, 5), padding='same', strides=(1, 1), name='conv1', activation='relu', 
                     kernel_initializer='glorot_uniform', kernel_regularizer=regularizer))
    model.add(MaxPool2D((9, 9), strides=(3, 3)))

    model.add(Conv2D(64, (5, 5), padding='same', strides=(1, 1), name='conv2', activation='relu', 
                     kernel_initializer='glorot_uniform', kernel_regularizer=regularizer))
    model.add(MaxPool2D((7, 7), strides=(3, 3)))
    
    model.add(Conv2D(32, (3, 3), padding='same', strides=(1, 1), name='conv3', activation='relu', 
                     kernel_initializer='glorot_uniform', kernel_regularizer=regularizer))
    model.add(MaxPool2D((5, 5), strides=(2, 2)))

    model.add(Conv2D(32, (3, 3), padding='same', strides=(1, 1), name='conv4', activation='relu', 
                     kernel_initializer='glorot_uniform', kernel_regularizer=regularizer))
    model.add(MaxPool2D((3, 3), strides=(2, 2)))    
    
    model.add(Flatten())
    model.add(Dropout(0.5))
    model.add(Dense(64, activation='relu', kernel_initializer='glorot_uniform', name='fc1'))
    model.add(Dropout(0.5))
    model.add(Dense(2, activation='softmax', kernel_initializer='glorot_uniform', name='fc3'))
    
    optimizer = Adam(3.15e-5)
    model.compile(optimizer=optimizer, loss='categorical_crossentropy', metrics=['accuracy'])
    return model
In [15]:
model= parkinson_disease_detection_model(input_shape=(128, 128, 1))
model.summary()
Model: "sequential"
_________________________________________________________________
Layer (type)                 Output Shape              Param #   
=================================================================
conv1 (Conv2D)               (None, 128, 128, 128)     3328      
_________________________________________________________________
max_pooling2d (MaxPooling2D) (None, 40, 40, 128)       0         
_________________________________________________________________
conv2 (Conv2D)               (None, 40, 40, 64)        204864    
_________________________________________________________________
max_pooling2d_1 (MaxPooling2 (None, 12, 12, 64)        0         
_________________________________________________________________
conv3 (Conv2D)               (None, 12, 12, 32)        18464     
_________________________________________________________________
max_pooling2d_2 (MaxPooling2 (None, 4, 4, 32)          0         
_________________________________________________________________
conv4 (Conv2D)               (None, 4, 4, 32)          9248      
_________________________________________________________________
max_pooling2d_3 (MaxPooling2 (None, 1, 1, 32)          0         
_________________________________________________________________
flatten (Flatten)            (None, 32)                0         
_________________________________________________________________
dropout (Dropout)            (None, 32)                0         
_________________________________________________________________
fc1 (Dense)                  (None, 64)                2112      
_________________________________________________________________
dropout_1 (Dropout)          (None, 64)                0         
_________________________________________________________________
fc3 (Dense)                  (None, 2)                 130       
=================================================================
Total params: 238,146
Trainable params: 238,146
Non-trainable params: 0
_________________________________________________________________

Training the Model

In [16]:
hist = model.fit(x_train, y_train, batch_size=128, epochs=70, validation_data=(x_test, y_test))
Epoch 1/70
40/40 [==============================] - 6s 152ms/step - loss: 0.8532 - accuracy: 0.5055 - val_loss: 0.8480 - val_accuracy: 0.5000
Epoch 2/70
40/40 [==============================] - 5s 130ms/step - loss: 0.8452 - accuracy: 0.5008 - val_loss: 0.8413 - val_accuracy: 0.5397
Epoch 3/70
40/40 [==============================] - 5s 130ms/step - loss: 0.8386 - accuracy: 0.5074 - val_loss: 0.8345 - val_accuracy: 0.5000
Epoch 4/70
40/40 [==============================] - 5s 130ms/step - loss: 0.8323 - accuracy: 0.5112 - val_loss: 0.8279 - val_accuracy: 0.5000
Epoch 5/70
40/40 [==============================] - 5s 131ms/step - loss: 0.8266 - accuracy: 0.5094 - val_loss: 0.8225 - val_accuracy: 0.6937
Epoch 6/70
40/40 [==============================] - 5s 131ms/step - loss: 0.8209 - accuracy: 0.5180 - val_loss: 0.8173 - val_accuracy: 0.5857
Epoch 7/70
40/40 [==============================] - 5s 132ms/step - loss: 0.8160 - accuracy: 0.5131 - val_loss: 0.8120 - val_accuracy: 0.5000
Epoch 8/70
40/40 [==============================] - 5s 133ms/step - loss: 0.8115 - accuracy: 0.5139 - val_loss: 0.8061 - val_accuracy: 0.6619
Epoch 9/70
40/40 [==============================] - 5s 134ms/step - loss: 0.8066 - accuracy: 0.5315 - val_loss: 0.8024 - val_accuracy: 0.7365
Epoch 10/70
40/40 [==============================] - 5s 134ms/step - loss: 0.8021 - accuracy: 0.5338 - val_loss: 0.7974 - val_accuracy: 0.6762
Epoch 11/70
40/40 [==============================] - 5s 135ms/step - loss: 0.7965 - accuracy: 0.5546 - val_loss: 0.7913 - val_accuracy: 0.7270
Epoch 12/70
40/40 [==============================] - 5s 135ms/step - loss: 0.7927 - accuracy: 0.5497 - val_loss: 0.7863 - val_accuracy: 0.7444
Epoch 13/70
40/40 [==============================] - 5s 136ms/step - loss: 0.7885 - accuracy: 0.5579 - val_loss: 0.7813 - val_accuracy: 0.6667
Epoch 14/70
40/40 [==============================] - 5s 137ms/step - loss: 0.7836 - accuracy: 0.5757 - val_loss: 0.7747 - val_accuracy: 0.6952
Epoch 15/70
40/40 [==============================] - 5s 137ms/step - loss: 0.7779 - accuracy: 0.5861 - val_loss: 0.7687 - val_accuracy: 0.6857
Epoch 16/70
40/40 [==============================] - 5s 137ms/step - loss: 0.7737 - accuracy: 0.5869 - val_loss: 0.7706 - val_accuracy: 0.6111
Epoch 17/70
40/40 [==============================] - 6s 138ms/step - loss: 0.7669 - accuracy: 0.6070 - val_loss: 0.7532 - val_accuracy: 0.7460
Epoch 18/70
40/40 [==============================] - 6s 138ms/step - loss: 0.7589 - accuracy: 0.6195 - val_loss: 0.7456 - val_accuracy: 0.7048
Epoch 19/70
40/40 [==============================] - 6s 139ms/step - loss: 0.7505 - accuracy: 0.6250 - val_loss: 0.7358 - val_accuracy: 0.6286
Epoch 20/70
40/40 [==============================] - 6s 140ms/step - loss: 0.7393 - accuracy: 0.6579 - val_loss: 0.7209 - val_accuracy: 0.7810
Epoch 21/70
40/40 [==============================] - 6s 141ms/step - loss: 0.7280 - accuracy: 0.6704 - val_loss: 0.7053 - val_accuracy: 0.7825
Epoch 22/70
40/40 [==============================] - 6s 142ms/step - loss: 0.7125 - accuracy: 0.6819 - val_loss: 0.6910 - val_accuracy: 0.7746
Epoch 23/70
40/40 [==============================] - 6s 142ms/step - loss: 0.6954 - accuracy: 0.7052 - val_loss: 0.6944 - val_accuracy: 0.7016
Epoch 24/70
40/40 [==============================] - 6s 143ms/step - loss: 0.6805 - accuracy: 0.7132 - val_loss: 0.6695 - val_accuracy: 0.7079
Epoch 25/70
40/40 [==============================] - 6s 144ms/step - loss: 0.6644 - accuracy: 0.7300 - val_loss: 0.6438 - val_accuracy: 0.8016
Epoch 26/70
40/40 [==============================] - 6s 144ms/step - loss: 0.6525 - accuracy: 0.7347 - val_loss: 0.6367 - val_accuracy: 0.7889
Epoch 27/70
40/40 [==============================] - 6s 144ms/step - loss: 0.6422 - accuracy: 0.7453 - val_loss: 0.6257 - val_accuracy: 0.7556
Epoch 28/70
40/40 [==============================] - 6s 144ms/step - loss: 0.6183 - accuracy: 0.7586 - val_loss: 0.6160 - val_accuracy: 0.7810
Epoch 29/70
40/40 [==============================] - 6s 144ms/step - loss: 0.6113 - accuracy: 0.7635 - val_loss: 0.6100 - val_accuracy: 0.7635
Epoch 30/70
40/40 [==============================] - 6s 145ms/step - loss: 0.6019 - accuracy: 0.7709 - val_loss: 0.6096 - val_accuracy: 0.7254
Epoch 31/70
40/40 [==============================] - 6s 145ms/step - loss: 0.5877 - accuracy: 0.7799 - val_loss: 0.5936 - val_accuracy: 0.7667
Epoch 32/70
40/40 [==============================] - 6s 145ms/step - loss: 0.5776 - accuracy: 0.7874 - val_loss: 0.5725 - val_accuracy: 0.7810
Epoch 33/70
40/40 [==============================] - 6s 145ms/step - loss: 0.5643 - accuracy: 0.7995 - val_loss: 0.5641 - val_accuracy: 0.7968
Epoch 34/70
40/40 [==============================] - 6s 145ms/step - loss: 0.5569 - accuracy: 0.8009 - val_loss: 0.5566 - val_accuracy: 0.8206
Epoch 35/70
40/40 [==============================] - 6s 145ms/step - loss: 0.5507 - accuracy: 0.7960 - val_loss: 0.5541 - val_accuracy: 0.7984
Epoch 36/70
40/40 [==============================] - 6s 145ms/step - loss: 0.5366 - accuracy: 0.8083 - val_loss: 0.5622 - val_accuracy: 0.7508
Epoch 37/70
40/40 [==============================] - 6s 145ms/step - loss: 0.5294 - accuracy: 0.8134 - val_loss: 0.5347 - val_accuracy: 0.8000
Epoch 38/70
40/40 [==============================] - 6s 145ms/step - loss: 0.5293 - accuracy: 0.8089 - val_loss: 0.5471 - val_accuracy: 0.7778
Epoch 39/70
40/40 [==============================] - 6s 145ms/step - loss: 0.5102 - accuracy: 0.8234 - val_loss: 0.5163 - val_accuracy: 0.8365
Epoch 40/70
40/40 [==============================] - 6s 145ms/step - loss: 0.5103 - accuracy: 0.8163 - val_loss: 0.5042 - val_accuracy: 0.8365
Epoch 41/70
40/40 [==============================] - 6s 145ms/step - loss: 0.4947 - accuracy: 0.8292 - val_loss: 0.4964 - val_accuracy: 0.8349
Epoch 42/70
40/40 [==============================] - 6s 145ms/step - loss: 0.4959 - accuracy: 0.8286 - val_loss: 0.4965 - val_accuracy: 0.8397
Epoch 43/70
40/40 [==============================] - 6s 145ms/step - loss: 0.4940 - accuracy: 0.8339 - val_loss: 0.4890 - val_accuracy: 0.8365
Epoch 44/70
40/40 [==============================] - 6s 145ms/step - loss: 0.4871 - accuracy: 0.8339 - val_loss: 0.4846 - val_accuracy: 0.8413
Epoch 45/70
40/40 [==============================] - 6s 145ms/step - loss: 0.4729 - accuracy: 0.8429 - val_loss: 0.4777 - val_accuracy: 0.8429
Epoch 46/70
40/40 [==============================] - 6s 146ms/step - loss: 0.4671 - accuracy: 0.8474 - val_loss: 0.4727 - val_accuracy: 0.8286
Epoch 47/70
40/40 [==============================] - 6s 145ms/step - loss: 0.4597 - accuracy: 0.8459 - val_loss: 0.4844 - val_accuracy: 0.8365
Epoch 48/70
40/40 [==============================] - 6s 145ms/step - loss: 0.4480 - accuracy: 0.8507 - val_loss: 0.4673 - val_accuracy: 0.8429
Epoch 49/70
40/40 [==============================] - 6s 145ms/step - loss: 0.4454 - accuracy: 0.8554 - val_loss: 0.4766 - val_accuracy: 0.8365
Epoch 50/70
40/40 [==============================] - 6s 145ms/step - loss: 0.4398 - accuracy: 0.8550 - val_loss: 0.4587 - val_accuracy: 0.8270
Epoch 51/70
40/40 [==============================] - 6s 145ms/step - loss: 0.4339 - accuracy: 0.8613 - val_loss: 0.4576 - val_accuracy: 0.8508
Epoch 52/70
40/40 [==============================] - 6s 145ms/step - loss: 0.4194 - accuracy: 0.8728 - val_loss: 0.4487 - val_accuracy: 0.8508
Epoch 53/70
40/40 [==============================] - 6s 145ms/step - loss: 0.4210 - accuracy: 0.8680 - val_loss: 0.4531 - val_accuracy: 0.8476
Epoch 54/70
40/40 [==============================] - 6s 145ms/step - loss: 0.4117 - accuracy: 0.8750 - val_loss: 0.4536 - val_accuracy: 0.8619
Epoch 55/70
40/40 [==============================] - 6s 145ms/step - loss: 0.4131 - accuracy: 0.8699 - val_loss: 0.4392 - val_accuracy: 0.8460
Epoch 56/70
40/40 [==============================] - 6s 145ms/step - loss: 0.4019 - accuracy: 0.8777 - val_loss: 0.4381 - val_accuracy: 0.8556
Epoch 57/70
40/40 [==============================] - 6s 145ms/step - loss: 0.4082 - accuracy: 0.8764 - val_loss: 0.4388 - val_accuracy: 0.8492
Epoch 58/70
40/40 [==============================] - 6s 145ms/step - loss: 0.4031 - accuracy: 0.8764 - val_loss: 0.4333 - val_accuracy: 0.8651
Epoch 59/70
40/40 [==============================] - 6s 145ms/step - loss: 0.3874 - accuracy: 0.8865 - val_loss: 0.4784 - val_accuracy: 0.8365
Epoch 60/70
40/40 [==============================] - 6s 145ms/step - loss: 0.3864 - accuracy: 0.8897 - val_loss: 0.4272 - val_accuracy: 0.8651
Epoch 61/70
40/40 [==============================] - 6s 145ms/step - loss: 0.3816 - accuracy: 0.8932 - val_loss: 0.4219 - val_accuracy: 0.8746
Epoch 62/70
40/40 [==============================] - 6s 145ms/step - loss: 0.3800 - accuracy: 0.8867 - val_loss: 0.4203 - val_accuracy: 0.8683
Epoch 63/70
40/40 [==============================] - 6s 145ms/step - loss: 0.3728 - accuracy: 0.8910 - val_loss: 0.4197 - val_accuracy: 0.8587
Epoch 64/70
40/40 [==============================] - 6s 145ms/step - loss: 0.3902 - accuracy: 0.8801 - val_loss: 0.4191 - val_accuracy: 0.8651
Epoch 65/70
40/40 [==============================] - 6s 145ms/step - loss: 0.3596 - accuracy: 0.9049 - val_loss: 0.4269 - val_accuracy: 0.8746
Epoch 66/70
40/40 [==============================] - 6s 145ms/step - loss: 0.3500 - accuracy: 0.9038 - val_loss: 0.4147 - val_accuracy: 0.8841
Epoch 67/70
40/40 [==============================] - 6s 145ms/step - loss: 0.3561 - accuracy: 0.9018 - val_loss: 0.4197 - val_accuracy: 0.8778
Epoch 68/70
40/40 [==============================] - 6s 145ms/step - loss: 0.3487 - accuracy: 0.9079 - val_loss: 0.4402 - val_accuracy: 0.8667
Epoch 69/70
40/40 [==============================] - 6s 145ms/step - loss: 0.3538 - accuracy: 0.8979 - val_loss: 0.4103 - val_accuracy: 0.8857
Epoch 70/70
40/40 [==============================] - 6s 145ms/step - loss: 0.3430 - accuracy: 0.9047 - val_loss: 0.4242 - val_accuracy: 0.8762

Loss and Accuracy Plot

In [17]:
figure = plt.figure(figsize=(10, 10))
plt.plot(hist.history['accuracy'], label='Train_accuracy')
plt.plot(hist.history['val_accuracy'], label='Test_accuracy')
plt.title('Model Accuracy')
plt.xlabel('Epochs')
plt.ylabel('Accuracy')
plt.legend(loc="upper left")
plt.show()

figure2 = plt.figure(figsize=(10, 10))
plt.plot(hist.history['loss'], label='Train_loss')
plt.plot(hist.history['val_loss'], label='Test_loss')
plt.title('Model Loss')
plt.xlabel('Epochs')
plt.ylabel('Loss')
plt.legend(loc="upper left")
plt.show()

Classification Report

In [18]:
ypred = model.predict(x_test)
ypred = np.argmax(ypred, axis=1)
y_test_pred = np.argmax(y_test, axis=1)
print(classification_report(y_test_pred, ypred))
              precision    recall  f1-score   support

           0       0.93      0.81      0.87       315
           1       0.83      0.94      0.88       315

    accuracy                           0.88       630
   macro avg       0.88      0.88      0.88       630
weighted avg       0.88      0.88      0.88       630

Confusion Matrix

In [19]:
matrix = confusion_matrix(y_test_pred, ypred)
df_cm = pd.DataFrame(matrix, index=[0, 1], columns=[0, 1])
figure = plt.figure(figsize=(5, 5))
sns.heatmap(df_cm, annot=True, fmt='d')
Out[19]:
<AxesSubplot:>

Saving the Model

In [20]:
model.save('parkinson_disease_detection.h5')

Testing Model on Images

In [21]:
labels = ['Healthy', 'Parkinson']
image_healthy = cv2.imread('Parkinson_disease_detection/test_image_healthy.png')
image_parkinson = cv2.imread('Parkinson_disease_detection/test_image_parkinson.png')

image_healthy = cv2.resize(image_healthy, (128, 128))
image_healthy = cv2.cvtColor(image_healthy, cv2.COLOR_BGR2GRAY)
image_healthy = np.array(image_healthy)
image_healthy = np.expand_dims(image_healthy, axis=0)
image_healthy = np.expand_dims(image_healthy, axis=-1)

image_parkinson = cv2.resize(image_parkinson, (128, 128))
image_parkinson = cv2.cvtColor(image_parkinson, cv2.COLOR_BGR2GRAY)
image_parkinson = np.array(image_parkinson)
image_parkinson = np.expand_dims(image_parkinson, axis=0)
image_parkinson = np.expand_dims(image_parkinson, axis=-1)
In [22]:
ypred_healthy = model.predict(image_healthy)
ypred_parkinson = model.predict(image_parkinson)
In [23]:
figure = plt.figure(figsize=(2, 2))
img_healthy = np.squeeze(image_healthy, axis=0)
plt.imshow(img_healthy)
plt.axis('off')
plt.title(f'Prediction by the model: {labels[np.argmax(ypred_healthy[0], axis=0)]}')
plt.show()
In [24]:
figure = plt.figure(figsize=(2, 2))
image_parkinson = np.squeeze(image_parkinson, axis=0)
plt.imshow(image_parkinson)
plt.axis('off')
plt.title(f'Prediction by the model: {labels[np.argmax(ypred_parkinson[0], axis=0)]}')
plt.show()

deepCC

In [25]:
!deepCC parkinson_disease_detection.h5
[INFO]
Reading [keras model] 'parkinson_disease_detection.h5'
[SUCCESS]
Saved 'parkinson_disease_detection_deepC/parkinson_disease_detection.onnx'
[INFO]
Reading [onnx model] 'parkinson_disease_detection_deepC/parkinson_disease_detection.onnx'
[INFO]
Model info:
  ir_vesion : 5
  doc       : 
[WARNING]
[ONNX]: graph-node conv1's attribute auto_pad has no meaningful data.
[WARNING]
[ONNX]: graph-node conv2's attribute auto_pad has no meaningful data.
[WARNING]
[ONNX]: graph-node conv3's attribute auto_pad has no meaningful data.
[WARNING]
[ONNX]: graph-node conv4's attribute auto_pad has no meaningful data.
[WARNING]
[ONNX]: terminal (input/output) input_1's shape is less than 1. Changing it to 1.
[WARNING]
[ONNX]: terminal (input/output) fc3's shape is less than 1. Changing it to 1.
WARN (GRAPH): found operator node with the same name (fc3) as io node.
[INFO]
Running DNNC graph sanity check ...
[SUCCESS]
Passed sanity check.
[INFO]
Writing C++ file 'parkinson_disease_detection_deepC/parkinson_disease_detection.cpp'
[INFO]
deepSea model files are ready in 'parkinson_disease_detection_deepC/' 
[RUNNING COMMAND]
g++ -std=c++11 -O3 -fno-rtti -fno-exceptions -I. -I/opt/tljh/user/lib/python3.7/site-packages/deepC-0.13-py3.7-linux-x86_64.egg/deepC/include -isystem /opt/tljh/user/lib/python3.7/site-packages/deepC-0.13-py3.7-linux-x86_64.egg/deepC/packages/eigen-eigen-323c052e1731 "parkinson_disease_detection_deepC/parkinson_disease_detection.cpp" -D_AITS_MAIN -o "parkinson_disease_detection_deepC/parkinson_disease_detection.exe"
[RUNNING COMMAND]
size "parkinson_disease_detection_deepC/parkinson_disease_detection.exe"
   text	   data	    bss	    dec	    hex	filename
1133765	   3784	    760	1138309	 115e85	parkinson_disease_detection_deepC/parkinson_disease_detection.exe
[SUCCESS]
Saved model as executable "parkinson_disease_detection_deepC/parkinson_disease_detection.exe"