Cardiotocography under a microscope

cardiotocography

Cardiotocography under a microscope


This is a short study of the heart rate and other characteristics of 2126 fetuses. The fetuses are classified in 10 classes of heart behavior, and 3 classes of disease risk ( NSP ). For more information on the parameters of the dataset, they are widely explained in the dataset description.

In a first part we will explore our dataset to try to find some valuable insights hidden in the numbers. To do that we will use dimensionality reduction, first through PCA, then using an autoencoder. We will analyze the results and compare them to our original dataset.

In a second part we will try to model a tool that could be useful in detecting the possible pathology. In order to do this, we will test a number of Machine Learning classifiers, we will try to find the most accurate for this problem and then tune it to its best accuracy. We will then compare the results of the best classifier we found with the results of a small artificial neural network and see which one does best.

Importing the libraries and dataset

Here we want to do a very basic preprocessing of the data and take a general look at the shape of the problem.

In [1]:
import numpy as np
import matplotlib.pyplot as plt
import pandas as pd
dataset = pd.read_excel(r'../input/CTG.xls', sheetname=1, skiprows=1) # Get the data
/opt/conda/lib/python3.6/site-packages/pandas/util/_decorators.py:118: FutureWarning: The `sheetname` keyword is deprecated, use `sheet_name` instead
  return func(*args, **kwargs)
In [2]:
dataset.head()
Out[2]:
b e AC FM UC DL DS DP DR Unnamed: 9 ... E AD DE LD FS SUSP Unnamed: 42 CLASS Unnamed: 44 NSP
0 240.0 357.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 NaN ... -1.0 -1.0 -1.0 -1.0 1.0 -1.0 NaN 9.0 NaN 2.0
1 5.0 632.0 4.0 0.0 4.0 2.0 0.0 0.0 0.0 NaN ... -1.0 1.0 -1.0 -1.0 -1.0 -1.0 NaN 6.0 NaN 1.0
2 177.0 779.0 2.0 0.0 5.0 2.0 0.0 0.0 0.0 NaN ... -1.0 1.0 -1.0 -1.0 -1.0 -1.0 NaN 6.0 NaN 1.0
3 411.0 1192.0 2.0 0.0 6.0 2.0 0.0 0.0 0.0 NaN ... -1.0 1.0 -1.0 -1.0 -1.0 -1.0 NaN 6.0 NaN 1.0
4 533.0 1147.0 4.0 0.0 5.0 0.0 0.0 0.0 0.0 NaN ... -1.0 -1.0 -1.0 -1.0 -1.0 -1.0 NaN 2.0 NaN 1.0

5 rows × 46 columns

We see that a few "extra" columns have been processed and that they don't contain any relevant information ( or any information at all for that matter ). Let's clean up the dataset.

In [3]:
dataset = dataset.dropna(axis=1, how='all') # Got rid of empty columns
dataset = dataset.dropna(axis=0, how='any') # Three rows were REALLY missing information
dataset = dataset.drop(['b','e','DR','Tendency'], axis=1) # No information from such columns...
In [4]:
dataset.head()
Out[4]:
AC FM UC DL DS DP LB AC.1 FM.1 UC.1 ... C D E AD DE LD FS SUSP CLASS NSP
0 0.0 0.0 0.0 0.0 0.0 0.0 120.0 0.000000 0.0 0.000000 ... -1.0 -1.0 -1.0 -1.0 -1.0 -1.0 1.0 -1.0 9.0 2.0
1 4.0 0.0 4.0 2.0 0.0 0.0 132.0 0.006380 0.0 0.006380 ... -1.0 -1.0 -1.0 1.0 -1.0 -1.0 -1.0 -1.0 6.0 1.0
2 2.0 0.0 5.0 2.0 0.0 0.0 133.0 0.003322 0.0 0.008306 ... -1.0 -1.0 -1.0 1.0 -1.0 -1.0 -1.0 -1.0 6.0 1.0
3 2.0 0.0 6.0 2.0 0.0 0.0 134.0 0.002561 0.0 0.007682 ... -1.0 -1.0 -1.0 1.0 -1.0 -1.0 -1.0 -1.0 6.0 1.0
4 4.0 0.0 5.0 0.0 0.0 0.0 132.0 0.006515 0.0 0.008143 ... -1.0 -1.0 -1.0 -1.0 -1.0 -1.0 -1.0 -1.0 2.0 1.0

5 rows × 38 columns

Much better.

Data exploration

In this part we are going to explore the dataset in a way that would make it more understable. For this purpose we are going to use correlations and graphic representations of the dataset. Since our dataset is composed of 38 columns, we will either choose which one to represent or use different dimensionality reduction techniques to present it on a 3D or 2D plot.

Distrubution of the different classes

In [5]:
import matplotlib.cm as cm # To make pretty graphs
import seaborn as sns
color = sns.color_palette()

cnt_srs = dataset['CLASS'].value_counts()
cnt_srs = cnt_srs.head(10)
plt.figure(figsize=(10,6))
sns.barplot(cnt_srs.index, cnt_srs.values, alpha=0.8, color=color[3])
N = 10
ind = np.arange(N) 
plt.xticks(ind, ('A', 'B', 'C', 'D', 'E', 'AD', 'DE', 'LD', 'FS', 'SUSP'))
plt.ylabel('Number of Cases', fontsize=12)
plt.title('Distribution of Classes', fontsize=18)
plt.show()

A wide majority of our cases is represented by the fetus classes B, A, AD, and DE. We want to know what they are made of to fully understand the distribution of the problem.

Distribution of the patholgies in the general problem

In [6]:
import matplotlib.cm as cm # To make pretty graphs
import seaborn as sns
color = sns.color_palette()

cnt_srs = dataset['NSP'].value_counts()
cnt_srs = cnt_srs.head(10)
plt.figure(figsize=(10,6))
sns.barplot(cnt_srs.index, cnt_srs.values, alpha=0.8, color=color[3])
N = 3
ind = np.arange(N) 
plt.xticks(ind, ('Normal','Suspect', 'Pathologic'))
plt.ylabel('Number of Cases', fontsize=12)
plt.title('Distribution of NSP', fontsize=18)
plt.show()

A large majority of our dataset shows a normal behavior while suspect and pathologic behavior are more rare.

Distribution of the NSP in the fetus classes

In [7]:
x = dataset[['CLASS','NSP']]
N = 10
zeroesddf = pd.DataFrame(data=np.zeros(10,),index=[1,2,3,4,5,6,7,8,9,10])

ind = np.arange(N)    # the x locations for the groups
width = 0.50    # the width of the bars: can also be len(x) sequence

plt.figure(figsize=(12,6))

for nsp_i in [1,2,3]:
    norm = x.loc[(x['NSP']==nsp_i)].drop('NSP', axis=1)
    norm = (pd.value_counts(norm['CLASS'].values, sort=False)).sort_index()
    norm = pd.DataFrame(data=norm, index=norm.index)
    norm = zeroesddf.add(norm,axis='index',fill_value=0) 
    norm = (norm.values).reshape(-1)
    if nsp_i == 1 :
        p1 = plt.bar(ind,norm, width)
    elif nsp_i == 2 :
        p2 = plt.bar(ind,norm,width)
    elif nsp_i == 3 :
        p3 = plt.bar(ind,norm,width)
    
plt.ylabel('Number of Cases')
plt.title('Distribution of NSP accross the classes')
plt.xticks(ind, ('A', 'B', 'C', 'D', 'E', 'AD', 'DE', 'LD', 'FS', 'SUSP'))
plt.legend((p1[0], p2[0], p3[0]), ('Normal', 'Suspect', 'Pathologic'))
plt.show()

For some of the classes the interpretation was obvious from start. As such the "SUSP" class contains a wide majority of cases classified as suspect, and LD and FS are mostly composed of cases classified as pathologic.

Two classes present interesting and different results. The "E" class, mostly composed of suspect cases but with a different behaviour, and the "DE" class that amongst a wide variety of cases classified as normal also contains a non negligeable amount of suspect cases.

Correlation map

Building the correlation map will help us understand which parameters are the most essential in determining if a fetus has a pathological behavior. Thankfully, the NSP parameter that describes the heatlth of the fetus is in increasing numerical order, and can be easily interpreted through this map. It can also help us understand what makes the other 10 classes by showing clearly their most relevant features.

In [8]:
sns.set(style="white")
# Generate a large random dataset
d = dataset

# Compute the correlation matrix
corr = d.corr()

# Generate a mask for the upper triangle
mask = np.zeros_like(corr, dtype=np.bool)
mask[np.triu_indices_from(mask)] = True

# Set up the matplotlib figure
f, ax = plt.subplots(figsize=(11, 9))

# Generate a custom diverging colormap
cmap = sns.diverging_palette(220, 10, as_cmap=True)

# Draw the heatmap with the mask and correct aspect ratio
sns.heatmap(corr, mask=mask, cmap=cmap, vmax=.3, center=0,
            square=True, linewidths=.5, cbar_kws={"shrink": .5})
Out[8]:
<matplotlib.axes._subplots.AxesSubplot at 0x7f1da034aa90>

The map does not show any strong positive correlation between the parameters describing the fetus and its NSP class. The highest we can see on the map are the DP value(number of prolongued decelerations per second) and ALTV value (percentage of time with abnormal long term variability).

Let's keep an eye on these values.

Dimensionality Reduction

Can we get a clear representation of our data using dimensionality reduction techniques ? In this part, we will try a few of them.

First we need to process the data to a format that can fit these algorithms.

In [9]:
# Preparing our variables
X = dataset.iloc[:,:-2].values # We got rid of the class value to focus on the FHR diagnosis
y = dataset.iloc[:,-1].values # Containing the FHR diagnosis

# Splitting the dataset into the Training set and Test set
from sklearn.cross_validation import train_test_split
X_train, X_test, y_train, y_test = train_test_split(X, y, test_size = 0.25, random_state = 0)

# Feature Scaling
from sklearn.preprocessing import StandardScaler
sc = StandardScaler()
X_train = sc.fit_transform(X_train)
X_test = sc.transform(X_test)
/opt/conda/lib/python3.6/site-packages/sklearn/cross_validation.py:41: DeprecationWarning: This module was deprecated in version 0.18 in favor of the model_selection module into which all the refactored classes and functions are moved. Also note that the interface of the new CV iterators are different from that of this module. This module will be removed in 0.20.
  "This module will be removed in 0.20.", DeprecationWarning)

Applying Kernel PCA

We will use the different kernels available in sklearn to see if any of them can help us represent the data.

In [10]:
from sklearn.decomposition import KernelPCA

names = [
         'Linear Kernel',
         'Polynomial Kernel',
         'RBF Kernel',
         'Sigmoid Kernel',
         'Cosine Kernel'
         ]

classifiers = [
    KernelPCA(n_components = 3, kernel = 'linear'),
    KernelPCA(n_components = 3, kernel = 'poly', gamma= 0.00001),
    KernelPCA(n_components = 3, kernel = 'rbf', gamma= 0.00001),
    KernelPCA(n_components = 3, kernel = 'sigmoid', gamma= 0.00001),
    KernelPCA(n_components = 3, kernel = 'cosine')
]

models=zip(names,classifiers)
   
for name, kpca in models:
    X_PCA = kpca.fit_transform(X_train)
    
    from mpl_toolkits.mplot3d import axes3d
    from matplotlib import style
    style.use('ggplot')
    
    fig = plt.figure(figsize=(10,6))
    ax1 = fig.add_subplot(111, projection='3d')
    loc = [1,2,3]
    classes = ['Normal','Suspect','Pathologic']
    x3d = X_PCA[:,0]
    y3d = X_PCA[:,1]
    z3d = X_PCA[:,2]

    plot = ax1.scatter(x3d, y3d, z3d, c=y_train, cmap="viridis")
    ax1.set_xlabel('PC1')
    ax1.set_ylabel('PC2')
    ax1.set_zlabel('PC3')
    cb = plt.colorbar(plot)
    cb.set_ticks(loc)
    cb.set_ticklabels(classes)

    plt.title(name)
    plt.show()

Regardless of the kernels we used as examples and regardless of the different parameters we tried for such kernels off-screen, we could not get the PCA technique to represent the problem on a 3D graph in a way that was clear and understandable. We added the colors on the graphs to show where the different NSP groups were represented. It clearly shows that the PCA did not perform efficiently when it comes to separate the NSP groups. Yet, something interesting came out of it. Every kernel we used created two different groups for the "Pathologic" class of the NSP. One is always close to the "Suspect" group of points and one is always far from it. It shows a subclassification amongst the "Suspect" group, some of them being more prone to evolve in a pathology than others.

Using an Autoencoder for Dimensionality reduction

Autoencoders have proven their efficiency in many different cases. When it comes to dimensionality reduction we have yet to find a technique more elegant and more accurate. We're gonna build an autoencoder from scratch, use it to encode the data that we will then put on a 3D graph to compare it with our previous results. From here, we will refer to the autoencoder as AE.

