Skip to content
geeksforgeeks
  • Courses
    • DSA to Development
    • Get IBM Certification
    • Newly Launched!
      • Master Django Framework
      • Become AWS Certified
    • For Working Professionals
      • Interview 101: DSA & System Design
      • Data Science Training Program
      • JAVA Backend Development (Live)
      • DevOps Engineering (LIVE)
      • Data Structures & Algorithms in Python
    • For Students
      • Placement Preparation Course
      • Data Science (Live)
      • Data Structure & Algorithm-Self Paced (C++/JAVA)
      • Master Competitive Programming (Live)
      • Full Stack Development with React & Node JS (Live)
    • Full Stack Development
    • Data Science Program
    • All Courses
  • Tutorials
    • Data Structures & Algorithms
    • ML & Data Science
    • Interview Corner
    • Programming Languages
    • Web Development
    • CS Subjects
    • DevOps And Linux
    • School Learning
  • Practice
    • Build your AI Agent
    • GfG 160
    • Problem of the Day
    • Practice Coding Problems
    • GfG SDE Sheet
  • Contests
    • Accenture Hackathon (Ending Soon!)
    • GfG Weekly [Rated Contest]
    • Job-A-Thon Hiring Challenge
    • All Contests and Events
  • Data Science
  • Data Science Projects
  • Data Analysis
  • Data Visualization
  • Machine Learning
  • ML Projects
  • Deep Learning
  • NLP
  • Computer Vision
  • Artificial Intelligence
Open In App
Next Article:
How to Implement Various Optimization Algorithms in Pytorch?
Next article icon

How to implement Genetic Algorithm using PyTorch

Last Updated : 01 Apr, 2024
Comments
Improve
Suggest changes
Like Article
Like
Report

The optimization algorithms are capable of solving complex problems and genetic algorithm is one of the optimization algorithm. Genetic Algorithm can be easily integrate with PyTorch to address a wide array of optimization tasks. We will understand how to implement Genetic Algorithm using PyTorch.

Genetic Algorithms

Genetic algorithms (GAs) are optimization techniques inspired by natural selection. They start with a population of potential solutions to a problem and improve them over many generations. Genetic algorithms imitate natural selection to solve problems. They start with a group of solutions, evaluate how good they are, and then mix and mutate the best ones to create new solutions. This process continues, improving the solutions over many iterations until a satisfactory one is found. GAs are useful for complex problems where traditional methods struggle.

Algorithm:

  • Population: Begin with a group of random solutions to the problem.
  • Fitness Function: Evaluate how good each solution is using a fitness function, which measures how well it solves the problem.
  • Selection: Choose the best solutions from the population to become parents for the next generation.
  • Crossover: Combine pairs of parents to create new solutions (offspring).
  • Mutation: Occasionally introduce random changes to keep the solutions diverse.
  • Repeat: Continue this process for many generations, gradually improving the solutions.

Implementing Genetic Algorithm using PyTorch

Here, we implement a simple genetic algorithm (GA) to optimize the hyperparameters of a neural network using PyTorch. We create an initial population of individuals representing different sets of hyperparameters, evaluate their fitness by training and evaluating neural networks, perform selection, crossover, and mutation operations, and iterate for a fixed number of generations. For this we follow these steps:

Step 1: Import necessary libraries

We will first import necessary libraries:

import torch
import torch.nn as nn
import torch.optim as optim
from torchvision import datasets, transforms
from torch.utils.data import DataLoader

Step 2: Define neural network

The CNN class defines a Convolutional Neural Network architecture using PyTorch's nn.Module. It consists of two convolutional layers (conv1 and conv2) followed by max-pooling operations and two fully connected layers (fc1 and fc2).

class CNN(nn.Module):
def __init__(self):
super(CNN, self).__init__()
self.conv1 = nn.Conv2d(1, 32, kernel_size=3, stride=1, padding=1)
self.conv2 = nn.Conv2d(32, 64, kernel_size=3, stride=1, padding=1)
self.fc1 = nn.Linear(64 * 7 * 7, 128)
self.fc2 = nn.Linear(128, 10)

def forward(self, x):
x = torch.relu(self.conv1(x))
x = torch.max_pool2d(x, kernel_size=2, stride=2)
x = torch.relu(self.conv2(x))
x = torch.max_pool2d(x, kernel_size=2, stride=2)
x = x.view(-1, 64 * 7 * 7)
x = torch.relu(self.fc1(x))
x = self.fc2(x)
return torch.log_softmax(x, dim=1)

