class_docstr: Evolutionary optimization of Neural Networks.
  
  Parameters:
  -----------
  n_individuals: int
      The number of neural networks that are allowed in the population at a time.
  mutation_rate: float
      The probability that a weight will be mutated.
  model_builder: method
      A method which returns a user specified NeuralNetwork instance. 
class_docstr_tok: ["Evolutionary","optimization","of","Neural","Networks",".","Parameters",":","--","--","--","--","--","-","n_individuals",":","int","The","number","of","neural","networks","that","are","allowed","in","the","population","at","a","time",".","mutation_rate",":","float","The","probability","that","a","weight","will","be","mutated",".","model_builder",":","method","A","method","which","returns","a","user","specified","NeuralNetwork","instance","."]
docstr: Will evolve the population for n_generations based on dataset X and labels y
docstr_tok: ["Will","evolve","the","population","for","n_generations","based","on","dataset","X","and","labels","y"]
code: def evolve(self, X, y, n_generations):
      """Will evolve the population for n_generations based on dataset X and labels y"""
      self.X, self.y = X, y
  
      self._initialize_population()
  
      # The 40% highest fittest individuals will be selected for the next generation
      n_winners = int(self.population_size * 0.4)
      # The fittest 60% of the population will be selected as parents to form offspring
      n_parents = self.population_size - n_winners
  
      for epoch in range(n_generations):
          # Determine the fitness of the individuals in the population
          self._calculate_fitness()
  
          # Sort population by fitness
          sorted_i = np.argsort(
              [model.fitness for model in self.population]
          )[::-1]
          self.population = [self.population[i] for i in sorted_i]
  
          # Get the individual with the highest fitness
          fittest_individual = self.population[0]
          print(
              "[%d Best Individual - Fitness: %.5f, Accuracy: %.1f%%]"
              % (
                  epoch,
                  fittest_individual.fitness,
                  float(100 * fittest_individual.accuracy),
              )
          )
          # The 'winners' are selected for the next generation
          next_population = [
              self.population[i] for i in range(n_winners)
          ]
  
          total_fitness = np.sum(
              [model.fitness for model in self.population]
          )
          # The probability that a individual will be selected as a parent is proportionate to its fitness
          parent_probabilities = [
              model.fitness / total_fitness for model in self.population
          ]
          # Select parents according to probabilities (without replacement to preserve diversity)
          parents = np.random.choice(
              self.population,
              size=n_parents,
              p=parent_probabilities,
              replace=False,
          )
          for i in np.arange(0, len(parents), 2):
              # Perform crossover to produce offspring
              child1, child2 = self._crossover(
                  parents[i], parents[i + 1]
              )
              # Save mutated offspring for next population
              next_population += [
                  self._mutate(child1),
                  self._mutate(child2),
              ]
  
          self.population = next_population
  
      return fittest_individual
  
file_path: ML-From-Scratch/mlfromscratch/supervised_learning/neuroevolution.py
imports: from __future__ import print_function, division
  import numpy
  import copy
label_desc: Use image node_id 8 for calling the Neuroevolution obj's underlying member method code with example usage: obj.evolve(X, y, n_generations) and returns: fittest_individual