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: Calculate the new velocity and update weights for each layer 
docstr_tok: ["Calculate","the","new","velocity","and","update","weights","for","each","layer"]
code: def _update_weights(self, individual):
      """Calculate the new velocity and update weights for each layer"""
      # Two random parameters used to update the velocity
      r1 = np.random.uniform()
      r2 = np.random.uniform()
      for i, layer in enumerate(individual.layers):
          if hasattr(layer, "W"):
              # Layer weights velocity
              first_term_W = (
                  self.inertia_w * individual.velocity[i]["W"]
              )
              second_term_W = (
                  self.cognitive_w
                  * r1
                  * (individual.best_layers[i].W - layer.W)
              )
              third_term_W = (
                  self.social_w
                  * r2
                  * (self.best_individual.layers[i].W - layer.W)
              )
              new_velocity = first_term_W + second_term_W + third_term_W
              individual.velocity[i]["W"] = np.clip(
                  new_velocity, self.min_v, self.max_v
              )
  
              # Bias weight velocity
              first_term_w0 = (
                  self.inertia_w * individual.velocity[i]["w0"]
              )
              second_term_w0 = (
                  self.cognitive_w
                  * r1
                  * (individual.best_layers[i].w0 - layer.w0)
              )
              third_term_w0 = (
                  self.social_w
                  * r2
                  * (self.best_individual.layers[i].w0 - layer.w0)
              )
              new_velocity = (
                  first_term_w0 + second_term_w0 + third_term_w0
              )
              individual.velocity[i]["w0"] = np.clip(
                  new_velocity, self.min_v, self.max_v
              )
  
              # Update layer weights with velocity
              individual.layers[i].W += individual.velocity[i]["W"]
              individual.layers[i].w0 += individual.velocity[i]["w0"]
  
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 4 for calling the ParticleSwarmOptimizedNN obj's underlying member method code with example usage: obj._update_weights(individual) without return types