Step 3: Compute Fitness

The function calculates the accuracy of a given model (individual) on the test dataset. It trains the model on the training dataset for a fixed number of epochs (5 in this case) and then evaluates its accuracy on the test dataset.

def compute_fitness(model, train_loader, test_loader):
criterion = nn.NLLLoss()
optimizer = optim.Adam(model.parameters())

model.train()
for epoch in range(5):
for data, target in train_loader:
optimizer.zero_grad()
output = model(data)
loss = criterion(output, target)
loss.backward()
optimizer.step()

model.eval()
correct = 0
total = 0
with torch.no_grad():
for data, target in test_loader:
output = model(data)
_, predicted = torch.max(output.data, 1)
total += target.size(0)
correct += (predicted == target).sum().item()

accuracy = correct / total
return accuracy

Step 4: Define Genetic Algorithm Parameters

  • population_size: Number of individuals in the population.
  • mutation_rate: Probability of mutation for each parameter.
  • num_generations: Number of generations for the genetic algorithm.
# Genetic algorithm parameters
population_size = 10
mutation_rate = 0.1
num_generations = 5

Step 5: Population Initialization Function

The function initializes the population with a specified number of CNN models.

# Initialize genetic algorithm parameters
def initialize_population():
population = []
for _ in range(population_size):
model = CNN()
population.append(model)
return population

Step 6: Crossover Operator (crossover):

The crossover operator combines genetic information from two parent models to produce two child models. It implements single-point crossover by swapping weights between the parent models' convolutional layers.

# Crossover operator: Single-point crossover
def crossover(parent1, parent2):
child1 = CNN()
child2 = CNN()
child1.conv1.weight.data = torch.cat((parent1.conv1.weight.data[:16], parent2.conv1.weight.data[16:]), dim=0)
child2.conv1.weight.data = torch.cat((parent2.conv1.weight.data[:16], parent1.conv1.weight.data[16:]), dim=0)
return child1, child2

Step 7: Mutation Operator (mutate):

The mutation operator introduces random perturbations to the parameters of the model with a certain probability (mutation_rate). It adds Gaussian noise to the model's parameters.

# Mutation operator: Random mutation
def mutate(model):
for param in model.parameters():
if torch.rand(1).item() < mutation_rate:
param.data += torch.randn_like(param.data) * 0.1 # Adding Gaussian noise with std=0.1
return model

Step 8: Loading Dataset

The MNIST dataset is loaded using torchvision. It consists of handwritten digit images and corresponding labels.

# Load MNIST dataset
transform = transforms.Compose([transforms.ToTensor(), transforms.Normalize((0.5,), (0.5,))])
train_dataset = datasets.MNIST(root='./data', train=True, transform=transform, download=True)
train_loader = DataLoader(train_dataset, batch_size=64, shuffle=True)
test_dataset = datasets.MNIST(root='./data', train=False, transform=transform, download=True)
test_loader = DataLoader(test_dataset, batch_size=64, shuffle=False)

Step 9: Executing Genetic Algorithm

The genetic algorithm iterates over multiple generations, evaluating the fitness of each individual (model) in the population, selecting the top-performing individuals for the next generation, and applying crossover and mutation operators to generate new individuals.

# Genetic algorithm
population = initialize_population()
for generation in range(num_generations):
print("Generation:", generation + 1)
best_accuracy = 0
best_individual = None

# Compute fitness for each individual
for individual in population:
fitness = compute_fitness(individual, train_loader, test_loader)
if fitness > best_accuracy:
best_accuracy = fitness
best_individual = individual

print("Best accuracy in generation", generation + 1, ":", best_accuracy)
print("Best individual:", best_individual)

next_generation = []

