+1 (315) 557-6473 

Python Program to Classify Various Iris Plants Assignment Solution.


Instructions

Objective
Write a python assignment to classify various iris plants.

Requirements and Specifications

program to classify various iris plants in python

Source Code

import numpy as np

import pandas as pd

from sklearn.preprocessing import OneHotEncoder

import matplotlib.pyplot as plt

class NeuralNetwork:

def __init__(self, layers, X=None, y=None,

activation=lambda x: 1 / (1 + np.exp(-x)),

deriv_activation=lambda x: np.multiply(x, 1 - x), learning_rate=0.15):

self.X = X

self.y = y

self.weights = list()

self.layers = layers

self.X_train = None

self.y_train = None

self.X_test = None

self.y_test = None

self.act = activation

self.dact = deriv_activation

self.lr = learning_rate

self.losses = list()

self.accuracies = list()

def train_test_split(self, test_size = 0.3):

if self.X is None:

raise ValueError('No dataset has been loaded into the Neural Network model')

# Compute the number of training samples

n_train = len(self.X)-int(test_size * len(self.X))

# Split

self.X_train = self.X[:n_train]

self.y_train = self.y[:n_train]

self.X_test = self.X[n_train:]

self.y_test = self.y[n_train:]

# print info

print(f"There are a total of {len(self.X)} samples and {len(self.y[0])} features in the dataset.")

print(f"There are {len(self.X_train)} samples in the train dataset.")

print(f"There are {len(self.X_test)} samples in the test dataset.")

def initialize_weights(self, layers):

# Initialize weights for hidden layers (not taking into account the input and output layers)

n_layers = len(layers)

for i in range(1, n_layers):

w = [

[np.random.uniform(-1, 1) for k in range(layers[i - 1] + 1)] for j in range(layers[i])

]

self.weights.append(np.matrix(w))

def fit(self, epochs=10):

# Initialize weights for hidden layers (not taking into account the input and output layers)

n_layers = len(self.layers) - 1

self.initialize_weights(self.layers)

# Update weights and print acc for each epoch

print('-' * 40)

print('{:<10s}{:>10s}{:>12s}'.format('Epoch', 'Accuracy (%)', 'Loss'))

print('{:<10s}{:>10s}{:>12s}'.format('-----', '------------', '----'))

for epoch in range(epochs):

# Update weights

err = self.train()

# Compute current accuracy

accuracy = self.accuracy(self.X_train, self.y_train)

print('{:<10d}{:<20.2f}{:<20.6f}'.format(epoch + 1, accuracy * 100.0, abs(err.mean())))

self.losses.append(abs(err.mean()))

self.accuracies.append(accuracy)

# After all training, print test accuracy

print('-' * 40)

val_acc = self.accuracy(self.X_test, self.y_test)

print('Model accuracy: {:.2f}%'.format(val_acc * 100.0))

print('-' * 40)

def accuracy(self, X, y):

n_good = 0

for i in range(len(X)):

y_pred = self.predict(X[i])

if list(y[i]) == y_pred:

n_good += 1

return n_good / len(X)

def predict(self, X):

X = np.append(1, X)

# Compute the activations

result = self.forward_prop(X)

output = result[-1].A1

index = self.find_max_activation(output)

y = [0 for i in range(len(output))]

y[index] = 1

return y

def find_max_activation(self, output):

m, index = output[0], 0

for i in range(1, len(output)):

if output[i] > m:

m, index = output[i], i

return index

def forward_prop(self, x):

activations = [x]

layer_input = x

for i in range(len(self.weights)):

activation = self.act(np.dot(layer_input, self.weights[i].T))

activations.append(activation)

layer_input = np.append(1, activation) # Augment with bias

return activations

def backward_prop(self, y, activations):

outputFinal = activations[-1]

error = np.matrix(y - outputFinal) # Error at output

; finalErr = None

n_layers = len(self.weights)

for j in range(n_layers, 0, -1):

currActivation = activations[j]

if j > 1:

# Augment previous activation

prevActivation = np.append(1, activations[j - 1])

else:

# First hidden layer, prevActivation is input (without bias)

prevActivation = activations[0]

delta = np.multiply(error, self.dact(currActivation))

self.weights[j - 1] += self.lr * np.multiply(delta.T, prevActivation)

# Remove bias from weights to calculate error

w = np.delete(self.weights[j - 1], [0], axis=1)

error = np.dot(delta, w) # Error at current layer

if j == 1:

finalErr = error

return finalErr

def train(self):

X = self.X_train

Y = self.y_train

n_layers = len(self.weights)

for i in range(len(X)):

x, y = X[i], Y[i]

x = np.matrix(np.append(1, x)) # Augment feature vector

activations = self.forward_prop(x)

err = self.backward_prop(y, activations)

return err

if __name__ == '__main__':

# Load data

df = pd.read_csv('ANN - Iris data.txt', header=None, names=['sepal_length', 'sepal_width',

'petal_length', 'petal_width', 'label'])

# Extract dependant and independent variables and convert to numpy arrays

y = df['label'].to_numpy()

X = df.drop(columns=['label']).to_numpy()

# Encode the dependent variable y

y = y.reshape(-1, 1)

encoder = OneHotEncoder(sparse=False)

y = encoder.fit_transform(y)

layers = [X.shape[1], 8, 16, y.shape[1]]

epochs = 100

nn = NeuralNetwork(layers, X, y)

nn.train_test_split(0.2)

nn.fit(epochs)

# Plot accuracy and loss

fig, axes = plt.subplots(nrows=1, ncols=2)

axes[0].plot(range(epochs), nn.accuracies)

axes[0].set_xlabel('Epoch')

axes[0].set_ylabel('Accuracy (%)')

axes[0].grid(True)

axes[1].plot(range(epochs), nn.losses)

axes[1].set_xlabel('Epoch')

axes[1].set_ylabel('Loss')

axes[1].grid(True)

plt.show()