0% found this document useful (0 votes)
59 views53 pages

ML Lab Manual

lab manual

Uploaded by

Sprout Gigs
Copyright
© © All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as PDF, TXT or read online on Scribd
0% found this document useful (0 votes)
59 views53 pages

ML Lab Manual

lab manual

Uploaded by

Sprout Gigs
Copyright
© © All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as PDF, TXT or read online on Scribd
You are on page 1/ 53

UNIVERSITY OF GUJRAT

Session (2020-2024)
DEPARTMENT OF E LECTRICAL ENGINEERING
Semester (Seventh)
=================================================

LAB REPORTS

SUBMITTED BY: FARYAL NAEEM MEHMOOD

ROLL NUMBER: 20013122-001

COURSE NAME: MACHINE LEARNING LAB

COURSE CODE: EE-430

SUBMITTED TO: ENGR. ALI ASGHAR

==================================================
Experiment No. 1

Title: “Introduction to Machine Learning Lab”

Objective: The main aim of this lab is:


1. To introduce basics of machine learning lab.
2. To discuss different types of machine learning
3. To study the applications of machine learning.
4. To study the Neural Networks.

Introduction:

Machine learning (ML) is defined as a discipline of artificial intelligence (AI) that provides
machines the ability to automatically learn from data and past experiences to identify patterns and
make predictions with minimal human intervention. Machine learning is a subset of AI, which
enables the machine to automatically learn from data, improve performance from past experiences,
and make predictions. Machine learning contains a set of algorithms that work on a huge amount
of data. Data is fed to these algorithms to train them, and on the basis of training, they build the
model & perform a specific task. These ML algorithms help to solve different business problems
like Regression, Classification, Forecasting, Clustering, and Associations, etc. Based on the
methods and way of learning, machine learning is divided into mainly four types, which are:

1. Supervised Machine Learning: As its name suggests, Supervised machine learning is based
on supervision. It means in the supervised learning technique, we train the machines using the
"labelled" dataset, and based on the training, the machine predicts the output. Here, the labelled
data specifies that some of the inputs are already mapped to the output. More preciously, we can
say; first, we train the machine with the input and corresponding output, and then we ask the
machine to predict the output using the test dataset. Let's understand supervised learning with an
example. Suppose we have an input dataset of cats and dog images. So, first, we will provide the
training to the machine to understand the images, such as the shape & size of the tail of cat and
dog, Shape of eyes, color, height (dogs are taller, cats are smaller), etc. After completion of
training, we input the picture of a cat and ask the machine to identify the object and predict the
output. Now, the machine is well trained, so it will check all the features of the object, such as
height, shape, color, eyes, ears, tail, etc., and find that it's a cat. So, it will put it in the Cat category.
This is the process of how the machine identifies the objects in Supervised Learning. Supervised
machine learning can be classified into two types of problems.

1. Classification algorithms are used to solve the classification problems in which


the output variable is categorical, such as "Yes" or No, Male or Female, Red or
Blue, etc. The classification algorithms predict the categories present in the dataset.
Some real-world examples of classification algorithms are Spam Detection, Email
filtering, etc.
2. Regression algorithms are used to solve regression problems in which there is a
linear relationship between input and output variables. These are used to predict
continuous output variables, such as market trends, weather prediction, etc.

2. Unsupervised Learning: Unsupervised learning is different from the Supervised learning


technique; as its name suggests, there is no need for supervision. It means, in unsupervised machine
learning, the machine is trained using the unlabeled dataset, and the machine predicts the output
without any supervision. In unsupervised learning, the models are trained with the data that is
neither classified nor labelled, and the model acts on that data without any supervision. The main
aim of the unsupervised learning algorithm is to group or categories the unsorted dataset according
to the similarities, patterns, and differences. Machines are instructed to find the hidden patterns
from the input dataset. Let's take an example to understand it more preciously; suppose there is a
basket of fruit images, and we input it into the machine learning model. The images are totally
unknown to the model, and the task of the machine is to find the patterns and categories of the
objects. So, now the machine will discover its patterns and differences, such as color difference,
shape difference, and predict the output when it is tested with the test dataset.

1. The clustering technique is used when we want to find the inherent groups from the data.
It is a way to group the objects into a cluster such that the objects with the most similarities
remain in one group and have fewer or no similarities with the objects of other groups. An
example of the clustering algorithm is grouping the customers by their purchasing
behavior.
2. Association rule learning is an unsupervised learning technique, which finds interesting
relations among variables within a large dataset. The main aim of this learning algorithm
is to find the dependency of one data item on another data item and map those variables
accordingly so that it can generate maximum profit. This algorithm is mainly applied
in Market Basket analysis, Web usage mining, continuous production, etc.

3. Semi Supervised Learning:

Semi-Supervised learning is a type of Machine Learning algorithm that lies between Supervised
and Unsupervised machine learning. It represents the intermediate ground between Supervised
(With Labelled training data) and Unsupervised learning (with no labelled training data)
algorithms and uses the combination of labelled and unlabeled datasets during the training period.
Although Semi-supervised learning is the middle ground between supervised and unsupervised
learning and operates on the data that consists of a few labels, it mostly consists of unlabeled data.
As labels are costly, but for corporate purposes, they may have few labels. It is completely different
from supervised and unsupervised learning as they are based on the presence & absence of labels.
To overcome the drawbacks of supervised learning and unsupervised learning algorithms, the
concept of Semi-supervised learning is introduced. The main aim of semi-supervised learning is
to effectively use all the available data, rather than only labelled data like in supervised learning.
Initially, similar data is clustered along with an unsupervised learning algorithm, and further, it
helps to label the unlabeled data into labelled data. It is because labelled data is a comparatively
more expensive acquisition than unlabeled data.

4.Reinforcement Learning:
Reinforcement learning works on a feedback-based process, in which an AI agent (A software
component) automatically explore its surrounding by hitting & trail, taking action, learning from
experiences, and improving its performance. Agent gets rewarded for each good action and get
punished for each bad action; hence the goal of reinforcement learning agent is to maximize the
rewards. In reinforcement learning, there is no labelled data like supervised learning, and agents
learn from their experiences only. The reinforcement learning process is similar to a human being;
for example, a child learns various things by experiences in his day-to-day life. An example of
reinforcement learning is to play a game, where the Game is the environment, moves of an agent
at each step define states, and the goal of the agent is to get a high score. Agent receives feedback
in terms of punishment and rewards.

Applications of Machine Learning:


1. Image Recognition: Image recognition is one of the most common applications of
machine learning. It is used to identify objects, persons, places, digital images, etc. The
popular use case of image recognition and face detection is, Automatic friend tagging
suggestion: Facebook provides us a feature of auto friend tagging suggestion. Whenever
we upload a photo with our Facebook friends, then we automatically get a tagging
suggestion with name, and the technology behind this is machine learning's face
detection and recognition algorithm. It is based on the Facebook project named "Deep
Face," which is responsible for face recognition and person identification in the picture.
2. Traffic prediction: If we want to visit a new place, we take help of Google Maps, which
shows us the correct path with the shortest route and predicts the traffic conditions. It
predicts the traffic conditions such as whether traffic is cleared, slow-moving, or heavily
congested with the help of two ways:

 Real Time location of the vehicle form Google Map app and sensors
 Average time has taken on past days at the same time.

3. Medical Diagnosis: In medical science, machine learning is used for diseases diagnoses.
With this, medical technology is growing very fast and able to build 3D models that can
predict the exact position of lesions in the brain. It helps in finding brain tumors and other
brain-related diseases easily.
4. Stock Market trading: Machine learning is widely used in stock market trading. In the
stock market, there is always a risk of up and downs in shares, so for this machine
learning's long short term memory neural network is used for the prediction of stock market
trends.
5. Online Fraud Detection: Machine learning is making our online transaction safe and
secure by detecting fraud transaction. Whenever we perform some online transaction, there
may be various ways that a fraudulent transaction can take place such as fake
accounts, fake ids, and steal money in the middle of a transaction. So to detect this, Feed
Forward Neural network helps us by checking whether it is a genuine transaction or a fraud
transaction. For each genuine transaction, the output is converted into some hash values,
and these values become the input for the next round. For each genuine transaction, there
is a specific pattern which gets change for the fraud transaction hence, it detects it and
makes our online transactions more secure.
Neural Networks: A neural network is a machine learning (ML) model designed to mimic the
function and structure of the human brain. Neural networks are intricate networks of
interconnected nodes, or neurons, that collaborate to tackle complicated problems. Also referred
to as artificial neural networks (ANNs) or deep neural networks, neural networks represent a type
of deep learning technology that's classified under the broader field of artificial intelligence (AI).
Neural networks are widely used in a variety of applications, including image recognition,
predictive modeling and natural language processing (NLP). Examples of significant commercial
applications since 2000 include handwriting recognition for check processing, speech-to-text
transcription, oil exploration data analysis, weather prediction and facial recognition.