In [11]:
from numpy.random import seed
from sklearn.preprocessing import minmax_scale
from keras.layers import Input, Dense
from keras.models import Model

X = dataset.iloc[:,:-1].values # Put back the class value to use it later

 
# Feature scaling for the AE
sX = minmax_scale(X, axis = 0)
ncol = 36
X_train_auto, X_test_auto, y_train_auto, y_test_auto = train_test_split(sX, y, train_size = 0.8, random_state = seed(2017))
 
Class_train_auto = X_train_auto[:, 36] # These two columns will be used for comparison
Class_test_auto = X_test_auto[:,36]    # later on

X_train_auto = np.delete(X_train_auto, 36, 1)  # But theyr are not needed
X_test_auto = np.delete(X_test_auto, 36, 1)  # as of right now

input_dim = Input(shape = (ncol, ))

# Define the dimension of the encoder
encoding_dim = 3

# Define the encoder layer
encoded = Dense(encoding_dim, activation = 'relu')(input_dim)

# Define the decoder layer
decoded = Dense(ncol, activation = 'sigmoid')(encoded)

# Combine the layers into a model to create the AE
autoencoder = Model(input = input_dim, output = decoded)

# Configure and train the AE
autoencoder.compile(optimizer = 'adadelta', loss = 'binary_crossentropy')
autoencoder.fit(X_train_auto, X_train_auto, nb_epoch = 150, batch_size = 25, shuffle = True, validation_data = (X_test_auto, X_test_auto))

# Get the encoded data and reduced dimmension
encoder = Model(input = input_dim, output = encoded)
encoded_input = Input(shape = (encoding_dim, ))
encoded_out = encoder.predict(X_test_auto)
/opt/conda/lib/python3.6/site-packages/h5py/__init__.py:36: FutureWarning: Conversion of the second argument of issubdtype from `float` to `np.floating` is deprecated. In future, it will be treated as `np.float64 == np.dtype(float).type`.
  from ._conv import register_converters as _register_converters
Using TensorFlow backend.
/opt/conda/lib/python3.6/site-packages/ipykernel_launcher.py:34: UserWarning: Update your `Model` call to the Keras 2 API: `Model(inputs=Tensor("in..., outputs=Tensor("de...)`
/opt/conda/lib/python3.6/site-packages/ipykernel_launcher.py:38: UserWarning: The `nb_epoch` argument in `fit` has been renamed `epochs`.
Train on 1700 samples, validate on 426 samples
Epoch 1/150
1700/1700 [==============================] - 0s 258us/step - loss: 0.6414 - val_loss: 0.5299
Epoch 2/150
1700/1700 [==============================] - 0s 71us/step - loss: 0.4285 - val_loss: 0.3835
Epoch 3/150
1700/1700 [==============================] - 0s 68us/step - loss: 0.3794 - val_loss: 0.3745
Epoch 4/150
1700/1700 [==============================] - 0s 71us/step - loss: 0.3744 - val_loss: 0.3713
Epoch 5/150
1700/1700 [==============================] - 0s 72us/step - loss: 0.3717 - val_loss: 0.3687
Epoch 6/150
1700/1700 [==============================] - 0s 73us/step - loss: 0.3691 - val_loss: 0.3661
Epoch 7/150
1700/1700 [==============================] - 0s 69us/step - loss: 0.3665 - val_loss: 0.3633
Epoch 8/150
1700/1700 [==============================] - 0s 70us/step - loss: 0.3638 - val_loss: 0.3605
Epoch 9/150
1700/1700 [==============================] - 0s 69us/step - loss: 0.3609 - val_loss: 0.3574
Epoch 10/150
1700/1700 [==============================] - 0s 72us/step - loss: 0.3580 - val_loss: 0.3545
Epoch 11/150
1700/1700 [==============================] - 0s 72us/step - loss: 0.3552 - val_loss: 0.3516
Epoch 12/150
1700/1700 [==============================] - 0s 73us/step - loss: 0.3525 - val_loss: 0.3488
Epoch 13/150
1700/1700 [==============================] - 0s 73us/step - loss: 0.3496 - val_loss: 0.3458
Epoch 14/150
1700/1700 [==============================] - 0s 71us/step - loss: 0.3464 - val_loss: 0.3426
Epoch 15/150
1700/1700 [==============================] - 0s 71us/step - loss: 0.3430 - val_loss: 0.3390
Epoch 16/150
1700/1700 [==============================] - 0s 71us/step - loss: 0.3389 - val_loss: 0.3346
Epoch 17/150
1700/1700 [==============================] - 0s 73us/step - loss: 0.3344 - val_loss: 0.3300
Epoch 18/150
1700/1700 [==============================] - 0s 72us/step - loss: 0.3298 - val_loss: 0.3255
Epoch 19/150
1700/1700 [==============================] - 0s 73us/step - loss: 0.3255 - val_loss: 0.3214
Epoch 20/150
1700/1700 [==============================] - 0s 77us/step - loss: 0.3218 - val_loss: 0.3180
Epoch 21/150
1700/1700 [==============================] - 0s 70us/step - loss: 0.3188 - val_loss: 0.3153
Epoch 22/150
1700/1700 [==============================] - 0s 70us/step - loss: 0.3164 - val_loss: 0.3130
Epoch 23/150
1700/1700 [==============================] - 0s 72us/step - loss: 0.3144 - val_loss: 0.3112
Epoch 24/150
1700/1700 [==============================] - 0s 72us/step - loss: 0.3127 - val_loss: 0.3096
Epoch 25/150
1700/1700 [==============================] - 0s 69us/step - loss: 0.3113 - val_loss: 0.3082
Epoch 26/150
1700/1700 [==============================] - 0s 72us/step - loss: 0.3101 - val_loss: 0.3070
Epoch 27/150
1700/1700 [==============================] - 0s 71us/step - loss: 0.3090 - val_loss: 0.3059
Epoch 28/150
1700/1700 [==============================] - 0s 73us/step - loss: 0.3080 - val_loss: 0.3050
Epoch 29/150
1700/1700 [==============================] - 0s 70us/step - loss: 0.3071 - val_loss: 0.3041
Epoch 30/150
1700/1700 [==============================] - 0s 73us/step - loss: 0.3063 - val_loss: 0.3033
Epoch 31/150
1700/1700 [==============================] - 0s 73us/step - loss: 0.3055 - val_loss: 0.3026
Epoch 32/150
1700/1700 [==============================] - 0s 69us/step - loss: 0.3048 - val_loss: 0.3019
Epoch 33/150
1700/1700 [==============================] - 0s 71us/step - loss: 0.3042 - val_loss: 0.3012
Epoch 34/150
1700/1700 [==============================] - 0s 71us/step - loss: 0.3035 - val_loss: 0.3005
Epoch 35/150
1700/1700 [==============================] - 0s 72us/step - loss: 0.3030 - val_loss: 0.3001
Epoch 36/150
1700/1700 [==============================] - 0s 71us/step - loss: 0.3024 - val_loss: 0.2994
Epoch 37/150
1700/1700 [==============================] - 0s 72us/step - loss: 0.3018 - val_loss: 0.2989
Epoch 38/150
1700/1700 [==============================] - 0s 72us/step - loss: 0.3013 - val_loss: 0.2983
Epoch 39/150
1700/1700 [==============================] - 0s 70us/step - loss: 0.3008 - val_loss: 0.2978
Epoch 40/150
1700/1700 [==============================] - 0s 71us/step - loss: 0.3003 - val_loss: 0.2974
Epoch 41/150
1700/1700 [==============================] - 0s 69us/step - loss: 0.2999 - val_loss: 0.2968
Epoch 42/150
1700/1700 [==============================] - 0s 67us/step - loss: 0.2994 - val_loss: 0.2963
Epoch 43/150
1700/1700 [==============================] - 0s 73us/step - loss: 0.2989 - val_loss: 0.2958
Epoch 44/150
1700/1700 [==============================] - 0s 72us/step - loss: 0.2985 - val_loss: 0.2954
Epoch 45/150
1700/1700 [==============================] - 0s 71us/step - loss: 0.2980 - val_loss: 0.2948
Epoch 46/150
1700/1700 [==============================] - 0s 71us/step - loss: 0.2975 - val_loss: 0.2944
Epoch 47/150
1700/1700 [==============================] - 0s 72us/step - loss: 0.2971 - val_loss: 0.2938
Epoch 48/150
1700/1700 [==============================] - 0s 70us/step - loss: 0.2966 - val_loss: 0.2933
Epoch 49/150
1700/1700 [==============================] - 0s 70us/step - loss: 0.2962 - val_loss: 0.2928
Epoch 50/150
1700/1700 [==============================] - 0s 71us/step - loss: 0.2957 - val_loss: 0.2924
Epoch 51/150
1700/1700 [==============================] - 0s 72us/step - loss: 0.2953 - val_loss: 0.2919
Epoch 52/150
1700/1700 [==============================] - 0s 73us/step - loss: 0.2949 - val_loss: 0.2914
Epoch 53/150
1700/1700 [==============================] - 0s 72us/step - loss: 0.2945 - val_loss: 0.2909
Epoch 54/150
1700/1700 [==============================] - 0s 72us/step - loss: 0.2940 - val_loss: 0.2905
Epoch 55/150
1700/1700 [==============================] - 0s 72us/step - loss: 0.2936 - val_loss: 0.2901
Epoch 56/150
1700/1700 [==============================] - 0s 71us/step - loss: 0.2933 - val_loss: 0.2896
Epoch 57/150
1700/1700 [==============================] - 0s 72us/step - loss: 0.2929 - val_loss: 0.2892
Epoch 58/150
1700/1700 [==============================] - 0s 71us/step - loss: 0.2925 - val_loss: 0.2888
Epoch 59/150
1700/1700 [==============================] - 0s 72us/step - loss: 0.2921 - val_loss: 0.2884
Epoch 60/150
1700/1700 [==============================] - 0s 70us/step - loss: 0.2918 - val_loss: 0.2880
Epoch 61/150
1700/1700 [==============================] - 0s 70us/step - loss: 0.2915 - val_loss: 0.2877
Epoch 62/150
1700/1700 [==============================] - 0s 70us/step - loss: 0.2911 - val_loss: 0.2873
Epoch 63/150
1700/1700 [==============================] - 0s 69us/step - loss: 0.2908 - val_loss: 0.2870
Epoch 64/150
1700/1700 [==============================] - 0s 71us/step - loss: 0.2905 - val_loss: 0.2867
Epoch 65/150
1700/1700 [==============================] - 0s 72us/step - loss: 0.2903 - val_loss: 0.2864
Epoch 66/150
1700/1700 [==============================] - 0s 74us/step - loss: 0.2900 - val_loss: 0.2861
Epoch 67/150
1700/1700 [==============================] - 0s 71us/step - loss: 0.2897 - val_loss: 0.2858
Epoch 68/150
1700/1700 [==============================] - 0s 72us/step - loss: 0.2895 - val_loss: 0.2856
Epoch 69/150
1700/1700 [==============================] - 0s 71us/step - loss: 0.2893 - val_loss: 0.2853
Epoch 70/150
1700/1700 [==============================] - 0s 73us/step - loss: 0.2890 - val_loss: 0.2851
Epoch 71/150
1700/1700 [==============================] - 0s 73us/step - loss: 0.2888 - val_loss: 0.2849
Epoch 72/150
1700/1700 [==============================] - 0s 71us/step - loss: 0.2886 - val_loss: 0.2846
Epoch 73/150
1700/1700 [==============================] - 0s 72us/step - loss: 0.2884 - val_loss: 0.2844
Epoch 74/150
1700/1700 [==============================] - 0s 72us/step - loss: 0.2882 - val_loss: 0.2842
Epoch 75/150
1700/1700 [==============================] - 0s 72us/step - loss: 0.2880 - val_loss: 0.2839
Epoch 76/150
1700/1700 [==============================] - 0s 73us/step - loss: 0.2878 - val_loss: 0.2838
Epoch 77/150
1700/1700 [==============================] - 0s 72us/step - loss: 0.2877 - val_loss: 0.2836
Epoch 78/150
1700/1700 [==============================] - 0s 74us/step - loss: 0.2875 - val_loss: 0.2834
Epoch 79/150
1700/1700 [==============================] - 0s 77us/step - loss: 0.2873 - val_loss: 0.2832
Epoch 80/150
1700/1700 [==============================] - 0s 72us/step - loss: 0.2871 - val_loss: 0.2831
Epoch 81/150
1700/1700 [==============================] - 0s 75us/step - loss: 0.2870 - val_loss: 0.2829
Epoch 82/150
1700/1700 [==============================] - 0s 73us/step - loss: 0.2869 - val_loss: 0.2827
Epoch 83/150
1700/1700 [==============================] - 0s 74us/step - loss: 0.2867 - val_loss: 0.2826
Epoch 84/150
1700/1700 [==============================] - 0s 73us/step - loss: 0.2866 - val_loss: 0.2825
Epoch 85/150
1700/1700 [==============================] - 0s 74us/step - loss: 0.2864 - val_loss: 0.2823
Epoch 86/150
1700/1700 [==============================] - 0s 74us/step - loss: 0.2863 - val_loss: 0.2821
Epoch 87/150
1700/1700 [==============================] - 0s 71us/step - loss: 0.2862 - val_loss: 0.2820
Epoch 88/150
1700/1700 [==============================] - 0s 70us/step - loss: 0.2861 - val_loss: 0.2819
Epoch 89/150
1700/1700 [==============================] - 0s 71us/step - loss: 0.2860 - val_loss: 0.2817
Epoch 90/150
1700/1700 [==============================] - 0s 71us/step - loss: 0.2858 - val_loss: 0.2817
Epoch 91/150
1700/1700 [==============================] - 0s 71us/step - loss: 0.2857 - val_loss: 0.2815
Epoch 92/150
1700/1700 [==============================] - 0s 71us/step - loss: 0.2856 - val_loss: 0.2814
Epoch 93/150
1700/1700 [==============================] - 0s 71us/step - loss: 0.2855 - val_loss: 0.2813
Epoch 94/150
1700/1700 [==============================] - 0s 73us/step - loss: 0.2854 - val_loss: 0.2812
Epoch 95/150
1700/1700 [==============================] - 0s 72us/step - loss: 0.2853 - val_loss: 0.2811
Epoch 96/150
1700/1700 [==============================] - 0s 72us/step - loss: 0.2852 - val_loss: 0.2810
Epoch 97/150
1700/1700 [==============================] - 0s 71us/step - loss: 0.2851 - val_loss: 0.2809
Epoch 98/150
1700/1700 [==============================] - 0s 70us/step - loss: 0.2850 - val_loss: 0.2807
Epoch 99/150
1700/1700 [==============================] - 0s 70us/step - loss: 0.2849 - val_loss: 0.2806
Epoch 100/150
1700/1700 [==============================] - 0s 70us/step - loss: 0.2848 - val_loss: 0.2805
Epoch 101/150
1700/1700 [==============================] - 0s 67us/step - loss: 0.2847 - val_loss: 0.2805
Epoch 102/150
1700/1700 [==============================] - 0s 70us/step - loss: 0.2846 - val_loss: 0.2804
Epoch 103/150
1700/1700 [==============================] - 0s 71us/step - loss: 0.2845 - val_loss: 0.2803
Epoch 104/150
1700/1700 [==============================] - 0s 70us/step - loss: 0.2844 - val_loss: 0.2802
Epoch 105/150
1700/1700 [==============================] - 0s 68us/step - loss: 0.2843 - val_loss: 0.2801
Epoch 106/150
1700/1700 [==============================] - 0s 67us/step - loss: 0.2842 - val_loss: 0.2800
Epoch 107/150
1700/1700 [==============================] - 0s 71us/step - loss: 0.2842 - val_loss: 0.2799
Epoch 108/150
1700/1700 [==============================] - 0s 70us/step - loss: 0.2841 - val_loss: 0.2798
Epoch 109/150
1700/1700 [==============================] - 0s 69us/step - loss: 0.2840 - val_loss: 0.2798
Epoch 110/150
1700/1700 [==============================] - 0s 71us/step - loss: 0.2839 - val_loss: 0.2797
Epoch 111/150
1700/1700 [==============================] - 0s 70us/step - loss: 0.2838 - val_loss: 0.2796
Epoch 112/150
1700/1700 [==============================] - 0s 70us/step - loss: 0.2837 - val_loss: 0.2795
Epoch 113/150
1700/1700 [==============================] - 0s 70us/step - loss: 0.2837 - val_loss: 0.2794
Epoch 114/150
1700/1700 [==============================] - 0s 70us/step - loss: 0.2836 - val_loss: 0.2793
Epoch 115/150
1700/1700 [==============================] - 0s 69us/step - loss: 0.2835 - val_loss: 0.2793
Epoch 116/150
1700/1700 [==============================] - 0s 70us/step - loss: 0.2834 - val_loss: 0.2792
Epoch 117/150
1700/1700 [==============================] - 0s 72us/step - loss: 0.2833 - val_loss: 0.2791
Epoch 118/150
1700/1700 [==============================] - 0s 69us/step - loss: 0.2833 - val_loss: 0.2791
Epoch 119/150
1700/1700 [==============================] - 0s 71us/step - loss: 0.2832 - val_loss: 0.2790
Epoch 120/150
1700/1700 [==============================] - 0s 72us/step - loss: 0.2831 - val_loss: 0.2789
Epoch 121/150
1700/1700 [==============================] - 0s 73us/step - loss: 0.2830 - val_loss: 0.2788
Epoch 122/150
1700/1700 [==============================] - 0s 73us/step - loss: 0.2830 - val_loss: 0.2787
Epoch 123/150
1700/1700 [==============================] - 0s 71us/step - loss: 0.2829 - val_loss: 0.2787
Epoch 124/150
1700/1700 [==============================] - 0s 71us/step - loss: 0.2828 - val_loss: 0.2786
Epoch 125/150
1700/1700 [==============================] - 0s 70us/step - loss: 0.2828 - val_loss: 0.2785
Epoch 126/150
1700/1700 [==============================] - 0s 70us/step - loss: 0.2827 - val_loss: 0.2785
Epoch 127/150
1700/1700 [==============================] - 0s 71us/step - loss: 0.2826 - val_loss: 0.2784
Epoch 128/150
1700/1700 [==============================] - 0s 70us/step - loss: 0.2826 - val_loss: 0.2784
Epoch 129/150
1700/1700 [==============================] - 0s 71us/step - loss: 0.2825 - val_loss: 0.2783
Epoch 130/150
1700/1700 [==============================] - 0s 70us/step - loss: 0.2824 - val_loss: 0.2782
Epoch 131/150
1700/1700 [==============================] - 0s 70us/step - loss: 0.2823 - val_loss: 0.2782
Epoch 132/150
1700/1700 [==============================] - 0s 68us/step - loss: 0.2823 - val_loss: 0.2781
Epoch 133/150
1700/1700 [==============================] - 0s 70us/step - loss: 0.2822 - val_loss: 0.2780
Epoch 134/150
1700/1700 [==============================] - 0s 70us/step - loss: 0.2821 - val_loss: 0.2780
Epoch 135/150
1700/1700 [==============================] - 0s 70us/step - loss: 0.2821 - val_loss: 0.2779
Epoch 136/150
1700/1700 [==============================] - 0s 71us/step - loss: 0.2820 - val_loss: 0.2778
Epoch 137/150
1700/1700 [==============================] - 0s 70us/step - loss: 0.2820 - val_loss: 0.2778
Epoch 138/150
1700/1700 [==============================] - 0s 73us/step - loss: 0.2819 - val_loss: 0.2777
Epoch 139/150
1700/1700 [==============================] - 0s 73us/step - loss: 0.2818 - val_loss: 0.2776
Epoch 140/150
1700/1700 [==============================] - 0s 71us/step - loss: 0.2818 - val_loss: 0.2776
Epoch 141/150
1700/1700 [==============================] - 0s 70us/step - loss: 0.2817 - val_loss: 0.2775
Epoch 142/150
1700/1700 [==============================] - 0s 71us/step - loss: 0.2816 - val_loss: 0.2774
Epoch 143/150
1700/1700 [==============================] - 0s 73us/step - loss: 0.2816 - val_loss: 0.2774
Epoch 144/150
1700/1700 [==============================] - 0s 70us/step - loss: 0.2815 - val_loss: 0.2773
Epoch 145/150
1700/1700 [==============================] - 0s 70us/step - loss: 0.2814 - val_loss: 0.2773
Epoch 146/150
1700/1700 [==============================] - 0s 70us/step - loss: 0.2814 - val_loss: 0.2772
Epoch 147/150
1700/1700 [==============================] - 0s 72us/step - loss: 0.2813 - val_loss: 0.2772
Epoch 148/150
1700/1700 [==============================] - 0s 71us/step - loss: 0.2813 - val_loss: 0.2771
Epoch 149/150
1700/1700 [==============================] - 0s 72us/step - loss: 0.2812 - val_loss: 0.2770
Epoch 150/150
1700/1700 [==============================] - 0s 69us/step - loss: 0.2811 - val_loss: 0.2770
/opt/conda/lib/python3.6/site-packages/ipykernel_launcher.py:41: UserWarning: Update your `Model` call to the Keras 2 API: `Model(inputs=Tensor("in..., outputs=Tensor("de...)`
In [12]:
# Visualising the clusters
from mpl_toolkits.mplot3d import axes3d
from matplotlib import style
style.use('ggplot')

