Import the libraries

In [1]:
import tensorflow as tf
import numpy as np
import pandas as pd
import matplotlib.pyplot as plt

Read the input data

In [2]:
df = pd.read_csv('Iris.csv')

Take a look at the data

Take a look at the first few rows

In [3]:
print(df.head())
   Id  SepalLengthCm  SepalWidthCm  PetalLengthCm  PetalWidthCm      Species
0   1            5.1           3.5            1.4           0.2  Iris-setosa
1   2            4.9           3.0            1.4           0.2  Iris-setosa
2   3            4.7           3.2            1.3           0.2  Iris-setosa
3   4            4.6           3.1            1.5           0.2  Iris-setosa
4   5            5.0           3.6            1.4           0.2  Iris-setosa

Take a look at the number of rows and columns

In [4]:
rows, cols = df.shape
print(rows)
print(cols)
150
6

Convert string values to numeric values

In [5]:
label_names = df['Species'].unique()

print(label_names)
['Iris-setosa' 'Iris-versicolor' 'Iris-virginica']
In [6]:
index_and_label = list(enumerate(label_names))

print(index_and_label)
[(0, 'Iris-setosa'), (1, 'Iris-versicolor'), (2, 'Iris-virginica')]
In [7]:
label_to_index = dict((label, index) for index, label in index_and_label)

print(label_to_index)
{'Iris-setosa': 0, 'Iris-versicolor': 1, 'Iris-virginica': 2}
In [8]:
df = df.replace(label_to_index)

print(df.head())
   Id  SepalLengthCm  SepalWidthCm  PetalLengthCm  PetalWidthCm  Species
0   1            5.1           3.5            1.4           0.2        0
1   2            4.9           3.0            1.4           0.2        0
2   3            4.7           3.2            1.3           0.2        0
3   4            4.6           3.1            1.5           0.2        0
4   5            5.0           3.6            1.4           0.2        0

Shuffle the data

In [9]:
df = df.sample(frac=1.0)

Split the data into training and testing data

In [10]:
train_data = df.iloc[:120, :]
test_data = df.iloc[120:, :]

x_train = train_data.iloc[:, 1:-1]
y_train = train_data.iloc[:, -1:]

x_test = test_data.iloc[:, 1:-1]
y_test = test_data.iloc[:, -1:]
In [11]:
print(len(train_data))
print(len(test_data))
120
30

Scale the numerical inputs

In [12]:
def scale_column(train_data, test_data, column):
    min_value = train_data[column].min()
    max_value = train_data[column].max()
    train_data[column] = (train_data[column] - min_value)/(max_value - min_value)
    test_data[column] = (test_data[column] - min_value)/(max_value - min_value)
In [13]:
scale_column(x_train, x_test, "SepalLengthCm")
scale_column(x_train, x_test, "SepalWidthCm")
scale_column(x_train, x_test, "PetalLengthCm")
scale_column(x_train, x_test, "PetalWidthCm")

Take a look at the final transformed data

In [14]:
print(x_train.head())
     SepalLengthCm  SepalWidthCm  PetalLengthCm  PetalWidthCm
148       0.527778      0.545455       0.741379      0.916667
53        0.333333      0.045455       0.500000      0.500000
131       1.000000      0.727273       0.913793      0.791667
90        0.333333      0.181818       0.568966      0.458333
122       0.944444      0.272727       0.965517      0.791667

Convert to Numpy arrays

In [15]:
x_train = x_train.to_numpy()
y_train = y_train.to_numpy()

x_test = x_test.to_numpy()
y_test = y_test.to_numpy()
In [16]:
print(x_train.shape)
print(y_train.shape)
print(x_test.shape)
print(y_test.shape)
(120, 4)
(120, 1)
(30, 4)
(30, 1)

Build the neural network model

In [17]:
model = tf.keras.Sequential()

model.add(tf.keras.layers.Input(shape=[4]))
model.add(tf.keras.layers.Dense(units=64, activation='relu'))
model.add(tf.keras.layers.Dense(units=3, activation='softmax'))

