class_docstr: Particle Swarm Optimization of Neural Network.
  
  Parameters:
  -----------
  n_individuals: int
      The number of neural networks that are allowed in the population at a time.
  model_builder: method
      A method which returns a user specified NeuralNetwork instance.
  inertia_weight:     float [0,1)
  cognitive_weight:   float [0,1)
  social_weight:      float [0,1)
  max_velocity: float
      The maximum allowed value for the velocity.
  
  Reference:
      Neural Network Training Using Particle Swarm Optimization
      https://visualstudiomagazine.com/articles/2013/12/01/neural-network-training-using-particle-swarm-optimization.aspx 
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 best individual of the population is initialized as population's first ind.
      self.best_individual = copy.copy(self.population[0])
  
      for epoch in range(n_generations):
          for individual in self.population:
              # Calculate new velocity and update the NN weights
              self._update_weights(individual)
              # Calculate the fitness of the updated individual
              self._calculate_fitness(individual)
  
              # If the current fitness is higher than the individual's previous highest
              # => update the individual's best layer setup
              if individual.fitness > individual.highest_fitness:
                  individual.best_layers = copy.copy(individual.layers)
                  individual.highest_fitness = individual.fitness
              # If the individual's fitness is higher than the highest recorded fitness for the
              # whole population => update the best individual
              if individual.fitness > self.best_individual.fitness:
                  self.best_individual = copy.copy(individual)
  
          print(
              "[%d Best Individual - ID: %d Fitness: %.5f, Accuracy: %.1f%%]"
              % (
                  epoch,
                  self.best_individual.id,
                  self.best_individual.fitness,
                  100 * float(self.best_individual.accuracy),
              )
          )
      return self.best_individual
  
file_path: ML-From-Scratch/mlfromscratch/supervised_learning/particle_swarm_optimization.py
imports: from __future__ import print_function, division
  import numpy
  import copy
label_desc: Use image node_id 6 for calling the ParticleSwarmOptimizedNN obj's underlying member method code with example usage: obj.evolve(X, y, n_generations) and returns: self