fig = plt.figure(figsize=(10,6))
ax1 = fig.add_subplot(111, projection='3d')
ax1.w_xaxis.set_pane_color((0.7, 0.7, 0.7, 1.0)) # During the previous visualisation
ax1.w_yaxis.set_pane_color((0.7, 0.7, 0.7, 1.0)) # the colors were difficult to see
ax1.w_zaxis.set_pane_color((0.7, 0.7, 0.7, 1.0)) # with the light gray background, color tuning

x3d = encoded_out[:,0]
y3d = encoded_out[:,1]
z3d = encoded_out[:,2]

plot = ax1.scatter(x3d, y3d, z3d, c=y_test_auto, cmap="viridis", marker='o')
ax1.set_xlabel('Coded_1')
ax1.set_ylabel('Coded_2')
ax1.set_zlabel('Coded_3')
cb = plt.colorbar(plot)
cb.set_ticks(loc)
cb.set_ticklabels(classes)
plt.show()

The results of the dimensionalty reduction using the autoencoder are not as expected but can still provide interesting insights. We could have expected three different clusters for the three NSP classes, or even ten clusters for the ten fetus classes. Instead we can see around seven clusters. All of them could be understood as their own particular class with different risks for the fetus. For example, we find a cluster of suspect cases that is very close to the cluster of pathological cases, they could be interpreted as highly suspect and hence refine or even re-define the classes we used before, would it be for pathological classification or for the fetus classifiaction. We decided to use the k-means algorithm to efficiently label the groups we found using the autoencoder. We will then insert these new classes in our dataset and study them to see if they can describe the problem in a more efficient way.

In [13]:
from sklearn.cluster import KMeans
kmeans = KMeans(n_clusters = 7, init = 'k-means++', random_state = 42)
y_kmeans = kmeans.fit_predict(encoded_out)
In [14]:
# Visualising the clusters
from mpl_toolkits.mplot3d import axes3d
from matplotlib import style
style.use('ggplot')

fig = plt.figure(figsize=(10,6))
loc = [0,1,2,3,4,5,6]
classes = ['Group 1','Group 2','Group 3','Group 4','Group 5','Group 6','Group 7']
ax1 = fig.add_subplot(111, projection='3d')
ax1.w_xaxis.set_pane_color((0.7, 0.7, 0.7, 1.0)) # During the previous visualisation
ax1.w_yaxis.set_pane_color((0.7, 0.7, 0.7, 1.0)) # the colors were difficult to see
ax1.w_zaxis.set_pane_color((0.7, 0.7, 0.7, 1.0)) # with the light gray background, color tuning

x3d = encoded_out[:,0]
y3d = encoded_out[:,1]
z3d = encoded_out[:,2]

ploto = ax1.scatter(x3d, y3d, z3d, c=y_kmeans, cmap="viridis")
cb = plt.colorbar(ploto)
cb.set_ticks(loc)
cb.set_ticklabels(classes)
ax1.set_xlabel('Coded 1')
ax1.set_ylabel('Coded 2')
ax1.set_zlabel('Coded 3')
plt.title('Clustering of the groups found with the AE')
plt.show()

Now that the new groups have been defined, we will insert them into our dataset and study them the same way we studied the fetus classes given in the dataset. This way we will be able to compare the labelling of the problem and see if the groups found by the autoencoder and by the k-means can represent the problem in a more efficient way.

In [15]:
dataset2 = pd.DataFrame(data=X_test_auto)
dataset2['NSP'] = y_test_auto
dataset2['New Groups'] = y_kmeans
#Succesfully added our new groups to the corresponding dataframe
In [16]:
# Distribution of the newfound classes

import matplotlib.cm as cm # To make pretty graphs
import seaborn as sns
color = sns.color_palette()

cnt_srs = dataset2['New Groups'].value_counts()
cnt_srs = cnt_srs.head(10)
plt.figure(figsize=(12,6))
sns.barplot(cnt_srs.index, cnt_srs.values, alpha=0.8, color=color[3])
N = 7
ind = np.arange(N) 
plt.xticks(ind, ('Group 1','Group 2','Group 3','Group 4','Group 5','Group 6','Group 7'))
plt.ylabel('Number of Cases', fontsize=12)
plt.title('Distribution of the New Classes', fontsize=18)
plt.show()
In [17]:
x = dataset2[['New Groups','NSP']]
plt.figure(figsize=(12,6))
N = 7
zeroesddf = pd.DataFrame(data=np.zeros(7,),index=[0,1,2,3,4,5,6])