model.summary()
Model: "sequential"
_________________________________________________________________
Layer (type)                 Output Shape              Param #   
=================================================================
dense (Dense)                (None, 64)                320       
_________________________________________________________________
dense_1 (Dense)              (None, 3)                 195       
=================================================================
Total params: 515
Trainable params: 515
Non-trainable params: 0
_________________________________________________________________

Choose the loss function and optimizer

In [18]:
model.compile(optimizer='Adam', loss='sparse_categorical_crossentropy', metrics=['accuracy'])

Start the training process

In [19]:
history = model.fit(x_train, y_train, validation_data=(x_test, y_test), epochs=75)
WARNING: Logging before flag parsing goes to stderr.
W0917 09:41:58.222157 139881287997248 deprecation.py:323] From /home/rishi/Programs/ML/mlvenv/lib/python3.7/site-packages/tensorflow/python/ops/math_grad.py:1250: add_dispatch_support.<locals>.wrapper (from tensorflow.python.ops.array_ops) is deprecated and will be removed in a future version.
Instructions for updating:
Use tf.where in 2.0, which has the same broadcast rule as np.where
Train on 120 samples, validate on 30 samples
Epoch 1/75
120/120 [==============================] - 0s 2ms/sample - loss: 1.1374 - accuracy: 0.3583 - val_loss: 1.1492 - val_accuracy: 0.2333
Epoch 2/75
120/120 [==============================] - 0s 100us/sample - loss: 1.1183 - accuracy: 0.3583 - val_loss: 1.1338 - val_accuracy: 0.2333
Epoch 3/75
120/120 [==============================] - 0s 103us/sample - loss: 1.1005 - accuracy: 0.3583 - val_loss: 1.1203 - val_accuracy: 0.2333
Epoch 4/75
120/120 [==============================] - 0s 113us/sample - loss: 1.0840 - accuracy: 0.3583 - val_loss: 1.1041 - val_accuracy: 0.2333
Epoch 5/75
120/120 [==============================] - 0s 112us/sample - loss: 1.0675 - accuracy: 0.3917 - val_loss: 1.0900 - val_accuracy: 0.2667
Epoch 6/75
120/120 [==============================] - 0s 140us/sample - loss: 1.0519 - accuracy: 0.4917 - val_loss: 1.0768 - val_accuracy: 0.2667
Epoch 7/75
120/120 [==============================] - 0s 103us/sample - loss: 1.0362 - accuracy: 0.5750 - val_loss: 1.0638 - val_accuracy: 0.4000
Epoch 8/75
120/120 [==============================] - 0s 100us/sample - loss: 1.0215 - accuracy: 0.6667 - val_loss: 1.0509 - val_accuracy: 0.4000
Epoch 9/75
120/120 [==============================] - 0s 109us/sample - loss: 1.0066 - accuracy: 0.7167 - val_loss: 1.0362 - val_accuracy: 0.4000
Epoch 10/75
120/120 [==============================] - 0s 114us/sample - loss: 0.9920 - accuracy: 0.7250 - val_loss: 1.0245 - val_accuracy: 0.4000
Epoch 11/75
120/120 [==============================] - 0s 121us/sample - loss: 0.9779 - accuracy: 0.7250 - val_loss: 1.0087 - val_accuracy: 0.4000
Epoch 12/75
120/120 [==============================] - 0s 126us/sample - loss: 0.9631 - accuracy: 0.7250 - val_loss: 0.9969 - val_accuracy: 0.4000
Epoch 13/75
120/120 [==============================] - 0s 102us/sample - loss: 0.9488 - accuracy: 0.7250 - val_loss: 0.9803 - val_accuracy: 0.4000
Epoch 14/75
120/120 [==============================] - 0s 116us/sample - loss: 0.9338 - accuracy: 0.7250 - val_loss: 0.9653 - val_accuracy: 0.4000
Epoch 15/75
120/120 [==============================] - 0s 98us/sample - loss: 0.9188 - accuracy: 0.7250 - val_loss: 0.9509 - val_accuracy: 0.4000
Epoch 16/75
120/120 [==============================] - 0s 118us/sample - loss: 0.9038 - accuracy: 0.7250 - val_loss: 0.9355 - val_accuracy: 0.4000
Epoch 17/75
120/120 [==============================] - 0s 106us/sample - loss: 0.8893 - accuracy: 0.7250 - val_loss: 0.9221 - val_accuracy: 0.4000
Epoch 18/75
120/120 [==============================] - 0s 110us/sample - loss: 0.8746 - accuracy: 0.7333 - val_loss: 0.9053 - val_accuracy: 0.4000
Epoch 19/75
120/120 [==============================] - 0s 111us/sample - loss: 0.8592 - accuracy: 0.7333 - val_loss: 0.8921 - val_accuracy: 0.4000
Epoch 20/75
120/120 [==============================] - 0s 129us/sample - loss: 0.8445 - accuracy: 0.7333 - val_loss: 0.8802 - val_accuracy: 0.4000
Epoch 21/75
120/120 [==============================] - 0s 100us/sample - loss: 0.8291 - accuracy: 0.7333 - val_loss: 0.8679 - val_accuracy: 0.4000
Epoch 22/75
120/120 [==============================] - 0s 102us/sample - loss: 0.8138 - accuracy: 0.7417 - val_loss: 0.8537 - val_accuracy: 0.4000
Epoch 23/75
120/120 [==============================] - 0s 101us/sample - loss: 0.7988 - accuracy: 0.7750 - val_loss: 0.8361 - val_accuracy: 0.5333
Epoch 24/75
120/120 [==============================] - 0s 127us/sample - loss: 0.7826 - accuracy: 0.8000 - val_loss: 0.8237 - val_accuracy: 0.5333
Epoch 25/75
120/120 [==============================] - 0s 135us/sample - loss: 0.7671 - accuracy: 0.8167 - val_loss: 0.8093 - val_accuracy: 0.5333
Epoch 26/75
120/120 [==============================] - 0s 136us/sample - loss: 0.7519 - accuracy: 0.8167 - val_loss: 0.7981 - val_accuracy: 0.5667
Epoch 27/75
120/120 [==============================] - 0s 146us/sample - loss: 0.7368 - accuracy: 0.8417 - val_loss: 0.7837 - val_accuracy: 0.6333
Epoch 28/75
120/120 [==============================] - 0s 160us/sample - loss: 0.7219 - accuracy: 0.8500 - val_loss: 0.7728 - val_accuracy: 0.6333
Epoch 29/75
120/120 [==============================] - 0s 148us/sample - loss: 0.7077 - accuracy: 0.8583 - val_loss: 0.7602 - val_accuracy: 0.6667
Epoch 30/75
120/120 [==============================] - 0s 175us/sample - loss: 0.6937 - accuracy: 0.8833 - val_loss: 0.7469 - val_accuracy: 0.7000
Epoch 31/75
120/120 [==============================] - 0s 213us/sample - loss: 0.6801 - accuracy: 0.8833 - val_loss: 0.7309 - val_accuracy: 0.7333
Epoch 32/75
120/120 [==============================] - 0s 154us/sample - loss: 0.6665 - accuracy: 0.9000 - val_loss: 0.7171 - val_accuracy: 0.7667
Epoch 33/75
120/120 [==============================] - 0s 184us/sample - loss: 0.6542 - accuracy: 0.9000 - val_loss: 0.7075 - val_accuracy: 0.7667
Epoch 34/75
120/120 [==============================] - 0s 135us/sample - loss: 0.6410 - accuracy: 0.9333 - val_loss: 0.6916 - val_accuracy: 0.9000
Epoch 35/75
120/120 [==============================] - 0s 162us/sample - loss: 0.6291 - accuracy: 0.9667 - val_loss: 0.6800 - val_accuracy: 0.9333
Epoch 36/75
120/120 [==============================] - 0s 158us/sample - loss: 0.6176 - accuracy: 0.9583 - val_loss: 0.6711 - val_accuracy: 0.9333
Epoch 37/75
120/120 [==============================] - 0s 139us/sample - loss: 0.6061 - accuracy: 0.9667 - val_loss: 0.6613 - val_accuracy: 0.9333
Epoch 38/75
120/120 [==============================] - 0s 164us/sample - loss: 0.5952 - accuracy: 0.9667 - val_loss: 0.6529 - val_accuracy: 0.9333
Epoch 39/75
120/120 [==============================] - 0s 150us/sample - loss: 0.5848 - accuracy: 0.9667 - val_loss: 0.6444 - val_accuracy: 0.9333
Epoch 40/75
120/120 [==============================] - 0s 169us/sample - loss: 0.5748 - accuracy: 0.9667 - val_loss: 0.6348 - val_accuracy: 0.9333
Epoch 41/75
120/120 [==============================] - 0s 193us/sample - loss: 0.5648 - accuracy: 0.9667 - val_loss: 0.6271 - val_accuracy: 0.9333
Epoch 42/75
120/120 [==============================] - 0s 161us/sample - loss: 0.5556 - accuracy: 0.9667 - val_loss: 0.6203 - val_accuracy: 0.9333
Epoch 43/75
120/120 [==============================] - 0s 138us/sample - loss: 0.5465 - accuracy: 0.9667 - val_loss: 0.6139 - val_accuracy: 0.9333
Epoch 44/75
120/120 [==============================] - 0s 154us/sample - loss: 0.5385 - accuracy: 0.9667 - val_loss: 0.6107 - val_accuracy: 0.9333
Epoch 45/75
120/120 [==============================] - 0s 112us/sample - loss: 0.5299 - accuracy: 0.9583 - val_loss: 0.6074 - val_accuracy: 0.9333
Epoch 46/75
120/120 [==============================] - 0s 110us/sample - loss: 0.5216 - accuracy: 0.9667 - val_loss: 0.5994 - val_accuracy: 0.9333
Epoch 47/75
120/120 [==============================] - 0s 111us/sample - loss: 0.5141 - accuracy: 0.9667 - val_loss: 0.5914 - val_accuracy: 0.9333
Epoch 48/75
120/120 [==============================] - 0s 114us/sample - loss: 0.5067 - accuracy: 0.9667 - val_loss: 0.5835 - val_accuracy: 0.9333
Epoch 49/75
120/120 [==============================] - 0s 128us/sample - loss: 0.4997 - accuracy: 0.9667 - val_loss: 0.5791 - val_accuracy: 0.9333
Epoch 50/75
120/120 [==============================] - 0s 118us/sample - loss: 0.4931 - accuracy: 0.9667 - val_loss: 0.5714 - val_accuracy: 0.9333
Epoch 51/75
120/120 [==============================] - 0s 110us/sample - loss: 0.4867 - accuracy: 0.9667 - val_loss: 0.5707 - val_accuracy: 0.9333
Epoch 52/75
120/120 [==============================] - 0s 121us/sample - loss: 0.4802 - accuracy: 0.9750 - val_loss: 0.5620 - val_accuracy: 0.9333
Epoch 53/75
120/120 [==============================] - 0s 92us/sample - loss: 0.4739 - accuracy: 0.9667 - val_loss: 0.5594 - val_accuracy: 0.9333
Epoch 54/75
120/120 [==============================] - 0s 139us/sample - loss: 0.4682 - accuracy: 0.9667 - val_loss: 0.5535 - val_accuracy: 0.9333
Epoch 55/75
120/120 [==============================] - 0s 110us/sample - loss: 0.4624 - accuracy: 0.9750 - val_loss: 0.5521 - val_accuracy: 0.9333
Epoch 56/75
120/120 [==============================] - 0s 124us/sample - loss: 0.4569 - accuracy: 0.9750 - val_loss: 0.5494 - val_accuracy: 0.9333
Epoch 57/75
120/120 [==============================] - 0s 118us/sample - loss: 0.4517 - accuracy: 0.9750 - val_loss: 0.5438 - val_accuracy: 0.9333
Epoch 58/75
120/120 [==============================] - 0s 110us/sample - loss: 0.4465 - accuracy: 0.9750 - val_loss: 0.5402 - val_accuracy: 0.9333
Epoch 59/75
120/120 [==============================] - 0s 133us/sample - loss: 0.4419 - accuracy: 0.9667 - val_loss: 0.5375 - val_accuracy: 0.9000
Epoch 60/75
120/120 [==============================] - 0s 109us/sample - loss: 0.4368 - accuracy: 0.9667 - val_loss: 0.5338 - val_accuracy: 0.9000
Epoch 61/75
120/120 [==============================] - 0s 133us/sample - loss: 0.4321 - accuracy: 0.9667 - val_loss: 0.5261 - val_accuracy: 0.9333
Epoch 62/75
120/120 [==============================] - 0s 135us/sample - loss: 0.4277 - accuracy: 0.9750 - val_loss: 0.5173 - val_accuracy: 0.9333
Epoch 63/75
120/120 [==============================] - 0s 170us/sample - loss: 0.4230 - accuracy: 0.9750 - val_loss: 0.5129 - val_accuracy: 0.9333
Epoch 64/75
120/120 [==============================] - 0s 123us/sample - loss: 0.4185 - accuracy: 0.9750 - val_loss: 0.5083 - val_accuracy: 0.9333
Epoch 65/75
120/120 [==============================] - ETA: 0s - loss: 0.3866 - accuracy: 1.00 - 0s 185us/sample - loss: 0.4139 - accuracy: 0.9750 - val_loss: 0.5059 - val_accuracy: 0.9333
Epoch 66/75
120/120 [==============================] - 0s 241us/sample - loss: 0.4098 - accuracy: 0.9750 - val_loss: 0.5019 - val_accuracy: 0.9333
Epoch 67/75
120/120 [==============================] - 0s 147us/sample - loss: 0.4054 - accuracy: 0.9750 - val_loss: 0.4990 - val_accuracy: 0.9333
Epoch 68/75
120/120 [==============================] - 0s 171us/sample - loss: 0.4014 - accuracy: 0.9750 - val_loss: 0.5002 - val_accuracy: 0.9000
Epoch 69/75
120/120 [==============================] - 0s 316us/sample - loss: 0.3974 - accuracy: 0.9750 - val_loss: 0.4940 - val_accuracy: 0.9333
Epoch 70/75
120/120 [==============================] - 0s 180us/sample - loss: 0.3935 - accuracy: 0.9750 - val_loss: 0.4952 - val_accuracy: 0.9000
Epoch 71/75
120/120 [==============================] - 0s 140us/sample - loss: 0.3892 - accuracy: 0.9750 - val_loss: 0.4898 - val_accuracy: 0.9000
Epoch 72/75
120/120 [==============================] - 0s 129us/sample - loss: 0.3856 - accuracy: 0.9750 - val_loss: 0.4814 - val_accuracy: 0.9333
Epoch 73/75
120/120 [==============================] - 0s 163us/sample - loss: 0.3811 - accuracy: 0.9750 - val_loss: 0.4776 - val_accuracy: 0.9333
Epoch 74/75
120/120 [==============================] - 0s 132us/sample - loss: 0.3774 - accuracy: 0.9750 - val_loss: 0.4757 - val_accuracy: 0.9000
Epoch 75/75
120/120 [==============================] - 0s 144us/sample - loss: 0.3734 - accuracy: 0.9750 - val_loss: 0.4693 - val_accuracy: 0.9333

Evaluate with test data

In [20]:
test_loss, test_acc = model.evaluate(x_test, y_test)

print(test_acc)
30/30 [==============================] - 0s 47us/sample - loss: 0.4693 - accuracy: 0.9333
0.93333334

Plot training and validation loss

In [21]:
plt.figure(figsize=(20, 10))
plt.subplot(2, 2, 1)
plt.plot(history.history['loss'])
plt.subplot(2, 2, 2)
plt.plot(history.history['accuracy'])
plt.subplot(2, 2, 3)
plt.plot(history.history['val_loss'])
plt.subplot(2, 2, 4)
plt.plot(history.history['val_accuracy'])
plt.show()