How do artificial neural networks work?


An artificial neural network usually involves many processors operating in parallel and arranged
in tiers or layers. The first tier -- analogous to optic nerves in human visual processing -- receives
the raw input information. Each successive tier receives the output from the tier preceding it rather
than the raw input -- the same way neurons further from the optic nerve receive signals from those
closer to it. The last tier produces the output of the system. Each processing node has its own small
sphere of knowledge, including what it has seen and any rules it was originally programmed with
or developed for itself. The tiers are highly interconnected, which means each node in Tier N will
be connected to many nodes in Tier N-1 -- its inputs -- and in Tier N+1, which provides input data
for those nodes. There could be one or more nodes in the output layer, from which the answer it
produces can be read. Artificial neural networks are noted for being adaptive, which means they
modify themselves as they learn from initial training and subsequent runs provide more
information about the world. The most basic learning model is centered on weighting the input
streams, which is how each node measures the importance of input data from each of its
predecessors. Inputs that contribute to getting the right answers are weighted higher.

Conclusion:

In this Lab, I have covered all objectives which were to introduce the basics of machine learning,
discuss various types of machine learning, explore the real-world applications of machine learning,
and delve into the study of Neural Networks a fundamental building block of AI.
Experiment No. 2

Title: “Perceptron Learning Algorithm”

Objective: The main aim of this lab is:


1. To understand the perceptron learning algorithm
2. To execute this algorithm in Spyder environment

Apparatus:
1. Spyder environment

Procedure:
1. First of all, I opened a new file in Spyder.
2. I wrote the code for perceptron in Spyder.
3. I executed each line and showed its output.

Perceptron Learning Algorithm:


Initialization: set all of the weights wij to small (positive and negative) random numbers

Training: for T iterations or until all the outputs are correct

for each input vector:


To compute the activation of each neuron j using activation function g:

For updating the weights, update each of the weights individually using:

Recall:
To compute the activation of each neuron j using:
CODE:
import numpy as np

numpy is imported to perform mathematical operations.

inputs = np. array ([[0,0], [0,1], [1,0], [1,1]])

This line creates a Numpy array named "inputs" containing a 2D array with four rows and two
columns and showing four combinations of two inputs

# AND data

ANDtargets = np. array ([[0], [0], [0], [1]])

This line creates a Numpy array named "ANDtargets" containing a 2D array with four rows
and one column and showing target outputs for AND logic for above inputs.

# OR data

OR targets = np. array ([[0], [1], [1, [1]])

This line creates a Numpy array named "ORtargets" containing a 2D array with four rows and
one column and showing target outputs for OR logic for above inputs

import pcn_logic_eg

pcn_logic_eg is imported to perform further tasks of perceptron learning algorithm

print ("AND logic function")

It will print the AND logic function

pAND = pcn_logic_eg.pcn (inputs, ANDtargets)

This line creates an instance of a perceptron model using the "pcn" function from the
"pcn_logic_eg" module with the "inputs" and "ANDtargets" data. The specific output depends
on the implementation of the "pcn" function.

pAND.pcntrain(inputs, ANDtargets,0.25,6)
This line trains the perceptron model "pAND" with the specified parameters. The output will
depend on the implementation of the "pcntrain" method where 0.25 is the eta (learning rate)
and 6 is the total iterations.

print ("OR logic function")

This line prints the string "OR logic function" to the standard output.

pOR = pcn_logic_eg.pcn (inputs, ORtargets)

This line creates an instance of a perceptron model using the "pcn" function from the
"pcn_logic_eg" module with the "inputs" and "ORtargets" data. The specific output depends
on the implementation of the "pcn" function.

pOR.pcntrain(inputs, ORtargets,0.25,6)

This line trains the perceptron model "pOR" with the specified parameters. The output will
depend on the implementation of the "pcntrain" method where 0.25 is the eta (learning rate)
and 6 is the total iterations.

OUTPUT
Code For pcn_logic _eg :

import numpy as np

Import the numpy library and alias it as np.

class pcn:

Define a Python class named pcn.

""" A basic Perceptron (the same pcn.py except with the weights printed

and it does not reorder the inputs)"""

def __int__(self, inputs, targets):

""" Constructor """

Define the constructor for the pcn class, taking inputs and targets as arguments.

# Set up network size

if np. ndim(inputs) > 1:

Check if the input data has more than one dimension.

self. nIn = np. shape(inputs) [1]


Store the number of input features.

else:

self. nIn = 1

if np. ndim(targets) > 1:

Check if the target data has more than one dimension

self.nOut = np.shape(targets)[1]

Store the number of output classes.

else:

self. nOut = 1

self. nData = np. shape(inputs)

# Initialize network

self. weights = np. random.rand(self.nIn + 1, self.nOut) * 0.1 - 0.05

Initialize the network's weights with random values.

def pcntrain(self, inputs, targets, eta, nIterations):

Define a method to train the Perceptron.

""" Train the thing """

# Add the inputs that match the bias node

inputs = np.concatenate((inputs, -np.ones((self.nData, 1))), axis=1)

Add a bias term to the input data.

# Training

change = range(self.nData)

for n in range(nIterations):

Start a loop for training iterations.

self.activations = self.pcnfwd(inputs)

Start a loop for training iterations.


self.weights -= eta * np.dot(np.transpose(inputs), self.activations - targets)

Update the weights based on the Perceptron learning rule.

print('Iteration:', n)

Print the current iteration.

print(self.weights)

Print the updated weights.

activations = self.pcnfwd(inputs)

Calculate activations again.

print('Final outputs are:')

print(activations)

# return self.weights

def pcnfwd(self, inputs):

Define a method for the forward pass.

""" Run the network forward """

# Compute activations

activations = np.dot(inputs, self.weights)

# Threshold the activations

return np.where(activations > 0, 1, 0)

Apply the step function to threshold the activations.

def confmat(self, inputs, targets):

Define a method to compute a confusion matrix.

"""Confusion matrix"""

# Add the inputs that match the bias node

inputs = np.concatenate((inputs, -np.ones((self.nData, 1)), axis=1))

outputs = np.dot(inputs, self.weights)


Calculate Perceptron outputs.

nClasses = np.shape(targets)[1]

Determine the number of classes

if nClasses == 1:

nClasses = 2

outputs = np.where(outputs > 0, 1, 0)

else:

# 1-of-N encoding

outputs = np.argmax(outputs, 1)

Convert the outputs to class predictions.

targets = np.argmax(targets, 1)

cm = np.zeros((nClasses, nClasses))

Initialize a confusion matrix with zeros.

for i in range(nClasses):

for j in range(nClasses):

cm[i, j] = np.sum(np.where(outputs == i, 1, 0) * np.where(targets == j, 1, 0))

Compute elements of the confusion matrix.

print(cm)

Print the confusion matrix

print(np.trace(cm) / np.sum(cm)

Print the classification accuracy.


Experiment No. 3

Title: “Multi-layer Perceptron Learning Algorithm”

Objective: The main aim of this lab is:


1. To understand the multi-layer perceptron learning algorithm
2. To execute this algorithm in Spyder environment

Apparatus:
1. Spyder environment

Procedure:
1. First of all, I opened a new file in Spyder.
2. I wrote the code for MLP in Spyder.
3. I executed the code and showed its output.

Multi-Layer Perceptron Learning Algorithm:


Code for mlp:

import numpy as np
Imports the Numpy library and aliases it as np. Numpy is a powerful library for numerical
operations in Python.
class mlp:
""" A Multi-Layer Perceptron"""
Defines a class named mlp representing a Multi-Layer Perceptron (MLP).
def __init__(self,inputs,targets,nhidden,beta=1,momentum=0.9,outtype='logistic'):
Defines the constructor method for the mlp class. Initializes the MLP with input, target,
number of hidden neurons, beta, momentum, and output type.
""" Constructor """
# Set up network size
self.nin = np.shape(inputs)[1]
self.nout = np.shape(targets)[1]
self.ndata = np.shape(inputs)[0]
self.nhidden = nhidden
self.beta = beta
self.momentum = momentum
self.outtype = outtype
Initializes various attributes of the MLP, including the number of input, output, and
hidden neurons, as well as other parameters like beta, momentum, and output type.
# Initialise network
self.weights1 = (np.random.rand(self.nin+1,self.nhidden)-0.5)*2/np.sqrt(self.nin)
self.weights2 = (np.random.rand(self.nhidden+1,self.nout)-0.5)*2/np.sqrt(self.nhidden)
Initializes the weights for the connections between layers in the MLP using random values.
def mlptrain(self,inputs,targets,eta,niterations):
Defines a method to train the MLP. Takes input data, target data, learning rate (eta), and
the number of iterations as parameters.
""" Train the thing """
# Add the inputs that match the bias node
inputs = np.concatenate((inputs,-np.ones((self.ndata,1))),axis=1)
change = range(self.ndata)
Adds a bias node to the input data and creates an array 'change' with indices.
updatew1 = np.zeros((np.shape(self.weights1)))
updatew2 = np.zeros((np.shape(self.weights2)))
Initializes arrays to store weight updates during training.
for n in range(niterations):
Iterates over the specified number of training iterations.
self.outputs = self.mlpfwd(inputs)
error = 0.5*np.sum((self.outputs-targets)**2)
if (np.mod(n,100)==0):
print ("Iteration: ",n, " Error: ",error)
Performs forward propagation and calculates the error. Prints the error every 100
iterations.
# Different types of output neurons
if self.outtype == 'linear':
deltao = (self.outputs-targets)/self.ndata
elif self.outtype == 'logistic':
deltao = self.beta*(self.outputs-targets)*self.outputs*(1.0-self.outputs)
elif self.outtype == 'softmax':
deltao = (self.outputs-targets)*(self.outputs*(-self.outputs)+self.outputs)/self.ndata
else:
print ("error")
Calculates the output delta based on the specified output type (linear, logistic, or softmax).
deltah = self.hidden*self.beta*(1.0-self.hidden)*(np.dot(deltao,np.transpose(self.weights2)))
Calculates the hidden delta.
updatew1 = eta*(np.dot(np.transpose(inputs),deltah[:,:-1])) + self.momentum*updatew1
updatew2 = eta*(np.dot(np.transpose(self.hidden),deltao)) + self.momentum*updatew2
self.weights1 -= updatew1
self.weights2 -= updatew2
Updates the weights using backpropagation and momentum.
# Randomise order of inputs (not necessary for matrix-based calculation)
#np.random.shuffle(change)
#inputs = inputs[change,:]
#targets = targets[change,:]
def mlpfwd(self,inputs):
""" Run the network forward """
Defines a method to perform forward propagation in the MLP.
self.hidden = np.dot(inputs,self.weights1);
self.hidden = 1.0/(1.0+np.exp(-self.beta*self.hidden))
self.hidden = np.concatenate((self.hidden,-np.ones((np.shape(inputs)[0],1))),axis=1)
Calculates the output of the hidden layer using a sigmoid activation function.
outputs = np.dot(self.hidden,self.weights2);
Calculates the final outputs.
# Different types of output neurons
if self.outtype == 'linear':
return outputs
elif self.outtype == 'logistic':
return 1.0/(1.0+np.exp(-self.beta*outputs))
elif self.outtype == 'softmax':
normalisers = np.sum(np.exp(outputs),axis=1)*np.ones((1,np.shape(outputs)[0]))
return np.transpose(np.transpose(np.exp(outputs))/normalisers)
else:
print ("error")
Returns the final outputs based on the specified output type.
def confmat(self,inputs,targets):
"""Confusion matrix"""
Defines a method to calculate the confusion matrix.
# Add the inputs that match the bias node
inputs = np.concatenate((inputs,-np.ones((np.shape(inputs)[0],1))),axis=1)
outputs = self.mlpfwd(inputs)
nclasses = np.shape(targets)[1]
if nclasses==1:
nclasses = 2
outputs = np.where(outputs>0.5,1,0)
else:
# 1-of-N encoding
outputs = np.argmax(outputs,1)
targets = np.argmax(targets,1)
Adds a bias node to the input data for testing and adjusts outputs for binary classification
or 1-of-N encoding.
cm = np.zeros((nclasses,nclasses))
for i in range(nclasses):
for j in range(nclasses):
cm[i,j] = np.sum(np.where(outputs==i,1,0)*np.where(targets==j,1,0))
print ("Confusion matrix is:")
print (cm)
print ("Percentage Correct: ",np.trace(cm)/np.sum(cm)*100)
Calculates and prints the confusion matrix and percentage of correct predictions.
Conclusion: I have successfully executed the code on python
Experiment No. 4

Title: “Multi-layer Perceptron using regression example”

Objective: The main aim of this lab is:


1. To understand the multi-layer perceptron learning algorithm using regression example
2. To execute this algorithm in Spyder environment

Apparatus:
1. Spyder environment

Procedure:
1. First of all, I opened a new file in Spyder.
2. I wrote the code for MLP in Spyder.
3. I executed the code and showed its output

Code:
import numpy as np
Imports the Numpy library and aliases it as np. Numpy is a powerful library for numerical
operations in Python
x = np.ones((1,40))*np.linspace(0,1,40)
Creates a 1x40 matrix (x) filled with ones and multiplies it element-wise by an array
generated using np. linspace (0, 1, 40). This results in a matrix where each column is a
linearly spaced value between 0 and 1
t = np.sin(2*np.pi*x) + np.cos(4*np.pi*x) + np.random.randn(40)*0.2
Generates a target array t by applying sine and cosine functions to the elements of x, and
adds some random noise.
x = x.T
Transposes the matrix x, swapping rows and columns.
t = t.T
Transposes the array t.
import pylab as pl
Imports the pylab module from the Matplotlib library and aliases it as pl. Matplotlib is a
plotting library in Python.
pl.plot(x,t,'.')
Plots the points in the x and t arrays using a scatter plot.
train = x[0::2,:]
Creates a new array train by selecting every second row from the transposed x.
print(train)
Prints the train array.
test = x[1::4,:]
Creates a new array test by selecting every fourth row starting from the second row of the
transposed x.
print(test)
Prints the test array.
valid = x[3::4,:]
Creates a new array valid by selecting every fourth row starting from the third row of the
transposed x
print(valid)
Prints the valid array.
traintarget = t[0::2,:]
Creates a new array train target by selecting every second row from the transposed t
print(traintarget)
Prints the traintarget array.
testtarget = t[1::4,:]
Creates a new array test target by selecting every fourth row starting from the second row
of the transposed t.
print(testtarget)
Prints the testtarget array.
validtarget = t[3::4,:]
Creates a new array validtarget by selecting every fourth row starting from the third row
of the transposed t.
print(validtarget)
Prints the validtarget array.
import mlp
Imports a module named mlp. The code assumes that there is a module named mlp in the
working directory.
net = mlp.mlp(train,traintarget,3,outtype='linear')
Creates a neural network (net) using the mlp module, with the specified input, target, and
output layer size. The output type is set to 'linear'.
net.mlptrain(train,traintarget,0.25,101)
Trains the neural network (net) using the backpropagation algorithm with the training
data, target data, learning rate (0.25), and a maximum of 101 epochs

Results:
Conclusion: I have successfully executed above code in python without any error.
Experiment No. 5

Title: “Radial Basis Function Learning Algorithm”

Objective: The main aim of this lab is:


1. To understand the RBF learning algorithm
2. To execute this algorithm in Spyder environment

Apparatus:
1. Spyder environment

Procedure:
2. First of all, I opened a new file in Spyder.
3. I wrote the code for RBF in Spyder.
4. I executed the code and showed its output.

RBF Learning algorithm:

Code:

import numpy as np
Imports the Numpy library and aliases it as np. Numpy is a powerful library for numerical
operations in Python.
class RBFNN:
Defines a class named RBFNN for Radial Basis Function Neural Network.
def __init__(self, kernels,centers, beta=1,lr=0.1,epochs=80) -> None:
Defines the constructor method for the RBFNN class. Initializes the RBFNN with the
number of kernels, centers, beta (parameter for RBF activation), learning rate (lr), and
number of epochs for training.
self.kernels = kernels
self.centers = centers
self.beta = beta
self.lr = lr
self.epochs = epochs
self.W = np.random.randn(kernels,1)
self.b = np.random.randn(1,1)
Initializes attributes such as the number of kernels, centers, beta, learning rate, epochs,
weights (W), and bias (b) with random values.
# to save the errors evolution
# in case we want to check them later
self.errors = []
# to save the gradients
# calculated by the network
# for verification reasons
self.gradients = []
Initializes lists (errors and gradients) to store errors during training and gradients for
verification.
def rbf_activation(self,x,center):
return np.exp(-self.beta*np.linalg.norm(x - center)**2)
Defines a radial basis function (RBF) activation method.
def linear_activation(self,A):
return self.W.T.dot(A) + self.b
Defines a linear activation method.
def least_square_error(self,pred,y):
return (y - pred).flatten()**2
Defines a method to calculate the least square error between predictions and actual values.
def _forward_propagation(self,x)
a1 = np.array([
[self.rbf_activation(x,center)]
for center in self.centers
])
a2 = self.linear_activation(a1)
return a2, a1
Defines a method for forward propagation through the network.
def _backpropagation(self, y, pred,a1):
# Back propagation
dW = -(y - pred).flatten()*a1
db = -(y - pred).flatten()
# Updating the weights
self.W = self.W -self.lr*dW
self.b = self.b -self.lr*db
return dW, db
Defines a method for backpropagation through the network, updating weights and bias.
def fit(self,X,Y):
for _ in range(self.epochs):
for x,y in list(zip(X,Y)):
# Forward propagation
pred, a1 = self._forward_propagation(x)
error = self.least_square_error(pred[0],y[0,np.newaxis])
self.errors.append(error)
# Back propagation
dW, db = self._backpropagation(y,pred,a1)
self.gradients.append((dW,db))
Defines a method to train the RBFNN using forward and backward propagation.
def predict(self,x):
a2,a1 = self._forward_propagation(x)
return 1 if np.squeeze(a2) >= 0.5 else 0
Defines a method for making predictions using the trained RBFNN.
def main():
X = np.array([
[0,0],
[0,1],
[1,0],
[1,1]
])
Y = np.array([
[0],
[1],
[1],
[0]
])
Defines the main function and initializes input (X) and output (Y) data for the XOR gate.
rbf = RBFNN(kernels=4,
centers=np.array([
[0,0],
[0,1],
[1,0],
[1,1] ]),
beta=1,
lr= 0.1,
epochs=80)
Creates an instance of the RBFNN class with specific parameters.
rbf.fit(X,Y)
Calls the fit method to train the RBFNN.
print(f"RBFN weights : {rbf.W}")
print(f"RBFN bias : {rbf.b}")
print()
print("-- XOR Gate --")
print(f"| 1 xor 1 : {rbf.predict(X[3])} |")
print(f"| 0 xor 0 : {rbf.predict(X[0])} |")
print(f"| 1 xor 0 : {rbf.predict(X[2])} |")
print(f"| 0 xor 1 : {rbf.predict(X[1])} |")
print("_______________")
Prints the learned weights and bias of the trained RBFNN and tests its predictions for the
XOR gate.
if __name__ == "__main__":
main()
Executes the main function if the script is run as the main program
Output:

Conclusion: I have successfully executed the code on python without any error.
Experiment No. 6

Title: “Support Vector Machine Learning Algorithm”

Objective: The main aim of this lab is:


1. To understand the SVM learning algorithm
2. To execute this algorithm in Spyder environment

Apparatus:
1. Spyder environment

Procedure:
2. First of all, I opened a new file in Spyder.
3. I wrote the code for SVM in Spyder.
4. I executed the code and showed its output.

SVM Learning algorithm:


Code:

import numpy as np
Imports the Numpy library and assigns it the alias np. Numpy is commonly used for
numerical operations in Python.
import pylab as pl
Imports the pylab module from the Matplotlib library and assigns it the alias pl. Matplotlib
is a plotting library used for creating visualizations in Python.
# Make some 2D data
linsep = False
overlap = True
Defines two boolean variables, linsep and overlap, to control the generation of synthetic 2D
data. These variables are used to set conditions for creating linearly separable or non-
linearly separable data and controlling whether there is an overlap between classes.
if linsep:
# Case 1: Linearly separable
if overlap:
cov = [[2.0,1.0],[1.0,2.0]]
else:
cov = [[0.8,0.6],[0.6,0.8]]
Defines conditions for generating synthetic 2D data. If linsep is True, it selects between two
cases: linearly separable with or without class overlap. If linsep is False, it generates non-
linearly separable data.

train0 = np.random.multivariate_normal([0.,2.], cov, 100)


train1 = np.random.multivariate_normal([2.,0.], cov, 100)
train = np.concatenate((train0,train1),axis=0)
Generates 100 data points for each of the two classes (train0 and train1) using
np.random.multivariate_normal. These points are drawn from multivariate normal
distributions with means [0., 2.] and [2., 0.], respectively, and the covariance matrix cov.
Concatenates these two sets of points along axis 0 to form the training data train
test0 = np.random.multivariate_normal([0.,2.], cov, 20)
test1 = np.random.multivariate_normal([2.,0.], cov, 20)
test = np.concatenate((test0,test1),axis=0)
Similar to the training data, generates 20 data points for each of the two classes (test0 and
test1) for testing purposes. Concatenates these points along axis 0 to form the test data test.
labeltrain0 = np.ones((np.shape(train0)[0],1))
labeltrain1 = -np.ones((np.shape(train1)[0],1))
labeltrain = np.concatenate((labeltrain0,labeltrain1),axis=0)
labeltest0 = np.ones((np.shape(test0)[0],1))
labeltest1 = -np.ones((np.shape(test1)[0],1))
labeltest = np.concatenate((labeltest0,labeltest1),axis=0)
Creates labels for the training data (labeltrain) and testing data (labeltest). For the training
data, sets the labels for train0 class to 1 and for train1 class to -1. Similar labeling is done
for the testing data.
else:
# Case 2: Not linearly separable
cov = [[1.5,1.0],[1.0,1.5]]
train0a = np.random.multivariate_normal([-1.,2.], cov, 50)
train0b = np.random.multivariate_normal([1.,-1.], cov, 50)
train0 = np.concatenate((train0a,train0b),axis=0)
train1a = np.random.multivariate_normal([4.,-4.], cov, 50)
train1b = np.random.multivariate_normal([-4.,4.], cov, 50)
train1 = np.concatenate((train1a,train1b),axis=0)
train = np.concatenate((train0,train1),axis=0)
If linsep is False, indicating the desire to generate non-linearly separable data, sets the
covariance matrix cov to [[1.5, 1.0], [1.0, 1.5]]. Generates two sets of non-linearly separable
training data (train0 and train1) with 50 points each for two classes. Concatenates these
points along axis 0 to form the training data train.
test0a = np.random.multivariate_normal([-1.,2.], cov, 50)
test0b = np.random.multivariate_normal([1.,-1.], cov, 50)
test0 = np.concatenate((test0a,test0b),axis=0)
test1a = np.random.multivariate_normal([4.,-4.], cov, 50)
test1b = np.random.multivariate_normal([-4.,4.], cov, 50)
test1 = np.concatenate((test1a,test1b),axis=0)
test = np.concatenate((test0,test1),axis=0)
Similar to the training data, generates non-linearly separable testing data (test0 and test1)
with 50 points each for two classes. Concatenates these points along axis 0 to form the test
data test.
labeltrain0 = np.ones((np.shape(train0)[0],1))
labeltrain1 = -np.ones((np.shape(train1)[0],1))
labeltrain = np.concatenate((labeltrain0,labeltrain1),axis=0)
labeltest0 = np.ones((np.shape(test0)[0],1))
labeltest1 = -np.ones((np.shape(test1)[0],1))
labeltest = np.concatenate((labeltest0,labeltest1),axis=0)
Creates labels for the non-linearly separable training data (labeltrain) and testing data
(labeltest) similar to the linearly separable case.
pl.figure()
Creates a new figure for plotting using Matplotlib
pl.plot(train0[:,0], train0[:,1], "o",color="0.75")
pl.plot(train1[:,0], train1[:,1], "s",color="0.25")
Plots the generated synthetic data. train0 and train1 are two classes, and "o" and "s"
represent different markers. The colors are set using shades of gray.
import svm
Imports a module or class named svm. The specifics of this module are not provided in the
snippet.
svm = svm.svm(kernel='linear',C=0.1)
#svm = svm.svm(kernel='rbf')
#svm = svm.svm(kernel='poly',C=0.1,degree=4)
Creates an instance of the svm.svm class with different kernel options (linear, RBF, or
polynomial) and specific parameters such as C (regularization parameter) and degree (for
polynomial kernel).
print (np.shape(train), np.shape(labeltrain))
Prints the shapes of the training data (train) and its corresponding labels (labeltrain).
svm.train_svm(train, labeltrain)
Trains the SVM model using the training data (train) and labels (labeltrain) with the
train_svm method
pl.scatter(svm.X[:,0], svm.X[:,1], s=200,color= 'k')
Plots the support vectors identified by the SVM model. The svm.X attribute likely contains
the support vectors.
predict = svm.classifier(test,soft=False)
correct = np.sum(predict == labeltest)
Uses the trained SVM model to predict the labels for the test data (test) and compares the
predictions with the actual labels (labeltest). Counts the number of correct predictions.
print (correct, np.shape(predict))
print (float(correct)/np.shape(predict)[0]*100., "test accuracy")
Prints the number of correct predictions, the total number of predictions, and the test
accuracy as a percentage.
# Classify points over 2D space to fit contour
x,y = np.meshgrid(np.linspace(-6,6,50), np.linspace(-6,6,50))
xx = np.reshape(np.ravel(x),(2500,1))
yy = np.reshape(np.ravel(y),(2500,1))
points = np.concatenate((xx,yy),axis=1)
Creates a grid of points (x and y) in a 2D space using np.meshgrid and then flattens and
reshapes them into a single-dimensional array (xx and yy). Concatenates these arrays to
create a set of 2D points.
outpoints = svm.classifier(points,soft=True).reshape(np.shape(x))
Uses the trained SVM model to classify the points in the 2D space and reshapes the result
to match the shape of the grid.
pl.contour(x, y, outpoints, [0.0], colors='k', linewidths=1, origin='lower')
pl.contour(x, y, outpoints + 1, [0.0], colors='grey', linewidths=1, origin='lower')
pl.contour(x, y, outpoints - 1, [0.0], colors='grey', linewidths=1, origin='lower')
Plots contours of decision boundaries based on the SVM classifications. The contours at 0.0
represent the decision boundary, while the contours at +1 and -1 provide some margin
around the decision boundary.
pl.axis("tight")
pl.show()
Sets the axis limits to tightly fit the plotted data and displays the plot.

Conclusion: I have successfully executed above code without any error.


Experiment No. 7

Title: “Linear Discriminant Analysis”

Objective: The main aim of this lab is:


1. To understand the LDA algorithm
2. To execute this algorithm in Spyder environment

Apparatus:
1. Spyder environment

Procedure:
1. First of all, I opened a new file in Spyder.
2. I wrote the code for LDA in Spyder.
3. I executed the code and showed its output.

Introduction:

Linear Discriminant Analysis (LDA) is a supervised learning algorithm used for classification
tasks in machine learning. It is a technique used to find a linear combination of features that best
separates the classes in a dataset. LDA works by projecting the data onto a lower-dimensional
space that maximizes the separation between the classes. It does this by finding a set of linear
discriminants that maximize the ratio of between-class variance to within-class variance. In other
words, it finds the directions in the feature space that best separate the different classes of data.
Code for Linear Discriminant Analysis:

import numpy as np
Import the Numpy library with the alias np. Numpy is used for numerical operations and
handling arrays.
import matplotlib. pyplot as plt
Import the pyplot module from Matplotlib with the alias plt. This is used for creating
visualizations and plots.
from sklearn import datasets
Import the datasets module from scikit-learn. This module provides various datasets for
testing and practicing machine learning algorithms.
from sklearn.discriminant_analysis import LinearDiscriminantAnalysis
Import the LinearDiscriminantAnalysis class from scikit-learn, which is the implementation
of Linear Discriminant Analysis.
from sklearn.model_selection import train_test_split
Import the train_test_split function from scikit-learn. This function is used to split the
dataset into training and testing sets.
# Load the iris dataset
iris = datasets.load_iris()
Load the Iris dataset from scikit-learn. This dataset is commonly used for practicing
classification algorithms.
X = iris.data
Extract the features (input variables) from the dataset.
y = iris.target
Extract the target variable (labels) from the dataset.
# Split the dataset into training and testing sets
X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.2, random_state=42)
Split the dataset into training and testing sets. test_size=0.2 indicates that 20% of the data
will be used for testing, and random_state=42 ensures reproducibility.
# Create and fit the LDA model
lda = LinearDiscriminantAnalysis(n_components=2)
Create an instance of the LinearDiscriminantAnalysis class with the parameter
n_components=2. This specifies that we want to reduce the dimensionality to 2 components.
X_train_lda = lda.fit_transform(X_train, y_train)
Fit the LDA model to the training data (X_train, y_train) and transform it to the specified
number of components. The result is stored in X_train_lda.
# Plot the data before LDA
plt.figure(figsize=(12, 6))
Create a new figure with a specified size.
plt.subplot(1, 2, 1)
Create a subplot (1 row, 2 columns), and set the current subplot to the first one.
plt.scatter(X_train[:, 0], X_train[:, 1], c=y_train, cmap='viridis', edgecolor='k', s=60)
Scatter plot of the original training data. Each point is colored based on its class (y_train),
and different classes have different colors.
plt.title('Original Data')
Set the title of the first subplot.
plt.xlabel('Feature 1')
plt.ylabel('Feature 2')
Set the labels for the x and y axes of the first subplot.
# Plot the data after LDA
plt.subplot(1, 2, 2)
Set the current subplot to the second one.
plt.scatter(X_train_lda[:, 0], X_train_lda[:, 1], c=y_train, cmap='viridis', edgecolor='k', s=60)
Scatter plot of the data after applying LDA. Each point is colored based on its class (y_train).
plt.title('Data after LDA')
Set the title of the second subplot
plt.xlabel('LDA Component 1')
plt.ylabel('LDA Component 2')
Set the labels for the x and y axes of the second subplot.
plt.show()
Display the plots.
Results:

Conclusion: I have successfully executed above code in spyder without any error.
Experiment No. 8

Title: “Principal Component Analysis”

Objective: The main aim of this lab is:


1. To understand the PCA algorithm
2. To execute this algorithm in Spyder environment

Apparatus:
1. Spyder environment

Procedure:

1. First of all, I opened a new file in Spyder.


2. I wrote the code for LDA in Spyder.
3. I executed the code and showed its output.
Introduction:
Principal Component Analysis (PCA) is a technique for dimensionality reduction that identifies
a set of orthogonal axes, called principal components, that capture the maximum variance in the
data. The principal components are linear combinations of the original variables in the dataset
and are ordered in decreasing order of importance. The total variance captured by all the
principal components is equal to the total variance in the original dataset.
Code for Principal Component Analysis:
import numpy as np
import matplotlib.pyplot as plt
Import the necessary libraries, numpy for numerical operations and Matplotlib for plotting.
# Generate some example data
np.random.seed(42)
data = np.random.multivariate_normal(mean=[0, 0], cov=[[1, 0.8], [0.8, 1]], size=100)
Set a random seed for reproducibility and generate a dataset with a multivariate normal
distribution. The dataset has a mean of [0, 0] and a covariance matrix [[1, 0.8], [0.8, 1]]. The
size of the dataset is 100.
# Compute the covariance matrix
covariance_matrix = np.cov(data, rowvar=False)
Compute the covariance matrix of the dataset using np.cov(). rowvar=False indicates that
each column represents a variable.
# Compute eigenvalues and eigenvectors
eigenvalues, eigenvectors = np.linalg.eigh(covariance_matrix)
Use np.linalg.eigh() to compute the eigenvalues and eigenvectors of the covariance matrix.
This function assumes that the input matrix is symmetric.
# Sort eigenvalues and eigenvectors in descending order
sorted_indices = np.argsort(eigenvalues)[::-1]
eigenvalues = eigenvalues[sorted_indices]
eigenvectors = eigenvectors[:, sorted_indices]
Sort the eigenvalues and corresponding eigenvectors in descending order. The np.argsort()
function returns the indices that would sort the array, and [::-1] reverses the order.
# Print eigenvalues, eigenvectors, and covariance matrix
print("Eigenvalues:")
print(eigenvalues)
print("\nEigenvectors:")
print(eigenvectors)
print("\nCovariance Matrix:")
print(covariance_matrix)
Print the computed eigenvalues, eigenvectors, and the original covariance matrix.
# Compute the principal components
principal_components = np.dot(data, eigenvectors)
Compute the principal components by multiplying the original data by the eigenvectors.
# Plot the original data and principal components
plt.scatter(data[:, 0], data[:, 1], label='Original Data')
plt.quiver(0, 0, eigenvectors[0, 0], eigenvectors[1, 0], angles='xy', scale_units='xy', scale=1,
color='r', label='Principal Component 1')
plt.quiver(0, 0, eigenvectors[0, 1], eigenvectors[1, 1], angles='xy', scale_units='xy', scale=1,
color='b', label='Principal Component 2')
plt.xlabel('X-axis')
plt.ylabel('Y-axis')
plt.legend()
plt.title('Original Data and Principal Components')
plt.show()
Create a scatter plot of the original data points. Then, use plt.quiver() to plot arrows
representing the principal components. Finally, add labels, a legend, and a title to the plot
and display it using plt.show(). The red arrow corresponds to the first principal component,
and the blue arrow corresponds to the second principal component.

Results:

Conclusion: I have successfully executed the above code in spyder without any error
Experiment No. 9

Title: “Independent Component Analysis”

Objective: The main aim of this lab is:


1. To understand the ICA algorithm
2. To execute this algorithm in Spyder environment

Apparatus:
1. Spyder environment

Procedure:

1. First of all, I opened a new file in Spyder.


2. I wrote the code for ICA in Spyder.
3. I executed the code and showed its output.
Introduction:
Independent Component Analysis (ICA) is a statistical and computational technique used in
machine learning to separate a multivariate signal into its independent non-Gaussian components.
The goal of ICA is to find a linear transformation of the data such that the transformed data is as
close to being statistically independent as possible.
Code for ICA:

import numpy as np
import matplotlib.pyplot as plt
Import the required libraries, NumPy for numerical operations and matplotlib for plotting.
def center_data(X):
mean_X = np.mean(X, axis=1, keepdims=True)
centered_X = X - mean_X
return centered_X, mean_X
Define a function center_data that takes a matrix X as input, calculates the mean along each
row (axis=1), and returns the centered matrix (centered_X) and the mean values (mean_X).
def whiten_data(X):
cov_matrix = np.cov(X)
_, S, V = np.linalg.svd(cov_matrix)
whitening_matrix = np.dot(np.dot(V.T, np.diag(1 / np.sqrt(S))), V)
whitened_X = np.dot(whitening_matrix, X)
return whitened_X, whitening_matrix
Define a function whiten_data that takes a matrix X as input, calculates the covariance
matrix, performs singular value decomposition (SVD), and returns the whitened matrix
(whitened_X) and the whitening matrix (whitening_matrix)
def g(x):
return np.tanh(x)
Define a non-linear function g (activation function) which is the hyperbolic tangent (tanh)
function.
def g_prime(x):
return 1 - np.square(np.tanh(x))
Define the derivative of the non-linear function g (used in the FastICA algorithm).
def decorrelate(W):
return np.linalg.qr(W)[0]
Define a function decorrelate that takes a matrix W as input and returns its orthonormalized
version using QR decomposition.
def fast_ica(X, max_iterations=500, tolerance=1e-4):
centered_X, mean_X = center_data(X)
whitened_X, whitening_matrix = whiten_data(centered_X)
num_components = X.shape[0]
W = np.random.rand(num_components, num_components)
Define the main function fast_ica that takes the data matrix X and some optional parameters
(max_iterations and tolerance). It starts by centering and whitening the data.
for iteration in range(max_iterations):
# Update the weight matrix using the FastICA algorithm
WX = np.dot(W, whitened_X)
g_WX = g(WX)
g_prime_WX = g_prime(WX)
In a loop, perform the main steps of the FastICA algorithm: multiply the weight matrix W
with the whitened data, compute the non-linear function g applied to the product, and
compute the derivative of the non-linear function.
# Update step
W_new = (np.dot(g_WX, whitened_X.T) / X.shape[1]) - np.dot(g_prime_WX, WX.T) /
X.shape[1]
# Decorrelate the weight matrix
W_new = decorrelate(W_new)
# Check for convergence
if np.max(np.abs(np.abs(np.diag(np.dot(W_new, W.T))) - 1)) < tolerance:
break
W = W_new
Update the weight matrix using the FastICA update rule, decorrelate the weight matrix, and
check for convergence.
sources = np.dot(W, whitened_X)
return sources, W
After convergence or reaching the maximum number of iterations, compute the estimated
sources using the final weight matrix.
num_samples = 1000
t = np.linspace(0, 1, num_samples)
s1 = np.sin(2 * np.pi * 5 * t) # Sinusoid with frequency 5 Hz
s2 = 0.5 * np.sin(2 * np.pi * 20 * t) # Sinusoid with frequency 20 Hz
S = np.vstack([s1, s2])
Generate two sinusoids with different frequencies (5 Hz and 20 Hz) and stack them vertically
to create the original sources matrix S.
# Mixing matrix
A = np.array([[1, 2], [2, 1]])
X = np.dot(A, S)
Mix the original sources using a mixing matrix A to create the mixed signals matrix X
# FastICA
unmixed_sources, estimated_W = fast_ica(X)
Apply the FastICA algorithm to the mixed signals to estimate the original sources and the
separating matrix.
# Plot the original sources and the estimated sources
plt.figure(figsize=(10, 4))
plt.subplot(2, 2, 1)
plt.plot(unmixed_sources[0], label='Estimated Source 1')
plt.title('Estimated Source 1')
plt.legend()
plt.subplot(2, 2, 2)
plt.plot(unmixed_sources[1], label='Estimated Source 2')
plt.title('Estimated Source 2')
plt.legend()
plt.subplot(2, 2, 3)
plt.plot(X[0], label='Mixed Signal 1')
plt.title('Mixed Signal 1')
plt.legend()
plt.subplot(2, 2, 4)
plt.plot(X[1], label='Mixed Signal 2')
plt.title('Mixed Signal 2')
plt.legend()
plt.tight_layout()
plt.show()
Plot the original sources, the mixed signals, and the estimated sources for visualization.
Results:

Conclusion: I have successfully executed the above code in spyder without any error.
Experiment No. 10

Title: “Q-Learning Algorithm”

Objective: The main aim of this lab is:


1. To understand the Q learning algorithm
2. To execute this algorithm in Spyder environment

Apparatus:
1. Spyder environment

Procedure:

1. First of all, I opened a new file in Spyder.


2. I wrote the code for Q-Learning in Spyder.
3. I executed the code and showed its output.
Introduction:

Reinforcement learning is a branch of Machine Learning that trains a model to come to an optimum
solution for a problem by taking decisions by itself. Q-Learning is a Reinforcement learning policy
that will find the next best action, given a current state. It chooses this action at random and aims
to maximize the reward.
Code:
import numpy as np
This line imports the NumPy library, which is commonly used for numerical operations in
Python.
# Step 1: Initialize Q-table
num_states = 5
num_actions = 3
Q = np.zeros((num_states, num_actions))
These lines set up the Q-table, which is a matrix where rows represent states, columns
represent actions, and each entry represents the Q-value for a state-action pair. In this
example, we have 5 states and 3 actions, and the Q-table is initialized with zeros.
# Step 2: Set hyperparameters
alpha = 0.1 # learning rate
gamma = 0.9 # discount factor
epsilon = 0.1 # exploration-exploitation trade-off
These lines set up hyperparameters for the Q-learning algorithm. alpha is the learning rate,
gamma is the discount factor for future rewards, and epsilon is the exploration-exploitation
trade-off parameter.
# Step 3: Define the reward matrix
# Example: a 5x3 matrix where each entry represents the reward for a specific state-action pair
rewards = np.array([
[-1, 0, -1],
[-1, -1, 0],
[0, -1, 1],
[-1, 1, -1],
[0, 0, 0]
])
This line defines the reward matrix, where each entry represents the reward for a specific
state-action pair. The matrix is a simple example with arbitrary values. In a real-world
scenario, you would need to define the rewards based on the task you are trying to solve.
# Step 4: Implement Q-learning algorithm
num_episodes = 1000
These lines set the number of episodes, which is the number of times the agent interacts with
the environment to learn.
for episode in range(num_episodes):
state = np.random.randint(0, num_states) # Initial state
done = False
This loop iterates over each episode. It randomly initializes the starting state for each episode and
sets done to False to indicate the episode is not finished yet
while not done:
# Exploration-exploitation trade-off
if np.random.uniform(0, 1) < epsilon:
action = np.random.randint(0, num_actions) # Explore
else:
action = np.argmax(Q[state, :]) # Exploit
This loop iterates within each episode until the episode is finished. It implements the
exploration-exploitation trade-off. With probability epsilon, it chooses a random action
(Explore), and with probability 1 - epsilon, it chooses the action with the highest Q-value for
the current state (Exploit).
# Take the chosen action and observe the new state and reward
new_state = np.random.choice(range(num_states), p=[0.2, 0.3, 0.1, 0.2, 0.2])
reward = rewards[state, action]
These lines simulate taking the chosen action in the environment and obtaining a new state
and reward. new_state is randomly chosen based on a predefined transition model (in this
case, a probability distribution). reward is obtained from the predefined reward matrix.
# Update Q-value using the Q-learning update rule
Q [state, action] = Q[state, action] + alpha * (reward + gamma * np.max(Q[new_state, :]) -
Q[state, action])
state = new_state
This line updates the Q-value for the chosen state-action pair using the Q-learning update
rule. It incorporates the reward obtained, the discounted maximum Q-value for the new
state, and the learning rate. The current state is then updated to the new state for the next
iteration.
if state == num_states - 1: # Terminal state
done = True
This condition checks whether the current state is the terminal state. If so, it sets done to
True, indicating that the episode is finished.
# Print the learned Q-values
print("Learned Q-values:")
print(Q)
Finally, this code prints the learned Q-values after all episodes. The Q-values represent the
learned expected cumulative rewards for each state-action pair.
Results:

Conclusion: I have successfully executed the above code without any error.
Experiment No. 11

Title: “SARSA Algorithm”

Objective: The main aim of this lab is:


1. To understand the SARSA algorithm
2. To execute this algorithm in Spyder environment

Apparatus:
1. Spyder environment

Procedure:
1. First of all, I opened a new file in Spyder.
2. I wrote the code for SARSA in Spyder.
3. I executed the code and showed its output.

Introduction:
State Action Reward State Action (SARSA) is one of the algorithms of reinforcement learning
which is a modified version of the Q-learning algorithm. The major point that differentiates the
SARSA algorithm from the Q-learning algorithm is that it does not maximize the reward for the
next stage of action to be performed and updates the Q-value for the corresponding states.
Code for SARSA algorithm:
import numpy as np
This line imports the NumPy library and aliases it as np for convenience.
def SARSA():
Defines a function named SARSA.
R=np.array([[-5,0,-np.inf,-np.inf,-np.inf,-np.inf],[0,-5,0,0,-np.inf,-np.inf],[-np.inf,0,-5,0,-
np.inf,100],[-np.inf,0,0,-5,0,-np.inf],[-np.inf,-np.inf,-np.inf,0,-5,100],[-np.inf,-np.inf,0,-np.inf,-
np.inf,0]])
t = np.array([[1,1,0,0,0,0],[1,1,1,1,0,0],[0,1,1,1,0,1],[0,1,1,1,1,0],[0,0,0,1,1,1],[0,0,1,0,1,1]])
Creates two NumPy arrays, R and t. R represents the rewards for each state-action pair, and
t represents the transitions between states.
nStates = np.shape(R)[0]
nActions = np.shape(R)[1]
Determines the number of states and actions based on the shape of the R array.
Q = np.random.rand(nStates,nActions)*0.1-0.05
Initializes the Q-values with random values between -0.05 and 0.05.
mu = 0.7
gamma = 0.4
epsilon = 0.1
nits = 0
Sets some parameters for the SARSA algorithm, including the learning rate (mu), discount
factor (gamma), exploration rate (epsilon), and the number of iterations (nits).
while nits < 1000:
Starts a loop that will run for a maximum of 1000 iterations.
# Pick initial state
s = np.random.randint(nStates)
Randomly selects an initial state s.
# epsilon-greedy
if (np.random.rand()<epsilon):
indices = np.where(t[s,:]!=0)
pick = np.random.randint(np.shape(indices)[1])
a = indices[0][pick]
else:
a = np.argmax(Q[s,:])
Uses epsilon-greedy strategy to choose an action (a) based on the Q-values.
# Stop when the accepting state is reached
while s!=5:
Continues another loop until the accepting state (state 5) is reached.
r = R[s,a]
# For this example, new state is the chosen action
sprime = a
Sets the reward (r) and the new state (sprime) based on the chosen action.
# epsilon-greedy
if (np.random.rand()<epsilon):
indices = np.where(t[sprime,:]!=0)
pick = np.random.randint(np.shape(indices)[1])
aprime = indices[0][pick]
#print s,a
else:
aprime = np.argmax(Q[sprime,:])
Chooses the next action (aprime) using epsilon-greedy strategy for the next state.
#print "here", Q[sprime,aprime], Q[s,a], s, a
Q[s,a] += mu * (r + gamma*Q[sprime,aprime] - Q[s,a])
Updates the Q-value based on the SARSA update rule.
s = sprime
a = aprime
Updates the current state and action for the next iteration of the loop.
nits = nits+1
Increments the iteration counter
print (Q)
Prints the final Q-values after the SARSA algorithm has run.
SARSA()
Calls the SARSA function to execute the SARSA algorithm.
Results:

Conclusion: I have successfully executed the above code without any error.
Experiment No. 12

Title: “K-means Algorithm”

Objective: The main aim of this lab is:


1. To understand the K-means algorithm
2. To execute this algorithm in Spyder environment

Apparatus:
1. Spyder environment

Procedure:
1. First of all, I opened a new file in Spyder.
2. I wrote the code for K-means in Spyder.
3. I executed the code and showed its output.

Introduction: Unsupervised Machine Learning is the process of teaching a computer to use


unlabeled, unclassified data and enabling the algorithm to operate on that data without supervision.
K-Means Clustering is an Unsupervised Machine Learning algorithm, which groups the unlabeled
dataset into different clusters.
Code for K-means Algorithm:
import numpy as np
import matplotlib. pyplot as plt
Import the necessary libraries. numpy is used for numerical operations, and matplotlib is
used for data visualization.
def initialize_centroids(data, k):
# Randomly initialize k centroids
indices = np.random.choice(len(data), k, replace=False)
centroids = data[indices]
return centroids
Define a function initialize_centroids that takes the dataset (data) and the number of clusters
(k) as input. This function randomly selects k data points as initial centroids.
def assign_to_clusters(data, centroids):
# Assign each data point to the nearest centroid
distances = np.linalg.norm(data[:, np.newaxis] - centroids, axis=2)
clusters = np.argmin(distances, axis=1)
return clusters
Define a function assign_to_clusters that assigns each data point to the nearest centroid. It
calculates the Euclidean distances between each data point and all centroids, then assigns
the point to the cluster corresponding to the nearest centroid.
def update_centroids(data, clusters, k):
# Update centroids based on the mean of data points in each cluster
centroids = np.array([data[clusters == i].mean(axis=0) for i in range(k)])
return centroids
Define a function update_centroids that updates the centroids based on the mean of data
points in each cluster. It calculates the mean of all data points assigned to each cluster and
sets the centroid to that mean.
def k_means(data, k, max_iterations=100):
# Step 1: Initialize centroids
centroids = initialize_centroids(data, k)
for _ in range(max_iterations):
# Step 2: Assign each data point to the nearest centroid
clusters = assign_to_clusters(data, centroids)
# Step 3: Update centroids based on the mean of data points in each cluster
new_centroids = update_centroids(data, clusters, k)
# Check for convergence
if np.all(centroids == new_centroids):
break
centroids = new_centroids
return centroids, clusters
Define the main k_means function that orchestrates the entire algorithm. It initializes
centroids, iteratively assigns data points to clusters and updates centroids until convergence
or reaching the maximum number of iterations.
# Generate random data for demonstration
np.random.seed(42)
data = np.concatenate([np.random.normal(loc=0, scale=1, size=(100, 2)),
np.random.normal(loc=5, scale=1, size=(100, 2)),
np.random.normal(loc=10, scale=1, size=(100, 2))])
k = 3 # Number of clusters
centroids, clusters = k_means(data, k)
# Plot the results
plt.scatter(data[:, 0], data[:, 1], c=clusters, cmap='viridis', alpha=0.5)
plt.scatter(centroids[:, 0], centroids[:, 1], c='red', marker='X', s=200, label='Centroids')
plt.title('K-means Clustering')
plt.legend()
plt.show()
Generate random data with three clusters. Apply the K-means algorithm to the data and
plot the results. The data points are colored based on their assigned clusters, and the
centroids are marked with red 'X' markers.
Results:

Conclusion: I have successfully executed the above code without any error.
Experiment No. 13

Title: “K-means Neural Algorithm”

Objective: The main aim of this lab is:


1. To understand the K-means neural algorithm
2. To execute this algorithm in Spyder environment

Apparatus:
1. Spyder environment

Procedure:
1. First of all, I opened a new file in Spyder.
2. I wrote the code for K-means neural in Spyder.
3. I executed the code and showed its output.
Code for k-means neural algorithm
import numpy as np
This line is for performing numerical operations
class kmeans:
"""The k-Means Algorithm implemented as a neural network"""
def __init__(self,k,data,nEpochs=1000,eta=0.25):
self.nData = np.shape(data)[0]
self.nDim = np.shape(data)[1]
self.k = k
self.nEpochs = nEpochs
self.weights = np.random.rand(self.nDim,self.k)
self.eta = eta
This defines a class kmeans that represents the k-Means algorithm as a neural network. The
__init__ method initializes the class with parameters such as the number of clusters k, input
data, number of epochs nEpochs, and learning rate eta. It also initializes weights randomly.
def kmeanstrain(self,data):
# Preprocess data (won't work if (0,0,...0) is in data)
normalisers = np.sqrt(np.sum(data**2,axis=1))*np.ones((1,np.shape(data)[0]))
data = np.transpose(np.transpose(data)/normalisers)

for i in range(self.nEpochs):
for j in range(self.nData):
activation = np.sum(self.weights*np.transpose(data[j:j+1,:]),axis=0)
winner = np.argmax(activation)
self.weights[:,winner] += self.eta * data[j,:] - self.weights[:,winner]
The kmeanstrain method is responsible for training the k-Means model. It preprocesses the
data by normalizing it and then iterates over the data for a certain number of epochs,
updating the weights based on the winner neuron.
def kmeansfwd(self,data):
best = np.zeros(np.shape(data)[0])
for i in range(np.shape(data)[0]):
activation = np.sum(self.weights*np.transpose(data[i:i+1,:]),axis=0)
best[i] = np.argmax(activation)
return best
The kmeansfwd method is used for forward-pass inference. It assigns each data point to the
cluster with the highest activation.
import matplotlib.pyplot as plt
# Generate random data with two clusters
np.random.seed(42)
data1 = np.random.normal(loc=0, scale=1, size=(100, 2))
data2 = np.random.normal(loc=5, scale=1, size=(100, 2))
data = np.concatenate((data1, data2))
# Create an instance of the kmeans class
kmeans_model = kmeans(k=2, data=data, nEpochs=1000, eta=0.25)
# Train the model
kmeans_model.kmeanstrain(data)
# Classify the data points based on the trained model
predictions = kmeans_model.kmeansfwd(data)
# Plot the original data and color-coded clusters
plt.scatter(data[:, 0], data[:, 1], c=predictions, cmap='viridis')
plt.scatter(kmeans_model.weights[0, :], kmeans_model.weights[1, :], marker='X', s=200,
color='red')
plt.title('K-Means Neural Clustering')
plt.xlabel('Feature 1')
plt.ylabel('Feature 2')
plt.show()
Finally, this section generates random data with two clusters, creates an instance of the
kmeans class, trains the model, classifies the data points, and plots the results. The data
points are color-coded based on their assigned clusters, and the final centroids are marked
with red 'X' markers.

Conclusion: I have successfully executed above code without any error.


Experiment No. 14

Title: “Self Organizing Feature Map Algorithm”

Objective: The main aim of this lab is:


1. To understand the SOM algorithm
2. To execute this algorithm in Spyder environment

Apparatus:
1. Spyder environment

Procedure:
1. First of all, I opened a new file in Spyder.
2. I wrote the code for SOM in Spyder.
3. I executed the code and showed its output.

Introduction:
A self-organizing map (SOM) is a special type of neural network we use for reducing the
dimensionality of high-dimensional data. SOMs belong to unsupervised algorithms such as
principal component analysis (PCA) and k-means clustering and are also called Kohonen maps
Code for SOM:
import numpy as np
import matplotlib.pyplot as plt
These lines import the necessary libraries: numpy for numerical operations and arrays, and
matplotlib for data visualization.
class SelfOrganizingMap:
def __init__(self, input_size, output_size, learning_rate=0.1, sigma=1.0):
self.input_size = input_size
self.output_size = output_size
self.learning_rate = learning_rate
self.sigma = sigma
# Initialize weights
self.weights = np.random.rand(output_size, input_size)
This section defines a class SelfOrganizingMap with a constructor __init__ to initialize the
SOM. It takes parameters like input_size (size of input vectors), output_size (number of
nodes in the output layer), learning_rate (learning rate for weight updates), and sigma
(spread parameter for neighborhood function). It also initializes the weight matrix
randomly.
def find_best_matching_unit(self, input_vector):
# Compute distances between input vector and all weights
distances = np.linalg.norm(self.weights - input_vector, axis=1)
# Find the index of the best matching unit (BMU)
bmu_index = np.argmin(distances)
return bmu_index
find_best_matching_unit method calculates the Euclidean distances between the input
vector and all weights, then identifies the index of the best matching unit (BMU), i.e., the
weight vector closest to the input vector.
def update_weights(self, input_vector, bmu_index):
# Update weights based on the input vector and the BMU
for i in range(self.output_size):
distance_to_bmu = np.abs(bmu_index - i)
influence = np.exp(-(distance_to_bmu**2) / (2 * self.sigma**2))
self.weights[i] += self.learning_rate * influence * (input_vector - self.weights[i])
update_weights method adjusts the weights based on the input vector and the BMU. It
iterates over all nodes and updates their weights based on their distance to the BMU and the
learning rate.
def train(self, data, num_epochs):
for epoch in range(num_epochs):
for input_vector in data:
bmu_index = self.find_best_matching_unit(input_vector)
self.update_weights(input_vector, bmu_index)
train method iterates through the dataset for a specified number of epochs, finding the BMU
for each input vector and updating the weights accordingly.
def visualize(self, data):
plt.plot(data[:, 0], np.zeros_like(data[:, 0]), 'bo', label='Data')
plt.plot(self.weights[:, 0], np.zeros_like(self.weights[:, 0]), 'ro', label='SOM weights')
plt.legend()
plt.show()
visualize method plots the input data points (in blue) and the SOM weights (in red) on a 1D
graph.
# Assuming your data is a 1D array, for example, a sine wave
data = np.sin(np.linspace(0, 4 * np.pi, 100)).reshape(-1, 1)
# Initialize and train the SOM
input_size = 1
output_size = 10
som = SelfOrganizingMap(input_size, output_size)
som.train(data, num_epochs=1000)
som. visualize(data)
This section demonstrates how to use the SOM. It generates a 1D sine wave as an example
dataset, initializes and trains the SOM, and then visualizes the input data and the learned
weights.
Results:

You might also like