ind = np.arange(N)    # the x locations for the groups
width = 0.50    # the width of the bars: can also be len(x) sequence

plt.figure(figsize=(12,6))

for nsp_i in [1,2,3]:
    norm = x.loc[(x['NSP']==nsp_i)].drop('NSP', axis=1)
    norm = (pd.value_counts(norm['New Groups'].values, sort=False)).sort_index()
    norm = pd.DataFrame(data=norm, index=norm.index)
    norm = zeroesddf.add(norm,axis='index',fill_value=0) 
    norm = (norm.values).reshape(-1)
    if nsp_i == 1 :
        p1 = plt.bar(ind,norm, width)
    elif nsp_i == 2 :
        p2 = plt.bar(ind,norm,width)
    elif nsp_i == 3 :
        p3 = plt.bar(ind,norm,width)

plt.ylabel('Number of Cases')
plt.title('Distribution of NSP accross the new classes')
plt.xticks(ind, ('Group 1','Group 2','Group 3','Group 4','Group 5','Group 6','Group 7'))
plt.legend((p1[0], p2[0], p3[0]), ('Normal', 'Suspect', 'Pathologic'))
plt.show()
<matplotlib.figure.Figure at 0x7f1d447db7f0>

The new groups we previously found while using the autoencoder manage to describe the problem under a new light. While previously our fetus classes were made according to the fetus behavior, these ones have been made with a focus on the possibility of a disease. Much like a BIRADS classification used to describe the risk of breast cancer in a patient, these new classes could allow us to do a statistical risk classification for fetuses.

0 : No risks at all, Group 4

1 : Almost no risks, Group 5 & Group 6

2 : Small risk of pathology, Group3

3 : Verified risk of pathology, Group2

4 : Very high risk of pathology, Group 1

5 : Pathology detected, Group 7

For a more accurate classification we could use a bigger test sample and see how the AE behaves. Could we get more classes ? Less ? A better definition of the previous classes ? What if we tried with a different type of distance for the AE ? Or for the k-means ? We want to keep this simple so we will not explore these possibilities right now, instead, we will keep an eye on the new groups we created while solving the classification problem when it comes to NSP.

Comparing the AE clusters with the classes given in the dataset

In [18]:
# Decoding the scaled data
Class_test_auto2 = Class_test_auto

for i in range(426,):
    if Class_test_auto[i]==1. :
        Class_test_auto2[i]=9
    elif Class_test_auto[i]==1/9:
        Class_test_auto2[i]=1
    elif Class_test_auto[i]==2/9:
        Class_test_auto2[i]=2
    elif Class_test_auto[i]==1/3:
        Class_test_auto2[i]=3
    elif Class_test_auto[i]==8/9:
        Class_test_auto2[i]=8
    elif Class_test_auto[i]>0.7 and Class_test_auto[i]<0.8 :
        Class_test_auto2[i]=7
    elif Class_test_auto[i]>0.4 and Class_test_auto[i]<0.5 :
        Class_test_auto2[i]=4
    elif Class_test_auto[i]>0.5 and Class_test_auto[i]<0.6 :
        Class_test_auto2[i]=5
    elif Class_test_auto[i]>0.6 and Class_test_auto[i]<0.7 :
        Class_test_auto2[i]=6
In [19]:
dataset2['CLASS'] = Class_test_auto2

x = dataset2[['CLASS','New Groups']]
N = 10
zeroesddf = pd.DataFrame(data=np.zeros(10,),index=[0,1,2,3,4,5,6,7,8,9])

ind = np.arange(N)    # the x locations for the groups
width = 0.50    # the width of the bars: can also be len(x) sequence

plt.figure(figsize=(12,6))

norm=[]
p=[]
for class_i in [0,1,2,3,4,5,6]:
    temp = x.loc[(x['New Groups']==class_i)].drop('New Groups', axis=1)
    temp = (pd.value_counts(temp['CLASS'].values, sort=False)).sort_index()
    temp = pd.DataFrame(data=temp, index=temp.index)
    temp = zeroesddf.add(temp,axis='index',fill_value=0) 
    temp = (temp.values).reshape(-1)
    norm.append(temp)
    p_temp = plt.bar(ind,norm[class_i], width)
    p.append(p_temp)
        
plt.ylabel('Number of Cases')
plt.title('New vs Old')
plt.xticks(ind, ('A', 'B', 'C', 'D', 'E', 'AD', 'DE', 'LD', 'FS', 'SUSP'))
plt.legend((p[0][0], p[1][0], p[2][0], p[3][0], p[4][0], p[5][0], p[6][0]), ('Group 1', 'Group 2',
                                                               'Group 3','Group 4','Group 5',
                                                              'Group 6','Group 7'))
plt.show()

Overall the clusters we found using the AE behave quite similarly to the ones that were given with the dataset with one little difference. These new clusters focus on a statistical approach of the problem as we explained above. They do not describe entirely the fetus but describe the risk of a pathology. We can see that the main differences are present on the classes that previously presented the most suspect or pathological cases. "SUSP" has been replaced by a hig risk Group 1 that also includes parts of FS. "LD" seems to be entirely interchangeable with Group 7 and shows as we said earlier a verified patholgy in the fetuses. Eventually we realize that the "real" use for such new classes would only be for the last ones that split and refine the result of the suspect and pathological cases.

To conclude on this part, we saw that when the PCA fails to deliver meaningful results, the use of an autoencoder can not only prove efficient in the process of dimensionality reduction, but also can give us some very powerful insights.

Finding the best classifier

As a first part we're gonna implement an SVC and explain each line and each parameter chosen. In a second part we will test out all the classifiers that can apply to this problem that are in the sklearn library, pick out the best one and tune it to get the best results possible.

Using an SVC

In [20]:
from sklearn.svm import SVC # Importing the relevant classifier
classifier = SVC(kernel = 'linear', random_state = 0) # Choosing a linear Kernel for SVC and not K-svc
classifier.fit(X_train, y_train)# Fitting the classifier onto our dataset
score = classifier.score(X_test, y_test, sample_weight=None) # Checking how well it did

# Predicting the Test set results
y_pred = classifier.predict(X_test) # Still all pretty good

# Making the Confusion Matrix
from sklearn.metrics import confusion_matrix
cm1 = confusion_matrix(y_test, y_pred)

print('The score is : '+str(score))   
label = ["N","S","P"]
sns.heatmap(cm1, annot=True, xticklabels=label, yticklabels=label, cmap="YlGnBu")
plt.show()
The score is : 0.981203007518797

A score of 98.1% is fairly high for a non tuned algorithm. It also got a perfect score when it comes to detecting cases classified as pathologic, which is exactly the kind of criteria we're looking for when making a medical classifier. This score and this confusion matrix will be used in the next part as a comparison point with the other scores and confusion matrixes of other algorithms.

Testing all the classifiers

In [21]:
# Importing all the classifiers fitting to the problem from sklearn                             
from sklearn.linear_model import OrthogonalMatchingPursuit,RANSACRegressor,LogisticRegression,ElasticNetCV,HuberRegressor, Ridge, Lasso,LassoCV,Lars,BayesianRidge,SGDClassifier,LogisticRegressionCV,RidgeClassifier
from sklearn.preprocessing import MinMaxScaler
import seaborn as sns
from sklearn.svm import SVC
from sklearn.preprocessing import MinMaxScaler,PolynomialFeatures
from sklearn.model_selection import GridSearchCV
from sklearn.neighbors import KNeighborsClassifier
from sklearn.tree import DecisionTreeClassifier
from sklearn.ensemble import RandomForestClassifier

# Setting different parameters for the grid search
param_grid = {'C': [0.1,1, 10, 100, 1000], 'gamma': [1,0.1,0.01,0.001,0.0001], 'kernel': ['rbf']}

# Turning our problem into a non linear problem
n_col=36
poly = PolynomialFeatures(2)
X_train=poly.fit_transform(X_train)
X_test=poly.fit_transform(X_test)



names = [
         'ElasticNet',
         'SVC',
         'kSVC',
         'KNN',
         'DecisionTree',
         'RandomForestClassifier',
         'GridSearchCV',
         'HuberRegressor',
         'Lasso',
         'LassoCV',
         'Lars',
         'BayesianRidge',
         'SGDClassifier',
         'RidgeClassifier',
         ]

classifiers = [
    ElasticNetCV(cv=10, random_state=0),
    SVC(),
    SVC(kernel = 'rbf', random_state = 0),
    KNeighborsClassifier(n_neighbors = 1),
    DecisionTreeClassifier(),
    RandomForestClassifier(n_estimators = 200),
    GridSearchCV(SVC(),param_grid, refit = True, verbose = 1),
    HuberRegressor(fit_intercept=True, alpha=0.0, max_iter=100,epsilon=2.95),
    #Ridge(fit_intercept=True, alpha=0.0, random_state=0, normalize=True), # Seem to have problems with the Ridge, so I'm taking it out
    Lasso(alpha=0.05),
    LassoCV(),
    Lars(n_nonzero_coefs=10),
    BayesianRidge(),
    SGDClassifier(),
    RidgeClassifier(),
]
correction= [0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0]

models=zip(names,classifiers,correction)
   
for name, clf,correct in models:
    regr=clf.fit(X_train,y_train)
    from sklearn.metrics import classification_report, confusion_matrix, accuracy_score,f1_score, precision_score, recall_score
    
    # Confusion Matrix
    print('--'*40)
    print(name, 'Confusion Matrix')
    conf=confusion_matrix(y_test, np.round(regr.predict(X_test) ) )     
    label = ["N","S","P"]
    sns.heatmap(conf, annot=True, xticklabels=label, yticklabels=label, cmap="YlGnBu")
    plt.show()
    
    print('--'*40)

    # Classification Report
    print(name,'Classification Report')
    classif=classification_report(y_test,np.round( regr.predict(X_test) ) )
    print(classif)


    # Accuracy
    print('--'*40)
    logreg_accuracy = round(accuracy_score(y_test, np.round( regr.predict(X_test) ) ) * 100,2)
    print(name, 'Accuracy', logreg_accuracy,'%')
--------------------------------------------------------------------------------
ElasticNet Confusion Matrix
--------------------------------------------------------------------------------
ElasticNet Classification Report
             precision    recall  f1-score   support

        1.0       0.99      0.99      0.99       410
        2.0       0.96      0.92      0.94        72
        3.0       1.00      0.98      0.99        50
        4.0       0.00      0.00      0.00         0

avg / total       0.98      0.98      0.98       532

--------------------------------------------------------------------------------
ElasticNet Accuracy 98.12 %
/opt/conda/lib/python3.6/site-packages/sklearn/metrics/classification.py:1137: UndefinedMetricWarning: Recall and F-score are ill-defined and being set to 0.0 in labels with no true samples.
  'recall', 'true', average, warn_for)
--------------------------------------------------------------------------------
SVC Confusion Matrix
--------------------------------------------------------------------------------
SVC Classification Report
             precision    recall  f1-score   support

        1.0       0.97      1.00      0.98       410
        2.0       0.97      0.90      0.94        72
        3.0       1.00      0.86      0.92        50

avg / total       0.97      0.97      0.97       532

--------------------------------------------------------------------------------
SVC Accuracy 96.99 %
--------------------------------------------------------------------------------
kSVC Confusion Matrix
--------------------------------------------------------------------------------
kSVC Classification Report
             precision    recall  f1-score   support

        1.0       0.97      1.00      0.98       410
        2.0       0.97      0.90      0.94        72
        3.0       1.00      0.86      0.92        50

avg / total       0.97      0.97      0.97       532

--------------------------------------------------------------------------------
kSVC Accuracy 96.99 %
--------------------------------------------------------------------------------
KNN Confusion Matrix
--------------------------------------------------------------------------------
KNN Classification Report
             precision    recall  f1-score   support

        1.0       0.99      0.99      0.99       410
        2.0       0.95      0.96      0.95        72
        3.0       1.00      0.98      0.99        50

avg / total       0.99      0.98      0.98       532

--------------------------------------------------------------------------------
KNN Accuracy 98.5 %
--------------------------------------------------------------------------------
DecisionTree Confusion Matrix
--------------------------------------------------------------------------------
DecisionTree Classification Report
             precision    recall  f1-score   support

        1.0       0.99      0.99      0.99       410
        2.0       0.96      0.94      0.95        72
        3.0       1.00      1.00      1.00        50

avg / total       0.99      0.99      0.99       532

--------------------------------------------------------------------------------
DecisionTree Accuracy 98.68 %
--------------------------------------------------------------------------------
RandomForestClassifier Confusion Matrix
--------------------------------------------------------------------------------
RandomForestClassifier Classification Report
             precision    recall  f1-score   support

        1.0       0.99      1.00      0.99       410
        2.0       0.97      0.92      0.94        72
        3.0       1.00      1.00      1.00        50

