Frontender escribe neuronas. Nivel de dificultad "Quiero manejar"

Tarde o temprano debe suceder

Tarde o temprano, el desarrollador front-end se cansa de jugar con sus frameworks, se cansa de molestar a sus colegas - backend, se cansa de jugar devops y comienza a mirar hacia el aprendizaje automático, los datos son ciencia y eso es todo. Afortunadamente, cada segundo curso para quienes quieran ingresar a la web contribuye a ello, gritando en todas las plataformas lo fácil que es. Yo también, harto de transferir datos de la base de datos a la API, y luego de la API a tablas y formularios, decidí tomarme unas breves vacaciones e intentar aplicar mis habilidades de front-end en aprendizaje automático. Afortunadamente, hay personas como  Daniel Shiffman  y  Charlie Gerard que, con su ejemplo, te ayudan a no renunciar a lo que empezaste cuando ves las primeras páginas con fórmulas matemáticas.





Si retrocedemos un poco y echamos un vistazo al título, veremos que no  copiaré de libros y  lanzaré palabras de alta tecnología tratando de explicar lo que hice.





Estoy casi seguro de que todos, al escuchar la frase "aprendizaje automático", se imaginan una imagen en la que muchas, muchas neuronas en varias capas y todas están entrelazadas. Entonces, esto no es una coincidencia. Esta es exactamente la razón por la que se concibió el aprendizaje automático: implementar el cerebro humano y sus redes neuronales en forma digital.





Diagrama de red neuronal
Diagrama de red neuronal

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





. , , - , . - () .





, ? , - , ( , , ).





- , - . .





- . . . .





“ ” - , , , , .





, . , , , . , -, , .





Pesos de la red neuronal

, , . ,  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