Frontender writes neurons. Difficulty level "I want to handle"

Sooner or later this must happen

Sooner or later, the front-end developer gets tired of playing with his frameworks, gets tired of bothering his colleagues - backend, gets tired of playing devops and starts looking towards machine learning, data is science and that's all. Fortunately, every second course for those who want to enter the website contributes to this, shouting on all platforms how easy it is. I, too, fed up with transferring data from the database to the API, and then from the API to tables and forms, decided to take a short vacation and try to apply my frontend skills in machine learning. Fortunately, there are people like  Daniel Shiffman  and  Charlie Gerard who, by their example, help not to quit what they started after seeing the first pages with mathematical formulas.





If we go back a little and take a look at the title, we will see that I will not  copy from books and  throw high-tech words trying to explain what I did.





I am almost sure that everyone, hearing the phrase "machine learning" imagines a picture where many, many neurons in several layers and all are intertwined. So, this is no coincidence. This is why machine learning was conceived - to implement the human brain and its neural networks in digital form.





Neural network diagram
Neural network diagram

? , . , , . - , , , . , , .





. , , - , . - () .





, ? , - , ( , , ).





- , - . .





- . . . .





โ€œ โ€ - , , , , .





, . , , , . , -, , .





Neural network weights

, , . ,  0.1*X1 (W1 == 0.1)   X1. (, , , , , , -1 1). , 10 . , ,  1*X2 (W2 == 1).





, . , .





, , -? , ( - ). f() = .   - input - output ,  f, - .





, .  input  X   output  . , - , , , , .





, , ,   , -  i  .





 label  . , , -  3,  label = โ€œ โ€, , . , , , .





. โ€œ !โ€ . -, , , ?





, . , ?





 thecodingtrain, . , .





, . .





, , ( ). .





? , . - , . . . , , .





, .  score, .





. , , () , , , , . , , , .





, , ,   raid shadow legends.  dino game   google chrome. , , ?





Dino game

 p5.js. , , . 5 : setup, , ;  draw - , , .





? , , , . , , .





- , , . . .





class Cactus {
  constructor() {}
}

class Dino {
  constructor() {}
}
      
      



, - - ( - , ), . ? , , , -  GameObject,  onTick, . , , . .





...

onTick(cb = () => { }) {
  cb(this);
}

...
      
      



, , . ,  , , .





(, , ). , . , : - , , , , , , . ,  , .





switch (this.state) {
  case DinoStateEnum.run: break;
  case DinoStateEnum.jump: {
    this.currH += this.jumpSpeed;

    if (this.currH == this.maxH) {
      this.state = DinoStateEnum.fall;
    }

    break;
  }
  case DinoStateEnum.fall: {
    this.currH -= this.jumpSpeed;

    if (this.currH == 0) {
      this.state = DinoStateEnum.run;
    }

    break;
  }
}
      
      



, . , . . .





function updateCactuses() {
  const copy = cactuses.slice();

  for (let i = 0; i < copy.length; i++) {
    let c = copy[i];

    c.onTick(cactus => {
      drawCactus(cactus)

      cactus.currDistance -= dinoVelocitySlider.value();

      if (cactus.currDistance + cactusW < initialDinoW && !cactus.passDinoPosition) {
        updateDinoScore()

        cactus.passDinoPosition = true;
      }

      if (cactus.currDistance < 0) {
        cactuses.splice(i, 1);
      }
    })
  }
}
      
      



, ,   .





 tensorflowjs  , - . , . .





<script
  src="https://cdn.jsdelivr.net/npm/@tensorflow/tfjs@2.0.0/dist/tf.min.js">
</script>

<script>
  tf.setBackend('cpu') // tf  
</script>
      
      



, ? . : . , ?





, . , , . - . , . , , , . , .





, . . , . , ?





, - . , , . ( , , , ).





, , . ? .





? - 200-300 , . , (best score) , , . , . . ().





, , , .





  .





  • - .





  • C - .





  • - , .





  , :





  • T  .





  • .





  • .





  • , .





4 .





8 . 2, :  .





:





createModel() {
  const model = tf.sequential();

  const hiddenLayer = tf.layers.dense({
    units: this.hidden_nodes, // -     (8)
    inputShape: [this.input_nodes], // -     (4)
    activation: "sigmoid" //  
  });

  model.add(hiddenLayer);

  const outputLayer = tf.layers.dense({
    units: this.output_nodes, // -     (2)
    activation: "sigmoid"
  });

  model.add(outputLayer);

  return model;
}
      
      



 sequential()  . , . - , . . ,  sigmoid.





, , - ,  tensorflow  .





, . , .





predict(inputs) {
  return tf.tidy(() => {
    const xs = tf.tensor([inputs]); //     ( )

    const ys = this.model.predict(xs); //  

    const output = ys.dataSync(); //    

    return output;
  });
}
      
      



 tensorflow  ,  tensor ( ) , , , ,  tidy.





tensorflow  , , . , , . ( , ). 2, 2 . , , , , . ,  output[0] > output[1], .





 dino npc.





- , , .





, - .





function drawDino(dino) {
  if (dino.isDead) return;

  if (dino.state != DinoStateEnum.run) {
    //   ,      
    image(dino2, initialDinoW, initialDinoH - dino.currH, dinoW, dinoH); // 5      
  } else if (iteration % 7 == 0)
    //      
    image(dino1, initialDinoW, initialDinoH, dinoW, dinoH);
  else
    image(dino2, initialDinoW, initialDinoH, dinoW, dinoH);
}
      
      



. , , , , , . .





function updateGenerationIfNeeded() {
  if (dinos.every(d => d.isDead)) {
    cactuses = [];
    dinoVelocitySlider.value(initDinoVelocity);

    dinos = newGeneration(dinos)
  }
}
      
      



, , . , . .





, , . , .





: .





mutate(rate) {
  tf.tidy(() => {
    const weights = this.model.getWeights(); //   

    const mutatedWeights = [];

    for (let i = 0; i < weights.length; i++) {
      let tensor = weights[i]; //   -  
      let shape = weights[i].shape;
      let values = tensor.dataSync().slice();

      for (let j = 0; j < values.length; j++) {
        if (Math.random() < rate) { //    
          let w = values[j];
          values[j] = w + this.gaussianRandom(); //       -1  1
        }
      }

      let newTensor = tf.tensor(values, shape);
      mutatedWeights[i] = newTensor;
    }

    this.model.setWeights(mutatedWeights); //   
  });
}
      
      



, . . e .  fitness ( ).





const calculateFitness = (dinos) => {
  let sum = 0;

  dinos.map(d => sum += d.score)
  dinos.map(d => d.fitness = d.score / sum)
}
      
      



. . ( ), , .





:





const pickOne = (dinos) => { //       fitness
  let index = 0;
  let r = Math.random();

  while (r > 0) {
    r = r - dinos[index].fitness;
    index++;
  }

  index--;

  let dino = dinos[index] //   -   ,    rate

  const dinoBrain = dino.brain.copy();
  dinoBrain.mutate(0.2) //   

  let newDino = new Dino(dinoBrain) //    

  return newDino;
}
      
      



. , . , , .





for (let i = 0; i < TOTAL; i++) {
  newDinos.push(pickOne(oldDinos));
}

console.log(currentGeneration++);
return newDinos;
      
      



, , , , . 50+ . .





.





P.S. , welcome to PR's.  v_hadoocken








All Articles