avg / total       0.98      0.98      0.98       532

--------------------------------------------------------------------------------
RandomForestClassifier Accuracy 98.5 %
Fitting 3 folds for each of 25 candidates, totalling 75 fits
[Parallel(n_jobs=1)]: Done  75 out of  75 | elapsed:  2.2min finished
--------------------------------------------------------------------------------
GridSearchCV Confusion Matrix
--------------------------------------------------------------------------------
GridSearchCV Classification Report
             precision    recall  f1-score   support

        1.0       1.00      0.99      0.99       410
        2.0       0.97      0.96      0.97        72
        3.0       0.96      1.00      0.98        50

avg / total       0.99      0.99      0.99       532

--------------------------------------------------------------------------------
GridSearchCV Accuracy 98.87 %
--------------------------------------------------------------------------------
HuberRegressor Confusion Matrix
--------------------------------------------------------------------------------
HuberRegressor Classification Report
             precision    recall  f1-score   support

        1.0       0.99      0.99      0.99       410
        2.0       0.93      0.92      0.92        72
        3.0       1.00      0.96      0.98        50
        4.0       0.00      0.00      0.00         0
        5.0       0.00      0.00      0.00         0

avg / total       0.98      0.98      0.98       532

--------------------------------------------------------------------------------
HuberRegressor Accuracy 97.56 %
--------------------------------------------------------------------------------
Lasso Confusion Matrix
/opt/conda/lib/python3.6/site-packages/sklearn/metrics/classification.py:1137: UndefinedMetricWarning: Recall and F-score are ill-defined and being set to 0.0 in labels with no true samples.
  'recall', 'true', average, warn_for)
--------------------------------------------------------------------------------
Lasso Classification Report
             precision    recall  f1-score   support

        1.0       0.98      0.99      0.99       410
        2.0       0.95      0.88      0.91        72
        3.0       1.00      1.00      1.00        50

avg / total       0.98      0.98      0.98       532

--------------------------------------------------------------------------------
Lasso Accuracy 97.74 %
--------------------------------------------------------------------------------
LassoCV Confusion Matrix
--------------------------------------------------------------------------------
LassoCV Classification Report
             precision    recall  f1-score   support

        1.0       0.99      0.99      0.99       410
        2.0       0.96      0.92      0.94        72
        3.0       1.00      0.98      0.99        50
        4.0       0.00      0.00      0.00         0

avg / total       0.98      0.98      0.98       532

--------------------------------------------------------------------------------
LassoCV Accuracy 98.12 %
--------------------------------------------------------------------------------
Lars Confusion Matrix
/opt/conda/lib/python3.6/site-packages/sklearn/metrics/classification.py:1137: UndefinedMetricWarning: Recall and F-score are ill-defined and being set to 0.0 in labels with no true samples.
  'recall', 'true', average, warn_for)
--------------------------------------------------------------------------------
Lars Classification Report
             precision    recall  f1-score   support

        0.0       0.00      0.00      0.00         0
        1.0       0.95      0.98      0.97       410
        2.0       0.55      0.67      0.60        72
        3.0       1.00      0.20      0.33        50
        4.0       0.00      0.00      0.00         0

avg / total       0.90      0.87      0.86       532

--------------------------------------------------------------------------------
Lars Accuracy 86.65 %
--------------------------------------------------------------------------------
BayesianRidge Confusion Matrix
--------------------------------------------------------------------------------
BayesianRidge Classification Report
             precision    recall  f1-score   support

        1.0       0.99      0.99      0.99       410
        2.0       0.93      0.96      0.95        72
        3.0       1.00      0.96      0.98        50
        4.0       0.00      0.00      0.00         0
        5.0       0.00      0.00      0.00         0

avg / total       0.99      0.98      0.98       532

--------------------------------------------------------------------------------
BayesianRidge Accuracy 98.12 %
--------------------------------------------------------------------------------
SGDClassifier Confusion Matrix
/opt/conda/lib/python3.6/site-packages/sklearn/linear_model/stochastic_gradient.py:128: FutureWarning: max_iter and tol parameters have been added in <class 'sklearn.linear_model.stochastic_gradient.SGDClassifier'> in 0.19. If both are left unset, they default to max_iter=5 and tol=None. If tol is not None, max_iter defaults to max_iter=1000. From 0.21, default max_iter will be 1000, and default tol will be 1e-3.
  "and default tol will be 1e-3." % type(self), FutureWarning)
--------------------------------------------------------------------------------
SGDClassifier Classification Report
             precision    recall  f1-score   support

        1.0       0.99      0.99      0.99       410
        2.0       0.94      0.94      0.94        72
        3.0       1.00      0.98      0.99        50

avg / total       0.98      0.98      0.98       532

--------------------------------------------------------------------------------
SGDClassifier Accuracy 98.31 %
--------------------------------------------------------------------------------
RidgeClassifier Confusion Matrix
--------------------------------------------------------------------------------
RidgeClassifier Classification Report
             precision    recall  f1-score   support

        1.0       0.99      0.98      0.99       410
        2.0       0.88      0.94      0.91        72
        3.0       1.00      0.94      0.97        50

avg / total       0.97      0.97      0.97       532

--------------------------------------------------------------------------------
RidgeClassifier Accuracy 97.37 %

After this multi-model study, some of the algorithms we have used stand out with an accuracy equal or beyond 98.5%. These algorithms are : KNN, Decision Tree, Random Forest, GridSearchCV ( applied to kSVC) , SGDC. Amongst these, the one to particularly stand out is the kSVC after it has been optimized by the grid search, quite obviously. We want to know if we can push the limits of this algorithms to even higher accuracies and scores. The method used here could be used for any of the above algorithms, while testing for the algorithm-specific parameters.

Optimization of the kSVC This one can take a few minutes to run, if you don't want to run it you can see the results right below the code.

In [22]:
from sklearn.model_selection import GridSearchCV
parameters = {'C': [0.1,1, 10, 100, 1000], 'gamma': [1,0.1,0.01,0.001,0.0001], 'kernel': ['rbf']}

# Here we typed out all the options we want the method to test, each one in
# its own dictionary.

from sklearn.svm import SVC
grid_search = GridSearchCV(SVC(),param_grid = parameters, refit = True, verbose = 1)
grid_search = grid_search.fit(X_train, y_train)
best_accuracy = grid_search.best_score_
best_parameters = grid_search.best_params_
print(best_accuracy)
print(best_parameters)
Fitting 3 folds for each of 25 candidates, totalling 75 fits
[Parallel(n_jobs=1)]: Done  75 out of  75 | elapsed:  2.3min finished
0.9880803011292346
{'C': 100, 'gamma': 0.0001, 'kernel': 'rbf'}

After this grid search we obtained an accuracy of 98.80% with the parameters set as such : C=100, gamma=1e-4, kernel=rbf. Let's try to push it even more.

In [23]:
parameters = {'C': [50,75, 125, 100, 500], 'gamma': [0.0001,0.00001], 'kernel': ['rbf']}

from sklearn.svm import SVC
grid_search = GridSearchCV(SVC(),param_grid = parameters, refit = True, verbose = 1)
grid_search = grid_search.fit(X_train, y_train)
best_accuracy = grid_search.best_score_
best_parameters = grid_search.best_params_

print(best_accuracy)
print(best_parameters)
Fitting 3 folds for each of 10 candidates, totalling 30 fits
[Parallel(n_jobs=1)]: Done  30 out of  30 | elapsed:   10.4s finished
0.9893350062735258
{'C': 500, 'gamma': 1e-05, 'kernel': 'rbf'}

Not a significant increase in the accuracy this time. We got 98.93% accuracy with the parameters set as such : C=500, gamma=1e-5, kernel=rbf. To this point, trying to get the algorithm past our current accuracy would be a waste of our time.

Maybe an Artificial Neural Network could do better ?

Using an Artificial Neural Network as a classifier

Using the Keras library, we will build a simple ANN ( artificial neural network ). It will be composed of 4 layers. One input, one output, and two hidden layers. For this classification to happen in an ANN we will also have to encode categorical data ( our NSP classes ) in numerical data. After being processed by the ANN we will decode the predicted results to compare them with the actual results in the form of a confusion matrix.

In [24]:
# Importing the Keras libraries, models and layers
import keras
from keras.models import Sequential
from keras.layers import Dense
In [25]:
# In this part we are barely reprocessing the data and putting it in a form that will fit the ANN
# as we explained earlier.

# While chain-testing the different algorithms we had changed X and y to fit a polynomial form,
# so we have to import them anew.
X = dataset.iloc[:,:-2].values
y = dataset.iloc[:,-1].values
X_train, X_test, y_train, y_test = train_test_split(X, y, test_size = 0.25, random_state = 0)

from sklearn.preprocessing import OneHotEncoder
ohe = OneHotEncoder()
y_trainann = ohe.fit_transform(y_train.reshape(-1, 1)).toarray()
y_trainann = np.delete(y_trainann, 1, 1) # Deleting a column to avoid redundancy after the OHE
In [26]:
# Initializing the ANN
classifier = Sequential()

# Adding the input layer and the first hidden layer
classifier.add(Dense(output_dim = 20, init = 'uniform', activation = 'relu', input_dim = 36))

# Adding the second hidden layer
classifier.add(Dense(output_dim = 20, init = 'uniform', activation = 'relu'))

# Adding the output layer
classifier.add(Dense(output_dim = 2, init = 'uniform', activation = 'sigmoid'))

# Compiling the ANN
classifier.compile(optimizer = 'adam', loss = 'categorical_crossentropy', metrics = ['accuracy'])

