Frontender escreve neurônios. Nível de dificuldade "Eu quero lidar"

Mais cedo ou mais tarde isso deve acontecer

Mais cedo ou mais tarde, o desenvolvedor front-end se cansa de brincar com seus frameworks, se cansa de incomodar seus colegas - backend, se cansa de jogar devops e começa a olhar para o aprendizado de máquina, dados são ciência e isso é tudo. Felizmente, a cada dois cursos para quem quer entrar no site contribui para isso, gritando em todas as plataformas como é fácil. Eu também, farto de transferir dados do banco de dados para a API, e depois da API para tabelas e formulários, decidi tirar umas férias curtas e tentar aplicar minhas habilidades de front-end em aprendizado de máquina. Felizmente, existem pessoas como  Daniel Shiffman  e  Charlie Gerard que, por exemplo, ajudam a não desistir do que começaram após ver as primeiras páginas com fórmulas matemáticas.





Se voltarmos um pouco e darmos uma olhada no título, veremos que não  copiarei de livros para  lançar palavras de alta tecnologia tentando explicar o que fiz.





Tenho quase certeza de que todos, ouvindo a frase “aprendizado de máquina”, imaginam uma imagem em que muitos, muitos neurônios em várias camadas e todos estão interligados. Então, isso não é coincidência. É por isso que o aprendizado de máquina foi concebido - para implementar o cérebro humano e suas redes neurais na forma digital.





Diagrama de rede neural
Diagrama de rede neural

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





. , , - , . - () .





, ? , - , ( , , ).





- , - . .





- . . . .





“ ” - , , , , .





, . , , , . , -, , .





Pesos da rede neural

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