Skip to main content

(AI Blog#5) : Programming a Neural Network !!!

After discussing about the fundamentals of Neural Networks and Deep Learning, we have arrived to an exciting stage where we can learn how we program a Neural Network. 

I have created some simple programs to get some basic idea on how to program a Neural Network and I have used a Python library called PyTorch to program it.


Program 1 : Calculate total numbers of parameters in a neural network

Points to remember :

  • We need to import nn submodule from main module torch
  • We need to inherit the Module class available in torch.nn submodule
  • We should use self otherwise method doesn't get class objects data
  • Do not confuse about forward(), we don't call it directly, it will be called via constructor in super class. Hence using self.
  • p.numel() return the elements in the Model. Please see my explanation in the downloaded code
  • Need basics of Oops concepts in Python

# importing modules torch, nn(neural network): nn is a sub module in main module torch
import torch
import torch.nn as nn

class CalculateParams(nn.Module):
def __init__(self): # Constructor used to define layers and parameters
super().__init__() # Calls parent nn.Module constructor, it will register
our model so PyTorch can track prameters, load weights etc.
self.fc1 = nn.Linear(3, 5) # Fully connected layer1
self.fc2 = nn.Linear(5, 2) # Fully connected layer2

# forward() defines how a input flows through a network
# we never call it directly, it will be automatically called when we do
'output = Model(input)'
def forward(self, x):
x = self.fc1(x)
x = self.fc2(x)

return x

model = CalculateParams()

print()
# p.numel() returns number of elements in that tensor
total_params = sum(p.numel() for p in model.parameters())
print("Total parameters:", total_params)

for name, param in model.named_parameters():
print(name, param.shape, param.numel())

Output :
Total parameters: 32 fc1.weight torch.Size([5, 3]) 15 fc1.bias torch.Size([5]) 5 fc2.weight torch.Size([2, 5]) 10 fc2.bias torch.Size([2]) 2

GitHub location : https://github.com/amathe1/GenAI-AgenticAI-Hub/blob/main/Calulate_Params_in_Neural_Network.ipynb

Also, please find more explanation in the program once you download. Finally, it printed total number of parameters in the entire Neural Network. We could also see weight and bias values of our ML model.



Program 2 : House price prediction based on house size and no. of rooms

This is a full length NN programming with entire flow.

Points to remember :

  • In real time, we get the data either from files, cloud etc. and we need to segregate it properly
    • this is whole different activity!
    • there are ML teams dedicated only to do this activity, imagine the level of complexity and depth in segregating data
    • we need to remove outliers etc. before injecting this data to ML models
    • for ease of understand, we considered simple data X, Y(tensors)
    • X contains data like house size in sqft & no. of bedrooms, it have 5 records
    • Y represents actual price, we need to come close to these values using our ML model
  • Please ignore logic like model knows what is size and what is price, we need to understand the concept of co-relation for it, for now I recommend you to concentrate on the programming part and understand the logic behind a NN


import torch
import torch.nn as nn
import torch.optim as optim
# optim provides optimizers that update model
# weights so your neural network learns from data.

# Creating data sets
X = torch.tensor([
[800,2],
[1000,3],
[1200,3],
[1500,4],
[1800,4]
], dtype=torch.float32)

y = torch.tensor([[200],[260],[300],[360],[420]], dtype=torch.float32)


# Normalizing inputs
X = X / X.max(dim=0).values
y = y / y.max()


# Define model
model = nn.Sequential(
nn.Linear(2,8),
nn.ReLU(),
nn.Linear(8,1)
)


# Loss & Optimizer
criterion = nn.MSELoss()
optimizer = optim.Adam(model.parameters(), lr=0.01)


# Traning Loop
for epoch in range(500):
pred = model(X)
loss = criterion(pred,y)

optimizer.zero_grad()
loss.backward()
optimizer.step()

if epoch % 50 == 0:
print(f"Epoch {epoch}, Loss {loss.item():.4f}")



# Test Prediction
test = torch.tensor([[1600,4]], dtype=torch.float32)
test = test / X.max(dim=0).values

prob = model(test)
print("Pass probability:", prob.item())
print("Prediction:", 1 if prob>0.5 else 0)

print("Predicted price, Y :", model(test)*420)


Output :
Epoch 0, Loss 0.3705 Epoch 50, Loss 0.0028 Epoch 100, Loss 0.0011 Epoch 150, Loss 0.0007 Epoch 200, Loss 0.0006 Epoch 250, Loss 0.0005 Epoch 300, Loss 0.0005 Epoch 350, Loss 0.0004 Epoch 400, Loss 0.0004 Epoch 450, Loss 0.0003 Pass probability: 943.6936645507812 Prediction: 1 Predicted price, Y : tensor([[396351.3438]], grad_fn=<MulBackward0>)


Normalising input data for your reference (it is sample data, not from above programs input data X, Y)

Please download below program for more clarity on explanation. Observe that for 500 epochs, model started learning and came up with lower loss.


GitHub location : https://github.com/amathe1/GenAI-AgenticAI-Hub/blob/main/House_Price_Prediction.ipynb


Conclusion : 

I am coming up with more programs on building a ML model for different problem statements. Incase if you are interested, then please watch out this GitHub space : https://github.com/amathe1/GenAI-AgenticAI-Hub/tree/main


Thank you for reading this blog !

Arun Mathe

Comments

Popular posts from this blog

AWS : Working with Lambda, Glue, S3/Redshift

This is one of the important concept where we will see how an end-to-end pipeline will work in AWS. We are going to see how to continuously monitor a common source like S3/Redshift from Lambda(using Boto3 code) and initiate a trigger to start some Glue job(spark code), and perform some action.  Let's assume that, AWS Lambda should initiate a trigger to another AWS service Glue as soon as some file got uploaded in AWS S3 bucket, Lambda should pass this file information as well to Glue, so that Glue job will perform some transformation and upload that transformed data into AWS RDS(MySQL). Understanding above flow chart : Let's assume one of your client is uploading some files(say .csv/.json) in some AWS storage location, for example S3 As soon as this file got uploaded in S3, we need to initiate a TRIGGER in AWS Lambda using Boto3 code Once this trigger is initiated, another AWS service called GLUE(ETL Tool)  will start a Pyspark job to receive this file from Lambda, perform so...

Spark Core : Understanding RDD & Partitions in Spark

Let us see how to create an RDD in Spark.   RDD (Resilient Distributed Dataset): We can create RDD in 2 ways. From Collections For small amount of data We can't use it for large amount of data From Datasets  For huge amount of data Text, CSV, JSON, PDF, image etc. When data is large we should go with Dataset approach     How to create an RDD ? Using collections val list = List(1, 2, 3, 4, 5, 6) val rdd = sc.parallelize(list) SC is Spark Context parallelize() method will convert input(collection in this case) into RDD Type of RDD will be based on the values assigned to collection, if we assign integers and RDD will be of type int Let's see below Scala code : # Created an RDD by providing a Collection(List) as input scala> val rdd = sc.parallelize(List(1, 2, 3, 4, 5)) rdd: org.apache.spark.rdd.RDD[Int] = ParallelCollectionRDD[0] at parallelize at <console>:23 # Printing RDD using collect() method scala> rdd.collect() res0: Array[Int] = Array(1, 2, 3, 4...

Spark Core : Introduction & understanding Spark Context

Apache Spark is a free, open-source tool for processing large amounts of data in parallel across multiple computers. It is used for big data work loads like machine learning, graph processing and big data analytics. Spark is built on top of Hadoop, it is aware how Hadoop works. Programming languages for Spark : Scala Python Java R SQL Spark support 2 operations : Transformations Actions RDD (Resilient Distributed Dataset) : Entire Spark is built on the base concept called RDD. Below 2  operations are supported by RDD. Transformations Actions Features of Spark : Distributed, Partitioned, Replicated Note that if data is mutable then it will be hard to distribute, partition and replicate Hence Spark required Immutability feature Immutability We can't change the data By design, Spark is purely designed for Analytical operations(OLAP) It do support transactional operations using some 3rd party tools Cacheable  To reuse data we cache it If information is static, no need to recomput...