# Fitting the ANN to the Training set
classifier.fit(X_train, y_trainann, batch_size = 5, nb_epoch = 20)
/opt/conda/lib/python3.6/site-packages/ipykernel_launcher.py:5: UserWarning: Update your `Dense` call to the Keras 2 API: `Dense(activation="relu", input_dim=36, units=20, kernel_initializer="uniform")`
  """
/opt/conda/lib/python3.6/site-packages/ipykernel_launcher.py:8: UserWarning: Update your `Dense` call to the Keras 2 API: `Dense(activation="relu", units=20, kernel_initializer="uniform")`
  
/opt/conda/lib/python3.6/site-packages/ipykernel_launcher.py:11: UserWarning: Update your `Dense` call to the Keras 2 API: `Dense(activation="sigmoid", units=2, kernel_initializer="uniform")`
  # This is added back by InteractiveShellApp.init_path()
/opt/conda/lib/python3.6/site-packages/Keras-2.1.5-py3.6.egg/keras/models.py:981: UserWarning: The `nb_epoch` argument in `fit` has been renamed `epochs`.
Epoch 1/20
1594/1594 [==============================] - 1s 457us/step - loss: 0.2330 - acc: 0.9222
Epoch 2/20
1594/1594 [==============================] - 1s 341us/step - loss: 0.0960 - acc: 0.9423
Epoch 3/20
1594/1594 [==============================] - 1s 346us/step - loss: 0.0631 - acc: 0.9517
Epoch 4/20
1594/1594 [==============================] - 1s 340us/step - loss: 0.0659 - acc: 0.9504
Epoch 5/20
1594/1594 [==============================] - 1s 344us/step - loss: 0.0472 - acc: 0.9529
Epoch 6/20
1594/1594 [==============================] - 1s 340us/step - loss: 0.0398 - acc: 0.9611
Epoch 7/20
1594/1594 [==============================] - 1s 340us/step - loss: 0.0374 - acc: 0.9605
Epoch 8/20
1594/1594 [==============================] - 1s 346us/step - loss: 0.0362 - acc: 0.9661
Epoch 9/20
1594/1594 [==============================] - 1s 347us/step - loss: 0.0315 - acc: 0.9598
Epoch 10/20
1594/1594 [==============================] - 1s 340us/step - loss: 0.0218 - acc: 0.9680
Epoch 11/20
1594/1594 [==============================] - 1s 337us/step - loss: 0.0199 - acc: 0.9592
Epoch 12/20
1594/1594 [==============================] - 1s 340us/step - loss: 0.0217 - acc: 0.9605
Epoch 13/20
1594/1594 [==============================] - 1s 341us/step - loss: 0.0185 - acc: 0.9649
Epoch 14/20
1594/1594 [==============================] - 1s 339us/step - loss: 0.0183 - acc: 0.9573
Epoch 15/20
1594/1594 [==============================] - 1s 337us/step - loss: 0.0099 - acc: 0.9661
Epoch 16/20
1594/1594 [==============================] - 1s 341us/step - loss: 0.0061 - acc: 0.9636
Epoch 17/20
1594/1594 [==============================] - 1s 339us/step - loss: 0.0085 - acc: 0.9680
Epoch 18/20
1594/1594 [==============================] - 1s 335us/step - loss: 0.0082 - acc: 0.9680
Epoch 19/20
1594/1594 [==============================] - 1s 340us/step - loss: 0.0010 - acc: 0.9661
Epoch 20/20
1594/1594 [==============================] - 1s 342us/step - loss: 0.0101 - acc: 0.9642
Out[26]:
<keras.callbacks.History at 0x7f1d4c3a0a90>

With a very simple ANN and no tuning whatsoever we got accuracies around 97% at the end of training. Let's decode the results and create the confusion matrix to get the actual score.

In [27]:
# Predicting the Test set results
y_pred = classifier.predict(X_test)
y_pred = (y_pred > 0.7)

recovered_y = np.zeros(532,)
for i in range(0,532):
    for j in range(0,2):
        if (y_pred[i][j] == True) and j == 0:
            recovered_y[i] = 1
        elif (y_pred[i][j] == True) and j == 1:
            recovered_y[i] = 3            
for i in range(0,532):
    if recovered_y[i] == 0:
        recovered_y[i] = 2
     
from sklearn.metrics import confusion_matrix, accuracy_score
cm = confusion_matrix(y_test, recovered_y)
acc = accuracy_score(y_test, recovered_y)

print('The score is : '+str(acc))   
label = ["N","S","P"]
sns.heatmap(cm, annot=True, xticklabels=label, yticklabels=label, cmap="YlGnBu")
plt.show()
The score is : 0.6992481203007519

Not a very good result... It seems like the high accuracy during training and the sudden drop we get would be a symptom of overfitting, we can try with less epochs and different batch sizes. In order to do this we will create a for loop that will work in tha same manner as a grid search for our parameters ( here they are the number of epochs and the batch size ).

In [28]:
epochs = [5,10,15]
batch_sizes = [1,2,3,4,5,10,15,20]
table_results = np.zeros([(len(epochs)*len(batch_sizes)),3],)
c = 0
for aa in epochs:
    for bb in batch_sizes:
        print('The number of epochs is : '+str(aa))
        print('The batch size is : '+str(bb))
        classifier.fit(X_train, y_trainann, batch_size = bb, nb_epoch = aa)

        y_pred = classifier.predict(X_test)
        y_pred = (y_pred > 0.7)

        recovered_y = np.zeros(532,)
        for i in range(0,532):
            for j in range(0,2):
                if (y_pred[i][j] == True) and j == 0:
                    recovered_y[i] = 1
                elif (y_pred[i][j] == True) and j == 1:
                    recovered_y[i] = 3            
        for i in range(0,532):
            if recovered_y[i] == 0:
                recovered_y[i] = 2

        from sklearn.metrics import confusion_matrix, accuracy_score
        cm = confusion_matrix(y_test, recovered_y)
        acc = accuracy_score(y_test, recovered_y)
        
        table_results[c][0] = aa
        table_results[c][1] = bb
        table_results[c][2] = acc
        c += 1
        print('The accuracy is : '+str(acc))   
        label = ["N","S","P"]
        sns.heatmap(cm, annot=True, xticklabels=label, yticklabels=label, cmap="YlGnBu")
        plt.show()
The number of epochs is : 5
The batch size is : 1
Epoch 1/5
  87/1594 [>.............................] - ETA: 2s - loss: 0.1973 - acc: 0.9310  
/opt/conda/lib/python3.6/site-packages/Keras-2.1.5-py3.6.egg/keras/models.py:981: UserWarning: The `nb_epoch` argument in `fit` has been renamed `epochs`.
1594/1594 [==============================] - 3s 2ms/step - loss: 0.0407 - acc: 0.9586
Epoch 2/5
1594/1594 [==============================] - 3s 2ms/step - loss: 0.0337 - acc: 0.9586
Epoch 3/5
1594/1594 [==============================] - 3s 2ms/step - loss: 0.0196 - acc: 0.9655
Epoch 4/5
1594/1594 [==============================] - 3s 2ms/step - loss: 0.0215 - acc: 0.9561
Epoch 5/5
1594/1594 [==============================] - 3s 2ms/step - loss: 0.0175 - acc: 0.9655
The accuracy is : 0.8778195488721805
The number of epochs is : 5
The batch size is : 2
Epoch 1/5
1594/1594 [==============================] - 1s 839us/step - loss: 0.0088 - acc: 0.9724
Epoch 2/5
1594/1594 [==============================] - 1s 843us/step - loss: 0.0143 - acc: 0.9649
Epoch 3/5
1594/1594 [==============================] - 1s 836us/step - loss: 0.0011 - acc: 0.9724
Epoch 4/5
1594/1594 [==============================] - 1s 844us/step - loss: 0.0079 - acc: 0.9674
Epoch 5/5
1594/1594 [==============================] - 1s 846us/step - loss: 4.5585e-04 - acc: 0.9724
The accuracy is : 0.8890977443609023
The number of epochs is : 5
The batch size is : 3
Epoch 1/5
1594/1594 [==============================] - 1s 569us/step - loss: 0.0117 - acc: 0.9605
Epoch 2/5
1594/1594 [==============================] - 1s 561us/step - loss: 0.0081 - acc: 0.9624
Epoch 3/5
1594/1594 [==============================] - 1s 551us/step - loss: 0.0013 - acc: 0.9668
Epoch 4/5
1594/1594 [==============================] - 1s 556us/step - loss: 0.0043 - acc: 0.9693
Epoch 5/5
1594/1594 [==============================] - 1s 560us/step - loss: 0.0044 - acc: 0.9737
The accuracy is : 0.8834586466165414
The number of epochs is : 5
The batch size is : 4
Epoch 1/5
1594/1594 [==============================] - 1s 425us/step - loss: 3.4487e-04 - acc: 0.9680
Epoch 2/5
1594/1594 [==============================] - 1s 423us/step - loss: 1.6990e-04 - acc: 0.9686
Epoch 3/5
1594/1594 [==============================] - 1s 424us/step - loss: 1.1332e-04 - acc: 0.9668
Epoch 4/5
1594/1594 [==============================] - 1s 420us/step - loss: 8.0355e-05 - acc: 0.9668
Epoch 5/5
1594/1594 [==============================] - 1s 423us/step - loss: 6.2181e-05 - acc: 0.9655
The accuracy is : 0.8909774436090225
The number of epochs is : 5
The batch size is : 5
Epoch 1/5
1594/1594 [==============================] - 1s 339us/step - loss: 4.4007e-05 - acc: 0.9649
Epoch 2/5
1594/1594 [==============================] - 1s 338us/step - loss: 3.6843e-05 - acc: 0.9668
Epoch 3/5
1594/1594 [==============================] - 1s 335us/step - loss: 3.0187e-05 - acc: 0.9655
Epoch 4/5
1594/1594 [==============================] - 1s 338us/step - loss: 2.5020e-05 - acc: 0.9655
Epoch 5/5
1594/1594 [==============================] - 1s 339us/step - loss: 2.0030e-05 - acc: 0.9649
The accuracy is : 0.8928571428571429
The number of epochs is : 5
The batch size is : 10
Epoch 1/5
1594/1594 [==============================] - 0s 174us/step - loss: 1.6703e-05 - acc: 0.9655
Epoch 2/5
1594/1594 [==============================] - 0s 172us/step - loss: 1.4819e-05 - acc: 0.9642
Epoch 3/5
1594/1594 [==============================] - 0s 170us/step - loss: 1.3277e-05 - acc: 0.9655
Epoch 4/5
1594/1594 [==============================] - 0s 170us/step - loss: 1.2186e-05 - acc: 0.9649
Epoch 5/5
1594/1594 [==============================] - 0s 172us/step - loss: 1.1074e-05 - acc: 0.9636
The accuracy is : 0.8947368421052632
The number of epochs is : 5
The batch size is : 15
Epoch 1/5
1594/1594 [==============================] - 0s 112us/step - loss: 1.0050e-05 - acc: 0.9642
Epoch 2/5
1594/1594 [==============================] - 0s 115us/step - loss: 9.6201e-06 - acc: 0.9649
Epoch 3/5
1594/1594 [==============================] - 0s 115us/step - loss: 8.9619e-06 - acc: 0.9636
Epoch 4/5
1594/1594 [==============================] - 0s 115us/step - loss: 8.3948e-06 - acc: 0.9649
Epoch 5/5
1594/1594 [==============================] - 0s 116us/step - loss: 8.0205e-06 - acc: 0.9642
The accuracy is : 0.8947368421052632
The number of epochs is : 5
The batch size is : 20
Epoch 1/5
1594/1594 [==============================] - 0s 87us/step - loss: 7.4283e-06 - acc: 0.9636
Epoch 2/5
1594/1594 [==============================] - 0s 88us/step - loss: 7.0823e-06 - acc: 0.9642
Epoch 3/5
1594/1594 [==============================] - 0s 86us/step - loss: 6.8622e-06 - acc: 0.9636
Epoch 4/5
1594/1594 [==============================] - 0s 86us/step - loss: 6.5663e-06 - acc: 0.9636
Epoch 5/5
1594/1594 [==============================] - 0s 87us/step - loss: 6.1775e-06 - acc: 0.9642
The accuracy is : 0.900375939849624
The number of epochs is : 10
The batch size is : 1
Epoch 1/10
1594/1594 [==============================] - 3s 2ms/step - loss: 0.0293 - acc: 0.9567
Epoch 2/10
1594/1594 [==============================] - 3s 2ms/step - loss: 5.1368e-04 - acc: 0.9680
Epoch 3/10
1594/1594 [==============================] - 3s 2ms/step - loss: 1.3921e-04 - acc: 0.9649
Epoch 4/10
1594/1594 [==============================] - 3s 2ms/step - loss: 9.5458e-05 - acc: 0.9661
Epoch 5/10
1594/1594 [==============================] - 3s 2ms/step - loss: 0.0082 - acc: 0.9642
Epoch 6/10
1594/1594 [==============================] - 3s 2ms/step - loss: 5.8337e-05 - acc: 0.9636
Epoch 7/10
1594/1594 [==============================] - 3s 2ms/step - loss: 4.8998e-05 - acc: 0.9649
Epoch 8/10
1594/1594 [==============================] - 3s 2ms/step - loss: 2.1685e-05 - acc: 0.9686
Epoch 9/10
1594/1594 [==============================] - 3s 2ms/step - loss: 0.0726 - acc: 0.9605
Epoch 10/10
1594/1594 [==============================] - 3s 2ms/step - loss: 4.3176e-04 - acc: 0.9661
The accuracy is : 0.881578947368421
The number of epochs is : 10
The batch size is : 2
Epoch 1/10
1594/1594 [==============================] - 1s 841us/step - loss: 1.3017e-04 - acc: 0.9649
Epoch 2/10
1594/1594 [==============================] - 1s 841us/step - loss: 8.5543e-05 - acc: 0.9686
Epoch 3/10
1594/1594 [==============================] - 1s 852us/step - loss: 4.6321e-05 - acc: 0.9661
Epoch 4/10
1594/1594 [==============================] - 1s 851us/step - loss: 3.3728e-05 - acc: 0.9686
Epoch 5/10
1594/1594 [==============================] - 1s 843us/step - loss: 1.6959e-05 - acc: 0.9655
Epoch 6/10
1594/1594 [==============================] - 1s 841us/step - loss: 0.0027 - acc: 0.9668
Epoch 7/10
1594/1594 [==============================] - 1s 844us/step - loss: 0.0130 - acc: 0.9674
Epoch 8/10
1594/1594 [==============================] - 1s 835us/step - loss: 2.5093e-04 - acc: 0.9649
Epoch 9/10
1594/1594 [==============================] - 1s 841us/step - loss: 1.4289e-04 - acc: 0.9674
Epoch 10/10
1594/1594 [==============================] - 1s 845us/step - loss: 8.8545e-05 - acc: 0.9630
The accuracy is : 0.8853383458646616
The number of epochs is : 10
The batch size is : 3
Epoch 1/10
1594/1594 [==============================] - 1s 566us/step - loss: 7.0924e-05 - acc: 0.9642
Epoch 2/10
1594/1594 [==============================] - 1s 573us/step - loss: 0.0105 - acc: 0.9674
Epoch 3/10
1594/1594 [==============================] - 1s 566us/step - loss: 1.5612e-04 - acc: 0.9617
Epoch 4/10
1594/1594 [==============================] - 1s 569us/step - loss: 8.5029e-05 - acc: 0.9699
Epoch 5/10
1594/1594 [==============================] - 1s 565us/step - loss: 5.4132e-05 - acc: 0.9693
Epoch 6/10
1594/1594 [==============================] - 1s 563us/step - loss: 3.5247e-05 - acc: 0.9724
Epoch 7/10
1594/1594 [==============================] - 1s 562us/step - loss: 2.7196e-05 - acc: 0.9693
Epoch 8/10
1594/1594 [==============================] - 1s 564us/step - loss: 1.6096e-05 - acc: 0.9705
Epoch 9/10
1594/1594 [==============================] - 1s 566us/step - loss: 1.5192e-05 - acc: 0.9718
Epoch 10/10
1594/1594 [==============================] - 1s 567us/step - loss: 1.4014e-05 - acc: 0.9661
The accuracy is : 0.8796992481203008
The number of epochs is : 10
The batch size is : 4
Epoch 1/10
1594/1594 [==============================] - 1s 423us/step - loss: 6.6382e-06 - acc: 0.9699
Epoch 2/10
1594/1594 [==============================] - 1s 425us/step - loss: 4.8536e-06 - acc: 0.9674
Epoch 3/10
1594/1594 [==============================] - 1s 423us/step - loss: 4.2527e-06 - acc: 0.9699
Epoch 4/10
1594/1594 [==============================] - 1s 422us/step - loss: 3.6849e-06 - acc: 0.9699
Epoch 5/10
1594/1594 [==============================] - 1s 421us/step - loss: 2.7942e-06 - acc: 0.9674
Epoch 6/10
1594/1594 [==============================] - 1s 428us/step - loss: 2.4483e-06 - acc: 0.9686
Epoch 7/10
1594/1594 [==============================] - 1s 422us/step - loss: 1.8776e-06 - acc: 0.9686
Epoch 8/10
1594/1594 [==============================] - 1s 423us/step - loss: 1.7817e-06 - acc: 0.9699
Epoch 9/10
1594/1594 [==============================] - 1s 427us/step - loss: 1.5309e-06 - acc: 0.9655
Epoch 10/10
1594/1594 [==============================] - 1s 422us/step - loss: 1.0446e-06 - acc: 0.9686
The accuracy is : 0.8890977443609023
The number of epochs is : 10
The batch size is : 5
Epoch 1/10
1594/1594 [==============================] - 1s 337us/step - loss: 9.0469e-07 - acc: 0.9655
Epoch 2/10
1594/1594 [==============================] - 1s 337us/step - loss: 7.2613e-07 - acc: 0.9718
Epoch 3/10
1594/1594 [==============================] - 1s 336us/step - loss: 6.4692e-07 - acc: 0.9686
Epoch 4/10
1594/1594 [==============================] - 1s 337us/step - loss: 5.8376e-07 - acc: 0.9668
Epoch 5/10
1594/1594 [==============================] - 1s 336us/step - loss: 4.8735e-07 - acc: 0.9705
Epoch 6/10
1594/1594 [==============================] - 1s 342us/step - loss: 3.9708e-07 - acc: 0.9699
Epoch 7/10
1594/1594 [==============================] - 1s 335us/step - loss: 4.4024e-07 - acc: 0.9705
Epoch 8/10
1594/1594 [==============================] - 1s 345us/step - loss: 3.8576e-07 - acc: 0.9686
Epoch 9/10
1594/1594 [==============================] - 1s 334us/step - loss: 2.9597e-07 - acc: 0.9699
Epoch 10/10
1594/1594 [==============================] - 1s 341us/step - loss: 2.7380e-07 - acc: 0.9680
The accuracy is : 0.8966165413533834
The number of epochs is : 10
The batch size is : 10
Epoch 1/10
1594/1594 [==============================] - 0s 171us/step - loss: 2.2548e-07 - acc: 0.9699
Epoch 2/10
1594/1594 [==============================] - 0s 173us/step - loss: 2.1497e-07 - acc: 0.9705
Epoch 3/10
1594/1594 [==============================] - 0s 171us/step - loss: 2.1737e-07 - acc: 0.9705
Epoch 4/10
1594/1594 [==============================] - 0s 172us/step - loss: 2.0361e-07 - acc: 0.9674
Epoch 5/10
1594/1594 [==============================] - 0s 173us/step - loss: 1.9224e-07 - acc: 0.9705
Epoch 6/10
1594/1594 [==============================] - 0s 174us/step - loss: 1.8252e-07 - acc: 0.9693
Epoch 7/10
1594/1594 [==============================] - 0s 171us/step - loss: 1.7855e-07 - acc: 0.9705
Epoch 8/10
1594/1594 [==============================] - 0s 169us/step - loss: 1.7878e-07 - acc: 0.9711
Epoch 9/10
1594/1594 [==============================] - 0s 172us/step - loss: 1.6629e-07 - acc: 0.9668
Epoch 10/10
1594/1594 [==============================] - 0s 171us/step - loss: 1.6244e-07 - acc: 0.9699
The accuracy is : 0.8947368421052632
The number of epochs is : 10
The batch size is : 15
Epoch 1/10
1594/1594 [==============================] - 0s 116us/step - loss: 1.5597e-07 - acc: 0.9705
Epoch 2/10
1594/1594 [==============================] - 0s 116us/step - loss: 1.5372e-07 - acc: 0.9711
Epoch 3/10
1594/1594 [==============================] - 0s 116us/step - loss: 1.4942e-07 - acc: 0.9680
Epoch 4/10
1594/1594 [==============================] - 0s 113us/step - loss: 1.4587e-07 - acc: 0.9711
Epoch 5/10
1594/1594 [==============================] - 0s 114us/step - loss: 1.4482e-07 - acc: 0.9711
Epoch 6/10
1594/1594 [==============================] - 0s 115us/step - loss: 1.4232e-07 - acc: 0.9699
Epoch 7/10
1594/1594 [==============================] - 0s 115us/step - loss: 1.3996e-07 - acc: 0.9699
Epoch 8/10
1594/1594 [==============================] - 0s 116us/step - loss: 1.3828e-07 - acc: 0.9711
Epoch 9/10
1594/1594 [==============================] - 0s 115us/step - loss: 1.3581e-07 - acc: 0.9699
Epoch 10/10
1594/1594 [==============================] - 0s 115us/step - loss: 1.3424e-07 - acc: 0.9693
The accuracy is : 0.8966165413533834
The number of epochs is : 10
The batch size is : 20
Epoch 1/10
1594/1594 [==============================] - 0s 85us/step - loss: 1.3106e-07 - acc: 0.9705
Epoch 2/10
1594/1594 [==============================] - 0s 88us/step - loss: 1.3046e-07 - acc: 0.9711
Epoch 3/10
1594/1594 [==============================] - 0s 86us/step - loss: 1.2886e-07 - acc: 0.9699
Epoch 4/10
1594/1594 [==============================] - 0s 86us/step - loss: 1.2792e-07 - acc: 0.9699
Epoch 5/10
1594/1594 [==============================] - 0s 85us/step - loss: 1.2781e-07 - acc: 0.9711
Epoch 6/10
1594/1594 [==============================] - 0s 87us/step - loss: 1.2572e-07 - acc: 0.9699
Epoch 7/10
1594/1594 [==============================] - 0s 88us/step - loss: 1.2486e-07 - acc: 0.9693
Epoch 8/10
1594/1594 [==============================] - 0s 87us/step - loss: 1.2415e-07 - acc: 0.9699
Epoch 9/10
1594/1594 [==============================] - 0s 86us/step - loss: 1.2329e-07 - acc: 0.9705
Epoch 10/10
1594/1594 [==============================] - 0s 87us/step - loss: 1.2284e-07 - acc: 0.9693
The accuracy is : 0.8984962406015038
The number of epochs is : 15
The batch size is : 1
Epoch 1/15
1594/1594 [==============================] - 3s 2ms/step - loss: 0.1589 - acc: 0.9693
Epoch 2/15
1594/1594 [==============================] - 3s 2ms/step - loss: 1.5691e-05 - acc: 0.9737
Epoch 3/15
1594/1594 [==============================] - 3s 2ms/step - loss: 0.0207 - acc: 0.9743
Epoch 4/15
1594/1594 [==============================] - 3s 2ms/step - loss: 0.0094 - acc: 0.9730
Epoch 5/15
1594/1594 [==============================] - 3s 2ms/step - loss: 0.0131 - acc: 0.9699
Epoch 6/15
1594/1594 [==============================] - 3s 2ms/step - loss: 0.0554 - acc: 0.9636
Epoch 7/15
1594/1594 [==============================] - 3s 2ms/step - loss: 3.2367e-04 - acc: 0.9711
Epoch 8/15
1594/1594 [==============================] - 3s 2ms/step - loss: 7.9586e-05 - acc: 0.9693
Epoch 9/15
1594/1594 [==============================] - 3s 2ms/step - loss: 1.1950e-04 - acc: 0.9755
Epoch 10/15
1594/1594 [==============================] - 3s 2ms/step - loss: 4.8462e-06 - acc: 0.9724
Epoch 11/15
1594/1594 [==============================] - 3s 2ms/step - loss: 4.2064e-06 - acc: 0.9693
Epoch 12/15
1594/1594 [==============================] - 3s 2ms/step - loss: 0.0421 - acc: 0.9668
Epoch 13/15
1594/1594 [==============================] - 3s 2ms/step - loss: 2.3667e-04 - acc: 0.9705
Epoch 14/15
1594/1594 [==============================] - 3s 2ms/step - loss: 7.2031e-05 - acc: 0.9718
Epoch 15/15
1594/1594 [==============================] - 3s 2ms/step - loss: 6.1426e-05 - acc: 0.9686
The accuracy is : 0.8872180451127819
The number of epochs is : 15
The batch size is : 2
Epoch 1/15
1594/1594 [==============================] - 1s 840us/step - loss: 1.7238e-05 - acc: 0.9737
Epoch 2/15
1594/1594 [==============================] - 1s 842us/step - loss: 7.3448e-06 - acc: 0.9711
Epoch 3/15
1594/1594 [==============================] - 1s 840us/step - loss: 0.0020 - acc: 0.9724
Epoch 4/15
1594/1594 [==============================] - 1s 841us/step - loss: 0.0171 - acc: 0.9642
Epoch 5/15
1594/1594 [==============================] - 1s 831us/step - loss: 0.0065 - acc: 0.9799
Epoch 6/15
1594/1594 [==============================] - 1s 830us/step - loss: 0.0102 - acc: 0.9630
Epoch 7/15
1594/1594 [==============================] - 1s 832us/step - loss: 6.4919e-04 - acc: 0.9699
Epoch 8/15
1594/1594 [==============================] - 1s 835us/step - loss: 2.3090e-04 - acc: 0.9774
Epoch 9/15
1594/1594 [==============================] - 1s 834us/step - loss: 9.2010e-05 - acc: 0.9693
Epoch 10/15
1594/1594 [==============================] - 1s 834us/step - loss: 2.0083e-05 - acc: 0.9711
Epoch 11/15
1594/1594 [==============================] - 1s 837us/step - loss: 1.4811e-05 - acc: 0.9724
Epoch 12/15
1594/1594 [==============================] - 1s 835us/step - loss: 9.5710e-06 - acc: 0.9737
Epoch 13/15
1594/1594 [==============================] - 1s 829us/step - loss: 6.0392e-06 - acc: 0.9730
Epoch 14/15
1594/1594 [==============================] - 1s 831us/step - loss: 4.1073e-06 - acc: 0.9730
Epoch 15/15
1594/1594 [==============================] - 1s 828us/step - loss: 2.5928e-06 - acc: 0.9718
The accuracy is : 0.8872180451127819
The number of epochs is : 15
The batch size is : 3
Epoch 1/15
1594/1594 [==============================] - 1s 561us/step - loss: 1.4667e-06 - acc: 0.9743
Epoch 2/15
1594/1594 [==============================] - 1s 558us/step - loss: 1.1269e-06 - acc: 0.9718
Epoch 3/15
1594/1594 [==============================] - 1s 552us/step - loss: 9.3019e-07 - acc: 0.9730
Epoch 4/15
1594/1594 [==============================] - 1s 561us/step - loss: 7.3861e-07 - acc: 0.9730
Epoch 5/15
1594/1594 [==============================] - 1s 558us/step - loss: 5.1121e-07 - acc: 0.9737
Epoch 6/15
1594/1594 [==============================] - 1s 565us/step - loss: 5.5973e-07 - acc: 0.9699
Epoch 7/15
1594/1594 [==============================] - 1s 561us/step - loss: 3.7319e-07 - acc: 0.9730
Epoch 8/15
1594/1594 [==============================] - 1s 561us/step - loss: 3.0805e-07 - acc: 0.9724
Epoch 9/15
1594/1594 [==============================] - 1s 574us/step - loss: 2.5816e-07 - acc: 0.9730
Epoch 10/15
1594/1594 [==============================] - 1s 564us/step - loss: 2.1823e-07 - acc: 0.9699
Epoch 11/15
1594/1594 [==============================] - 1s 561us/step - loss: 7.9537e-07 - acc: 0.9693
Epoch 12/15
1594/1594 [==============================] - 1s 566us/step - loss: 1.4086e-07 - acc: 0.9737
Epoch 13/15
1594/1594 [==============================] - 1s 568us/step - loss: 1.3615e-07 - acc: 0.9711
Epoch 14/15
1594/1594 [==============================] - 1s 566us/step - loss: 1.2815e-07 - acc: 0.9724
Epoch 15/15
1594/1594 [==============================] - 1s 569us/step - loss: 1.2078e-07 - acc: 0.9724
The accuracy is : 0.8928571428571429
The number of epochs is : 15
The batch size is : 4
Epoch 1/15
1594/1594 [==============================] - 1s 426us/step - loss: 1.2673e-07 - acc: 0.9718
Epoch 2/15
1594/1594 [==============================] - 1s 425us/step - loss: 1.1895e-07 - acc: 0.9730
Epoch 3/15
1594/1594 [==============================] - 1s 428us/step - loss: 1.1678e-07 - acc: 0.9718
Epoch 4/15
1594/1594 [==============================] - 1s 427us/step - loss: 1.1068e-07 - acc: 0.9718
Epoch 5/15
1594/1594 [==============================] - 1s 425us/step - loss: 1.1401e-07 - acc: 0.9705
Epoch 6/15
1594/1594 [==============================] - 1s 432us/step - loss: 1.0971e-07 - acc: 0.9718
Epoch 7/15
1594/1594 [==============================] - 1s 422us/step - loss: 1.0896e-07 - acc: 0.9724
Epoch 8/15
1594/1594 [==============================] - 1s 426us/step - loss: 1.0702e-07 - acc: 0.9730
Epoch 9/15
1594/1594 [==============================] - 1s 424us/step - loss: 0.3482 - acc: 0.9567
Epoch 10/15
1594/1594 [==============================] - 1s 422us/step - loss: 0.0033 - acc: 0.9636
Epoch 11/15
1594/1594 [==============================] - 1s 436us/step - loss: 8.4748e-05 - acc: 0.9674
Epoch 12/15
1594/1594 [==============================] - 1s 428us/step - loss: 3.7770e-05 - acc: 0.9718
Epoch 13/15
1594/1594 [==============================] - 1s 433us/step - loss: 2.5493e-05 - acc: 0.9693
Epoch 14/15
1594/1594 [==============================] - 1s 426us/step - loss: 1.8901e-05 - acc: 0.9705
Epoch 15/15
1594/1594 [==============================] - 1s 426us/step - loss: 1.4572e-05 - acc: 0.9680
The accuracy is : 0.8872180451127819
The number of epochs is : 15
The batch size is : 5
Epoch 1/15
1594/1594 [==============================] - 1s 349us/step - loss: 1.1535e-05 - acc: 0.9724
Epoch 2/15
1594/1594 [==============================] - 1s 348us/step - loss: 9.6221e-06 - acc: 0.9699
Epoch 3/15
1594/1594 [==============================] - 1s 343us/step - loss: 8.1855e-06 - acc: 0.9718
Epoch 4/15
1594/1594 [==============================] - 1s 333us/step - loss: 6.9349e-06 - acc: 0.9724
Epoch 5/15
1594/1594 [==============================] - 1s 342us/step - loss: 5.9865e-06 - acc: 0.9699
Epoch 6/15
1594/1594 [==============================] - 1s 344us/step - loss: 5.1053e-06 - acc: 0.9711
Epoch 7/15
1594/1594 [==============================] - 1s 343us/step - loss: 4.3700e-06 - acc: 0.9730
Epoch 8/15
1594/1594 [==============================] - 1s 343us/step - loss: 3.7389e-06 - acc: 0.9711
Epoch 9/15
1594/1594 [==============================] - 1s 346us/step - loss: 3.2828e-06 - acc: 0.9718
Epoch 10/15
1594/1594 [==============================] - 1s 345us/step - loss: 2.8776e-06 - acc: 0.9730
Epoch 11/15
1594/1594 [==============================] - 1s 344us/step - loss: 2.5185e-06 - acc: 0.9711
Epoch 12/15
1594/1594 [==============================] - 1s 342us/step - loss: 2.2155e-06 - acc: 0.9718
Epoch 13/15
1594/1594 [==============================] - 1s 350us/step - loss: 1.9197e-06 - acc: 0.9730
Epoch 14/15
1594/1594 [==============================] - 1s 344us/step - loss: 1.6906e-06 - acc: 0.9737
Epoch 15/15
1594/1594 [==============================] - 1s 349us/step - loss: 1.5186e-06 - acc: 0.9724
The accuracy is : 0.8853383458646616
The number of epochs is : 15
The batch size is : 10
Epoch 1/15
1594/1594 [==============================] - 0s 176us/step - loss: 1.3223e-06 - acc: 0.9718
Epoch 2/15
1594/1594 [==============================] - 0s 177us/step - loss: 1.2398e-06 - acc: 0.9724
Epoch 3/15
1594/1594 [==============================] - 0s 173us/step - loss: 1.1740e-06 - acc: 0.9737
Epoch 4/15
1594/1594 [==============================] - 0s 172us/step - loss: 1.0847e-06 - acc: 0.9730
Epoch 5/15
1594/1594 [==============================] - 0s 173us/step - loss: 1.0195e-06 - acc: 0.9730
Epoch 6/15
1594/1594 [==============================] - 0s 172us/step - loss: 9.5490e-07 - acc: 0.9730
Epoch 7/15
1594/1594 [==============================] - 0s 168us/step - loss: 8.9533e-07 - acc: 0.9730
Epoch 8/15
1594/1594 [==============================] - 0s 170us/step - loss: 8.3557e-07 - acc: 0.9724
Epoch 9/15
1594/1594 [==============================] - 0s 172us/step - loss: 7.9698e-07 - acc: 0.9743
Epoch 10/15
1594/1594 [==============================] - 0s 174us/step - loss: 7.3442e-07 - acc: 0.9730
Epoch 11/15
1594/1594 [==============================] - 0s 169us/step - loss: 6.9755e-07 - acc: 0.9743
Epoch 12/15
1594/1594 [==============================] - 0s 172us/step - loss: 6.5705e-07 - acc: 0.9730
Epoch 13/15
1594/1594 [==============================] - 0s 173us/step - loss: 6.1173e-07 - acc: 0.9730
Epoch 14/15
1594/1594 [==============================] - 0s 174us/step - loss: 5.7530e-07 - acc: 0.9730
Epoch 15/15
1594/1594 [==============================] - 0s 170us/step - loss: 5.4064e-07 - acc: 0.9730
The accuracy is : 0.8890977443609023
The number of epochs is : 15
The batch size is : 15
Epoch 1/15
1594/1594 [==============================] - 0s 117us/step - loss: 5.1267e-07 - acc: 0.9730
Epoch 2/15
1594/1594 [==============================] - 0s 116us/step - loss: 4.8967e-07 - acc: 0.9730
Epoch 3/15
1594/1594 [==============================] - 0s 118us/step - loss: 4.7524e-07 - acc: 0.9730
Epoch 4/15
1594/1594 [==============================] - 0s 113us/step - loss: 4.5325e-07 - acc: 0.9730
Epoch 5/15
1594/1594 [==============================] - 0s 112us/step - loss: 4.3440e-07 - acc: 0.9730
Epoch 6/15
1594/1594 [==============================] - 0s 112us/step - loss: 4.2412e-07 - acc: 0.9730
Epoch 7/15
1594/1594 [==============================] - 0s 111us/step - loss: 4.0355e-07 - acc: 0.9730
Epoch 8/15
1594/1594 [==============================] - 0s 113us/step - loss: 3.8986e-07 - acc: 0.9730
Epoch 9/15
1594/1594 [==============================] - 0s 114us/step - loss: 3.7393e-07 - acc: 0.9730
Epoch 10/15
1594/1594 [==============================] - 0s 114us/step - loss: 3.6545e-07 - acc: 0.9730
Epoch 11/15
1594/1594 [==============================] - 0s 116us/step - loss: 3.5079e-07 - acc: 0.9737
Epoch 12/15
1594/1594 [==============================] - 0s 114us/step - loss: 3.3703e-07 - acc: 0.9737
Epoch 13/15
1594/1594 [==============================] - 0s 115us/step - loss: 3.2319e-07 - acc: 0.9730
Epoch 14/15
1594/1594 [==============================] - 0s 114us/step - loss: 3.1309e-07 - acc: 0.9737
Epoch 15/15
1594/1594 [==============================] - 0s 115us/step - loss: 3.0165e-07 - acc: 0.9737
The accuracy is : 0.8909774436090225
The number of epochs is : 15
The batch size is : 20
Epoch 1/15
1594/1594 [==============================] - 0s 89us/step - loss: 2.9279e-07 - acc: 0.9730
Epoch 2/15
1594/1594 [==============================] - 0s 89us/step - loss: 2.8322e-07 - acc: 0.9730
Epoch 3/15
1594/1594 [==============================] - 0s 87us/step - loss: 2.7686e-07 - acc: 0.9730
Epoch 4/15
1594/1594 [==============================] - 0s 84us/step - loss: 2.7039e-07 - acc: 0.9737
Epoch 5/15
1594/1594 [==============================] - 0s 87us/step - loss: 2.6377e-07 - acc: 0.9737
Epoch 6/15
1594/1594 [==============================] - 0s 86us/step - loss: 2.5712e-07 - acc: 0.9737
Epoch 7/15
1594/1594 [==============================] - 0s 85us/step - loss: 2.5106e-07 - acc: 0.9737
Epoch 8/15
1594/1594 [==============================] - 0s 88us/step - loss: 2.4605e-07 - acc: 0.9737
Epoch 9/15
1594/1594 [==============================] - 0s 88us/step - loss: 2.4021e-07 - acc: 0.9737
Epoch 10/15
1594/1594 [==============================] - 0s 88us/step - loss: 2.3457e-07 - acc: 0.9730
Epoch 11/15
1594/1594 [==============================] - 0s 88us/step - loss: 2.2885e-07 - acc: 0.9737
Epoch 12/15
1594/1594 [==============================] - 0s 87us/step - loss: 2.2309e-07 - acc: 0.9737
Epoch 13/15
1594/1594 [==============================] - 0s 88us/step - loss: 2.1811e-07 - acc: 0.9737
Epoch 14/15
1594/1594 [==============================] - 0s 86us/step - loss: 2.1389e-07 - acc: 0.9730
Epoch 15/15
1594/1594 [==============================] - 0s 89us/step - loss: 2.1030e-07 - acc: 0.9737
The accuracy is : 0.8947368421052632

Let's put this in a 3D representation to see if anything comes out immediatly.

In [29]:
style.use('ggplot')
    
fig = plt.figure(figsize=(10,6))
ax1 = fig.add_subplot(111, projection='3d')
loc = [1,2,3]
classes = ['Normal','Suspect','Pathologic']
    
x3d = table_results[:,0]
y3d = table_results[:,1]
z3d = table_results[:,2]

plot = ax1.scatter(x3d, y3d, z3d,c=z3d, cmap="jet")
ax1.set_xlabel('#epochs')
ax1.set_ylabel('Batch Size')
ax1.set_zlabel('Accuracy')


plt.title('Accuracy of the ANN in GridSearch')
plt.show()

Let's examine the table we made.

In [30]:
table_results
Out[30]:
array([[ 5.        ,  1.        ,  0.87781955],
       [ 5.        ,  2.        ,  0.88909774],
       [ 5.        ,  3.        ,  0.88345865],
       [ 5.        ,  4.        ,  0.89097744],
       [ 5.        ,  5.        ,  0.89285714],
       [ 5.        , 10.        ,  0.89473684],
       [ 5.        , 15.        ,  0.89473684],
       [ 5.        , 20.        ,  0.90037594],
       [10.        ,  1.        ,  0.88157895],
       [10.        ,  2.        ,  0.88533835],
       [10.        ,  3.        ,  0.87969925],
       [10.        ,  4.        ,  0.88909774],
       [10.        ,  5.        ,  0.89661654],
       [10.        , 10.        ,  0.89473684],
       [10.        , 15.        ,  0.89661654],
       [10.        , 20.        ,  0.89849624],
       [15.        ,  1.        ,  0.88721805],
       [15.        ,  2.        ,  0.88721805],
       [15.        ,  3.        ,  0.89285714],
       [15.        ,  4.        ,  0.88721805],
       [15.        ,  5.        ,  0.88533835],
       [15.        , 10.        ,  0.88909774],
       [15.        , 15.        ,  0.89097744],
       [15.        , 20.        ,  0.89473684]])

The best results we get here are around 91.2% accuracy. This is very far from the 98.9% accuracy we had with the optimized SVC. The SVC was extremely easy to optimize and is already built for these kind of problems. Indeed, the dataset is quite small, has barely any outliers and is overall very a "clean" one. All of these things make the SVC an ideal classifier for this problem. The ANN is slightly more difficult to tune because of its larger number of strong parameters and the time it takes to train. Furthermore the small size of the dataset that was an advantage for the SVC becomes an inconvenient for the ANN and makes it prone to overfitting.

A few other things that we could change to try to optimize the ANN would be the number of neurons per layer, the number of layers, type of activation functions, type of scaling for our data, etc. Since the computing time taken is higher for the ANN than it is for the SVC, we decided not to do this since our result of 98.9% accuracy for the SVC is already satisfactory.


Thanks for reading, I hope you learnt something. All feedback is welcome !

Written on October 29, 2017