ML Lab Manual
ML Lab Manual
Session (2020-2024)
DEPARTMENT OF E LECTRICAL ENGINEERING
Semester (Seventh)
=================================================
LAB REPORTS
==================================================
Experiment No. 1
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. 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.
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.
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.
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
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.
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
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
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
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
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.
This line prints the string "OR logic function" to the standard output.
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
class pcn:
""" A basic Perceptron (the same pcn.py except with the weights printed
Define the constructor for the pcn class, taking inputs and targets as arguments.
else:
self. nIn = 1
self.nOut = np.shape(targets)[1]
else:
self. nOut = 1
# Initialize network
# Training
change = range(self.nData)
for n in range(nIterations):
self.activations = self.pcnfwd(inputs)
print('Iteration:', n)
print(self.weights)
activations = self.pcnfwd(inputs)
print(activations)
# return self.weights
# Compute activations
"""Confusion matrix"""
nClasses = np.shape(targets)[1]
if nClasses == 1:
nClasses = 2
else:
# 1-of-N encoding
outputs = np.argmax(outputs, 1)
targets = np.argmax(targets, 1)
cm = np.zeros((nClasses, nClasses))
for i in range(nClasses):
for j in range(nClasses):
print(cm)
print(np.trace(cm) / np.sum(cm)
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.
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
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
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.
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
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.
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.
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
Apparatus:
1. Spyder environment
Procedure:
Results:
Conclusion: I have successfully executed the above code in spyder without any error
Experiment No. 9
Apparatus:
1. Spyder environment
Procedure:
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
Apparatus:
1. Spyder environment
Procedure:
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
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
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.
Conclusion: I have successfully executed the above code without any error.
Experiment No. 13
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.
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: