ahmedfgad / GeneticAlgorithmPython

Source code of PyGAD, a Python 3 library for building the genetic algorithm and training machine learning algorithms (Keras & PyTorch).
https://pygad.readthedocs.io
BSD 3-Clause "New" or "Revised" License
1.9k stars 467 forks source link

Advice for GA implementation in my project #4

Closed NihitBorpujari closed 4 years ago

NihitBorpujari commented 4 years ago

Hey!

I am working on some code with open cv to track the percentage of frames in which my face is detected in terms of "attention span". I intend to optimize this attention span with an evolutionary solver that iterates a combination of diffused and direct light levels in my environment with an arduino board. Owing to the long range of time over which a generation of light levels need to be iterated I am unsure as to the best Evolutionary algorithm library or approach i can use to do this. I am currently not connected to an arduino and am just trying to do this with dummy numbers (1-4,1-4) for diffused and direct respectively. The idea is that every 15 mins or so ( lets say 50,000 frames) the light levels assume a new and improved combination and wait for another 15.

I am new to python and coding in general so I am finding it harder to figure out which library and it's ideal implementation for this purpose I'd be grateful if you have any advice.

ahmedfgad commented 4 years ago

Hello,

So, you are building a project that tries to optimize the light level to gain more attention from the user. For so, you want to use an evolutionary algorithm for selecting the best levels of light.

I will not talk about which algorithm might be better [because I do not have enough knowledge about all algorithms] but I can say that the genetic algorithm might be a good fit.

Here is my opinion about how the project might work:

  1. The genetic algorithm starts with an initial population of solutions. In your case, the solution should hold some parameters (i.e. genes) describing the light configuration. Assume you selected the population size to be 5.
  2. Use the configuration in each of the 5 solutions to capture the frames during the 15 minutes period [50,000 as you said]. So, you will end up with 50,000 frames for each light configuration for a total of 5*50,000 frames.
  3. For each set of frames captured with each of the 5 solutions, calculate the fitness value which should refer to the number of frames in which the user's face is detected.
  4. Based on the fitness values, calculate the best solutions as parents.
  5. Apply crossover & mutation.
  6. Create a new population.
  7. Repeat steps 2 to 6 until you reach satisfying results or after a number of generations.

This is about how to work with your project.

Regarding the library to be used, I think my recently published library PyGAD that is built over my GitHub project [https://github.com/ahmedfgad/GeneticAlgorithmPython] could be a fit.

I am available in case some more clarification is required.

Good luck!

NihitBorpujari commented 4 years ago

Hello Ahmed,

Thanks so much for your guidance. I have since dabbled a bit with your library and have tried to set it up for my purpose.

I am however still a bit confused as to how to set it up with my open cv facial recognition because as of now the way I am recording "attention spans" is counting the required number of frames and then extracting the percentage out of it and then restarting the count. So if I bring an initial population of 5 I'm not sure how to associate the first generation in sequence with each of the first 5 percentages. Ideally it goes like. (with placeholder numbers)

light 1 levels (1-4) light 2 levels (1-4) i.e Light levels (1-4,1-4)

first population --> (1.2,3.86) (2.45,3.65) (2,3.9) (2,3) (3.1,1.3)

for light (1.2,3.86) count frames. Attention percentage 46% for light (2.45,3.65) count frames. Attention percentage 78% for light (2,3.9) count frames. Attention percentage 48% for light (2,3) count frames. Attention percentage 90% for light (3.1,1.3) count frames. Attention percentage 17%

compare fitness and select parents, crossover mutate.

second population --> etc ...

I am just not sure how to nest or arrange the ga functions within the counting and camera recording functions so that I may get this sort of sequence of events.

I would be so grateful if you could have a quick look at the code and suggest the right approach? Since i'm new to python i'm still not clear as to how to interact with lists, tuples, and variables well enough to set this up.

Thank you so much for your time, I hope i'm not wasting it. :/

Best regards,

Nihit

On Sun, Apr 19, 2020 at 3:24 PM Ahmed Gad notifications@github.com wrote:

Hello,

So, you are building a project that tries to optimize the light level to gain more attention from the user. For so, you want to use an evolutionary algorithm for selecting the best levels of light.

I will not talk about which algorithm might be better [because I do not have enough knowledge about all algorithms] but I can say that the genetic algorithm might be a good fit.

Here is my opinion about how the project might work:

  1. The genetic algorithm starts with an initial population of solutions. In your case, the solution should hold some parameters (i.e. genes) describing the light configuration. Assume you selected the population size to be 5.
  2. Use the configuration in each of the 5 solutions to capture the frames during the 15 minutes period [50,000 as you said]. So, you will end up with 50,000 frames for each light configuration for a total of 5*50,000 frames.
  3. For each set of frames captured with each of the 5 solutions, calculate the fitness value which should refer to the number of frames in which the user's face is detected.
  4. Based on the fitness values, calculate the best solutions as parents.
  5. Apply crossover & mutation.
  6. Create a new population.
  7. Repeat steps 2 to 6 until you reach satisfying results or after a number of generations.

This is about how to work with your project.

Regarding the library to be used, I think my recently published library PyGAD https://pypi.org/project/pygad that is built over my GitHub project [https://github.com/ahmedfgad/GeneticAlgorithmPython] could be a fit.

I am available in case some more clarification is required.

Good luck!

— You are receiving this because you authored the thread. Reply to this email directly, view it on GitHub https://github.com/ahmedfgad/GeneticAlgorithmPython/issues/4#issuecomment-616134038, or unsubscribe https://github.com/notifications/unsubscribe-auth/APHFLXPD7MIGOUDOYDWT3VTRNL3SVANCNFSM4MKYH5LQ .

import pygad import numpy as np import cv2 import string import random from cv2 import cv2

face_cascade = cv2.CascadeClassifier('C:/Dev/cascades/data/haarcascade_frontalface_alt2.xml')

cap = cv2.VideoCapture(0)

value = 0 numface = 0

attention = []

light_levels = [(1,2,3,4),(1,2,3,4)] num_light_levels = 2 sol_per_pop = 5 pop_size = (sol_per_pop,num_light_levels) new_population = np.random.uniform(low=1, high=4, size=pop_size) num_generations = 50 num_parents_mating = 2 mutation_percent_genes=10 parent_selection_type = "tournament" # Type of parent selection. crossover_type = "two_points" # Type of the crossover operator. mutation_type = "scramble" # Type of the mutation operator. keep_parents = 1 num_genes=1

def fitness_func(solution): fitness = 1.0 / np.abs(attention - desired_attention) return fitness

ga_instance = pygad.GA(num_generations=num_generations, sol_per_pop=sol_per_pop, num_parents_mating=num_parents_mating, fitness_func=fitness_func, mutation_percent_genes=mutation_percent_genes, num_genes=num_genes, parent_selection_type=parent_selection_type, crossover_type=crossover_type, mutation_type=mutation_type, keep_parents=keep_parents, K_tournament=3)

while(True):

ret, frame = cap.read()
value += 1

gray = cv2.cvtColor(frame, cv2.COLOR_BGR2GRAY)
faces = face_cascade.detectMultiScale(gray, scaleFactor=1.5, minNeighbors=5)
for (x, y, w, h) in faces:

    roi_color  = frame[y:y+h, x:x+w]

    color = (255, 255, 255)
    stroke = 2
    width = x + w 
    height = y + h
    cv2.rectangle(frame, (x, y), (width, height), color, stroke)

    nface = str(numface)
    framez = str(value)
    A = int(nface)
    B = int(framez)

#if len(faces) == 0:
#    print(0)

#elif len(faces) !=0:
#    print(1)
#    numface += 1

if len(faces) != 0:
    numface += 1

desired_attention = 100

if value == 100:
    attention.append(A/B*100)
    print(attention)
    print(new_population)
    numface = 0
    value = 0

if len(attention) == 5:
    print("Best result : ", np.max(np.sum(new_population*light_levels, axis=1)))

cv2.imshow('frame' ,frame)
if cv2.waitKey(20) & 0xFF == ord('q'):
    break

cap.release() cv2.destroyAllWindows()

ahmedfgad commented 4 years ago

Hi,

After inspecting your code, here are my comments:

  1. You created a variable named pop_size that holds the size of the population. To use my library, you do not have to define this variable as it is automatically defined internally within the GA class and there is no need for it within your script.
  2. You used the num_light_levels variable as the number of genes. Later, you defined the variable num_genes to hold the number of genes and you passed it to the constructor of the GA class. However, the 2 variables have different values. num_light_levels=2 and num_genes=1 and I see that the right value is 2. Then, replace the num_genes variable by the num_light_levels variable.
  3. The variable desired_attention used within the fitness_func() is not defined. This cases a NameError exception. Please define its value.
  4. Even you created an instance of the GA class within the ga_instance variable, you did not run the genetic algorithm. You need to run this ga_instance.run(). Note that calling the run() method returns a NameError exception because the variable desired_attention is not defined.
  5. The fitness_func() is not implemented in the right way. It should work as follows: For the 5 solutions you defined [(1.2,3.86), (2.45,3.65), (2,3.9), (2,3), (3.1,1.3)], use each one to calculate the attention percentage using OpenCV. In other words, the fitness_func() should accept the solution (e.g. (1.2,3.86)), apply the OpenCV stuff you built within the while loop, return the attention percentage, calculate the fitness value, and finally return this value. In your case, the fitness_func() is completely separated from the genetic algorithm. Note that I did not test the OpenCV code and not sure whether it works or not.

For the code used from my library, here is the correct way to do it but remember that you need to edit the fitness function to calculate the attention percentage correctly.

import pygad
import numpy

value = 0
numface = 0

attention = []

light_levels = [(1,2,3,4),(1,2,3,4)]
num_light_levels = 2
sol_per_pop = 5
pop_size = (sol_per_pop,num_light_levels)
new_population = numpy.random.uniform(low=1, high=4, size=pop_size)
num_generations = 50
num_parents_mating = 2
mutation_percent_genes=10
parent_selection_type = "tournament" # Type of parent selection.
crossover_type = "two_points" # Type of the crossover operator.
mutation_type = "scramble" # Type of the mutation operator.
keep_parents = 1

def fitness_func(solution):
    # OpenCV code to calculate the fitness value (i.e. attention percentage)
    fitness = 1.0 / numpy.abs(attention - desired_attention)
    return fitness

ga_instance = pygad.GA(num_generations=num_generations,
            sol_per_pop=sol_per_pop,
            num_parents_mating=num_parents_mating,
            fitness_func=fitness_func,
            mutation_percent_genes=mutation_percent_genes,
            num_genes=num_light_levels,
            parent_selection_type=parent_selection_type,
            crossover_type=crossover_type,
            mutation_type=mutation_type,
            keep_parents=keep_parents,
            K_tournament=3)

ga_instance.run()

In case something is not clear, please let me know.

Best regards, Ahmed

nurullo98 commented 4 years ago

Salam aleykum Ahmed! Thanks for your opensource projects, they help a lot, especially GA one. I have an issue with GA. I cant find in documentation how to use binary genes. Thank you!

ahmedfgad commented 4 years ago

Waalikum Alsalam,

PyGAD does not fully support binary genetic algorithm but you can tweak its parameters to work with the binary representation.

At first, prepare the initial population and feed it to the initial_population parameter of the pygad.GA class. Secondly, use one of these mutation types:

  1. Swap
  2. Scramble
  3. Inversion

You can specify the type of mutation using the mutation_type parameter.

Regards, Ahmed

nurullo98 commented 4 years ago

Thanks a lot. Very helpful advice.

On Fri, Jun 19, 2020, 14:21 Ahmed Gad notifications@github.com wrote:

Waalikum Alsalam,

PyGAD does not fully support binary genetic algorithm but you can tweak its parameters to work with the binary representation.

At first, prepare the initial population and feed it to the initial_population parameter of the pygad.GA class. Secondly, use one of these mutation types:

  1. Swap
  2. Scramble
  3. Inversion

You can specify the type of mutation using the mutation_type parameter https://pygad.readthedocs.io/en/latest/README_pygad_ReadTheDocs.html#init .

Regards, Ahmed

— You are receiving this because you commented. Reply to this email directly, view it on GitHub https://github.com/ahmedfgad/GeneticAlgorithmPython/issues/4#issuecomment-646531935, or unsubscribe https://github.com/notifications/unsubscribe-auth/AINSJAAZAZMCHK4V7RMRRP3RXMUZXANCNFSM4MKYH5LQ .

ahmedfgad commented 4 years ago

Good luck.

ahmedfgad commented 4 years ago

Closed for no further interaction.