# Select top individuals for next generation
selected_individuals = population[:population_size // 2]

# Crossover and mutation
for i in range(0, len(selected_individuals), 2):
parent1 = selected_individuals[i]
parent2 = selected_individuals[i + 1]
child1, child2 = crossover(parent1, parent2)
child1 = mutate(child1)
child2 = mutate(child2)
next_generation.extend([child1, child2])

population = next_generation

Complete Code

Python3
import torch import torch.nn as nn import torch.optim as optim from torchvision import datasets, transforms from torch.utils.data import DataLoader  # Define the neural network architecture (CNN) class CNN(nn.Module):     def __init__(self):         super(CNN, self).__init__()         self.conv1 = nn.Conv2d(1, 32, kernel_size=3, stride=1, padding=1)         self.conv2 = nn.Conv2d(32, 64, kernel_size=3, stride=1, padding=1)         self.fc1 = nn.Linear(64 * 7 * 7, 128)         self.fc2 = nn.Linear(128, 10)      def forward(self, x):         x = torch.relu(self.conv1(x))         x = torch.max_pool2d(x, kernel_size=2, stride=2)         x = torch.relu(self.conv2(x))         x = torch.max_pool2d(x, kernel_size=2, stride=2)         x = x.view(-1, 64 * 7 * 7)         x = torch.relu(self.fc1(x))         x = self.fc2(x)         return torch.log_softmax(x, dim=1)  # Function to compute fitness (accuracy) of an individual (hyperparameters) def compute_fitness(model, train_loader, test_loader):     criterion = nn.NLLLoss()     optimizer = optim.Adam(model.parameters())      model.train()     for epoch in range(5):         for data, target in train_loader:             optimizer.zero_grad()             output = model(data)             loss = criterion(output, target)             loss.backward()             optimizer.step()      model.eval()     correct = 0     total = 0     with torch.no_grad():         for data, target in test_loader:             output = model(data)             _, predicted = torch.max(output.data, 1)             total += target.size(0)             correct += (predicted == target).sum().item()      accuracy = correct / total     return accuracy  # Genetic algorithm parameters population_size = 10 mutation_rate = 0.1 num_generations = 5  # Initialize genetic algorithm parameters def initialize_population():     population = []     for _ in range(population_size):         model = CNN()         population.append(model)     return population  # Crossover operator: Single-point crossover def crossover(parent1, parent2):     child1 = CNN()     child2 = CNN()     child1.conv1.weight.data = torch.cat((parent1.conv1.weight.data[:16], parent2.conv1.weight.data[16:]), dim=0)     child2.conv1.weight.data = torch.cat((parent2.conv1.weight.data[:16], parent1.conv1.weight.data[16:]), dim=0)     return child1, child2  # Mutation operator: Random mutation def mutate(model):     for param in model.parameters():         if torch.rand(1).item() < mutation_rate:             param.data += torch.randn_like(param.data) * 0.1  # Adding Gaussian noise with std=0.1     return model  # Load MNIST dataset transform = transforms.Compose([transforms.ToTensor(), transforms.Normalize((0.5,), (0.5,))]) train_dataset = datasets.MNIST(root='./data', train=True, transform=transform, download=True) train_loader = DataLoader(train_dataset, batch_size=64, shuffle=True) test_dataset = datasets.MNIST(root='./data', train=False, transform=transform, download=True) test_loader = DataLoader(test_dataset, batch_size=64, shuffle=False)  # Genetic algorithm population = initialize_population() for generation in range(num_generations):     print("Generation:", generation + 1)     best_accuracy = 0     best_individual = None      # Compute fitness for each individual     for individual in population:         fitness = compute_fitness(individual, train_loader, test_loader)         if fitness > best_accuracy:             best_accuracy = fitness             best_individual = individual      print("Best accuracy in generation", generation + 1, ":", best_accuracy)     print("Best individual:", best_individual)      next_generation = []      # Select top individuals for next generation     selected_individuals = population[:population_size // 2]      # Crossover and mutation     for i in range(0, len(selected_individuals), 2):         parent1 = selected_individuals[i]         parent2 = selected_individuals[i + 1]         child1, child2 = crossover(parent1, parent2)         child1 = mutate(child1)         child2 = mutate(child2)         next_generation.extend([child1, child2])      population = next_generation  # Print final population print("Final population:") for individual in population:     print("Individual:", individual) 

Output:

Generation: 1
Best accuracy in generation 1 : 0.912
Best individual: CNN(
(conv1): Conv2d(1, 32, kernel_size=(3, 3), stride=(1, 1), padding=(1, 1))
(conv2): Conv2d(32, 64, kernel_size=(3, 3), stride=(1, 1), padding=(1, 1))
(fc1): Linear(in_features=3136, out_features=128, bias=True)
(fc2): Linear(in_features=128, out_features=10, bias=True)
)
...

Generation: 5
Best accuracy in generation 5 : 0.935
Best individual: CNN(
(conv1): Conv2d(1, 32, kernel_size=(3, 3), stride=(1, 1), padding=(1, 1))
(conv2): Conv2d(32, 64, kernel_size=(3, 3), stride=(1, 1), padding=(1, 1))
(fc1): Linear(in_features=3136, out_features=128, bias=True)
(fc2): Linear(in_features=128, out_features=10, bias=True)
)

Final population:
Individual: CNN(
(conv1): Conv2d(1, 32, kernel_size=(3, 3), stride=(1, 1), padding=(1, 1))
(conv2): Conv2d(32, 64, kernel_size=(3, 3), stride=(1, 1), padding=(1, 1))
(fc1): Linear(in_features=3136, out_features=128, bias=True)
(fc2): Linear(in_features=128, out_features=10, bias=True)
)
...

Output Explanation

  • For each generation, the code prints the generation number (Generation: X).
  • It also displays the best accuracy achieved in that generation (Best accuracy in generation X : Y).
  • Additionally, it shows the architecture of the best individual CNN model in that generation (Best individual: ...).
  • After all generations are processed, the code prints the final population of evolved CNN models.
  • Each individual in the final population represents a CNN model with its architecture printed.

Conclusion

In summary, combining PyTorch with genetic algorithms or optimization methods offers a powerful way to solve complex problems in machine learning and beyond. By leveraging PyTorch's flexibility and genetic algorithms' exploration abilities, practitioners can efficiently optimize neural network architectures, fine-tune hyperparameters, defend against attacks, allocate resources effectively, and automate machine learning processes. This collaboration between PyTorch and genetic algorithms promises to drive innovation and solve challenging optimization problems across various domains.


Next Article
How to Implement Various Optimization Algorithms in Pytorch?
author
deepkumarpatra
Improve
Article Tags :
  • Deep Learning
  • AI-ML-DS
  • Python-PyTorch
  • AI-ML-DS With Python

Similar Reads

  • How to Implement Adam Gradient Descent from Scratch using Python?
    Grade descent is an extensively used optimization algorithm in machine literacy and deep literacy. It's used to minimize the cost or loss function of a model by iteratively confirming the model's parameters grounded on the slants of the cost function with respect to those parameters. One variant of
    14 min read
  • How to Implement Various Optimization Algorithms in Pytorch?
    Optimization algorithms are an essential aspect of deep learning, and PyTorch provides a wide range of optimization algorithms to help us train our neural networks effectively. In this article, we will explore various optimization algorithms in PyTorch and demonstrate how to implement them. We will
    6 min read
  • Hyperparameter tuning SVM parameters using Genetic Algorithm
    The performance support Vector Machines (SVMs) are heavily dependent on hyperparameters such as the regularization parameter (C) and the kernel parameters (gamma for RBF kernel). Genetic Algorithms (GAs) leverage evolutionary principles to search for optimal hyperparameter values. This article explo
    9 min read
  • Simple Genetic Algorithm (SGA)
    Prerequisite - Genetic Algorithm Introduction : Simple Genetic Algorithm (SGA) is one of the three types of strategies followed in Genetic algorithm. SGA starts with the creation of an initial population of size N.Then, we evaluate the goodness/fitness of each of the solutions/individuals. After tha
    1 min read
  • How to use GPU acceleration in PyTorch?
    PyTorch is a well-liked deep learning framework that offers good GPU acceleration support, enabling users to take advantage of GPUs' processing power for quicker neural network training. This post will discuss the advantages of GPU acceleration, how to determine whether a GPU is available, and how t
    7 min read
  • Introduction to Optimization with Genetic Algorithm
    Optimization is the process of finding the best solution after evaluating all possible combinations. When dealing with complex problems, finding the optimal solution becomes crucial. One powerful tool in machine learning for solving such optimization problems is the genetic algorithm. Inspired by th
    10 min read
  • Implementation of Grey Wolf Optimization (GWO) Algorithm
    Previous article Grey wolf optimization- Introduction talked about inspiration of grey wolf optimization, and its mathematical modelling and algorithm. In this article we will implement grey wolf optimization (GWO) for two fitness functions - Rastrigin function and Sphere function. The aim of Grey w
    7 min read
  • How to use a DataLoader in PyTorch?
    Operating with large datasets requires loading them into memory all at once. In most cases, we face a memory outage due to the limited amount of memory available in the system. Also, the programs tend to run slowly due to heavy datasets loaded once. PyTorch offers a solution for parallelizing the da
    2 min read
  • How to Use Multiple GPUs in PyTorch
    PyTorch, a popular deep learning framework, provides robust support for utilizing multiple GPUs to accelerate model training. Leveraging multiple GPUs can significantly reduce training time and improve model performance. This article explores how to use multiple GPUs in PyTorch, focusing on two prim
    5 min read
  • How to Split a Dataset Using PyTorch
    Splitting a dataset is an important step in training machine learning models. It helps to separate the data into different sets, typically training, and validation, so we can train our model on one set and validate its performance on another. In this article, we are going to discuss the process of s
    6 min read
geeksforgeeks-footer-logo
Corporate & Communications Address:
A-143, 7th Floor, Sovereign Corporate Tower, Sector- 136, Noida, Uttar Pradesh (201305)
Registered Address:
K 061, Tower K, Gulshan Vivante Apartment, Sector 137, Noida, Gautam Buddh Nagar, Uttar Pradesh, 201305
GFG App on Play Store GFG App on App Store
Advertise with us
  • Company
  • About Us
  • Legal
  • Privacy Policy
  • In Media
  • Contact Us
  • Advertise with us
  • GFG Corporate Solution
  • Placement Training Program
  • Languages
  • Python
  • Java
  • C++
  • PHP
  • GoLang
  • SQL
  • R Language
  • Android Tutorial
  • Tutorials Archive
  • DSA
  • Data Structures
  • Algorithms
  • DSA for Beginners
  • Basic DSA Problems
  • DSA Roadmap
  • Top 100 DSA Interview Problems
  • DSA Roadmap by Sandeep Jain
  • All Cheat Sheets
  • Data Science & ML
  • Data Science With Python
  • Data Science For Beginner
  • Machine Learning
  • ML Maths
  • Data Visualisation
  • Pandas
  • NumPy
  • NLP
  • Deep Learning
  • Web Technologies
  • HTML
  • CSS
  • JavaScript
  • TypeScript
  • ReactJS
  • NextJS
  • Bootstrap
  • Web Design
  • Python Tutorial
  • Python Programming Examples
  • Python Projects
  • Python Tkinter
  • Python Web Scraping
  • OpenCV Tutorial
  • Python Interview Question
  • Django
  • Computer Science
  • Operating Systems
  • Computer Network
  • Database Management System
  • Software Engineering
  • Digital Logic Design
  • Engineering Maths
  • Software Development
  • Software Testing
  • DevOps
  • Git
  • Linux
  • AWS
  • Docker
  • Kubernetes
  • Azure
  • GCP
  • DevOps Roadmap
  • System Design
  • High Level Design
  • Low Level Design
  • UML Diagrams
  • Interview Guide
  • Design Patterns
  • OOAD
  • System Design Bootcamp
  • Interview Questions
  • Inteview Preparation
  • Competitive Programming
  • Top DS or Algo for CP
  • Company-Wise Recruitment Process
  • Company-Wise Preparation
  • Aptitude Preparation
  • Puzzles
  • School Subjects
  • Mathematics
  • Physics
  • Chemistry
  • Biology
  • Social Science
  • English Grammar
  • Commerce
  • World GK
  • GeeksforGeeks Videos
  • DSA
  • Python
  • Java
  • C++
  • Web Development
  • Data Science
  • CS Subjects
@GeeksforGeeks, Sanchhaya Education Private Limited, All rights reserved
We use cookies to ensure you have the best browsing experience on our website. By using our site, you acknowledge that you have read and understood our Cookie Policy & Privacy Policy
Lightbox
Improvement
Suggest Changes
Help us improve. Share your suggestions to enhance the article. Contribute your expertise and make a difference in the GeeksforGeeks portal.
geeksforgeeks-suggest-icon
Create Improvement
Enhance the article with your expertise. Contribute to the GeeksforGeeks community and help create better learning resources for all.
geeksforgeeks-improvement-icon
Suggest Changes
min 4 words, max Words Limit:1000

Thank You!

Your suggestions are valuable to us.

What kind of Experience do you want to share?

Interview Experiences
Admission Experiences
Career Journeys
Work Experiences
Campus Experiences
Competitive Exam Experiences