Neste codelab, você aprenderá como criar uma Máquina que Aprende simples, um classificador de imagens personalizadas que será treinado rapidamente no navegador usando o TensorFlow.js, uma biblioteca de machine learning avançada e flexível para JavaScript. Primeiro, você carregará e executará um modelo pré-treinado conhecido, chamado MobileNet, para classificação de imagens no navegador. Em seguida, você usará uma técnica chamada "aprendizado por transferência", que inicializa nosso treinamento com o modelo MobileNet pré-treinado e o personaliza para treinar para seu aplicativo.
Este codelab não abordará a teoria por trás do aplicativo de Máquina que Aprende. Caso esteja curioso sobre isso, confira este tutorial.
Você aprenderá a fazer o seguinte
- Como carregar um modelo MobileNet pré-treinado e fazer uma previsão sobre novos dados
 - Como fazer previsões pela webcam
 - Como usar ativações intermediárias do MobileNet para fazer aprendizado por transferência em um novo conjunto de classes que você define dinamicamente com a webcam
 
Então, vamos começar!
Para concluir este codelab, você precisará dos seguintes requisitos:
- Uma versão recente do Chrome ou de outro navegador moderno.
 - Um editor de texto executado localmente na sua máquina ou na Web por meio de algo como Codepen ou Glitch.
 - Conhecimento sobre HTML, CSS, JavaScript e Chrome DevTools (ou as DevTools do seu navegador preferido).
 - Conhecimento conceitual de alto nível sobre redes neurais. Se você precisar de uma introdução ou revisão, assista a este vídeo da 3blue1brown ou este vídeo sobre aprendizado profundo em JavaScript por Ashi Krishnan (links em inglês).
 
Abra index.html em um editor e adicione este conteúdo:
<html>
  <head>
    <!-- Load the latest version of TensorFlow.js -->
    <script src="https://cdn.jsdelivr.net/npm/@tensorflow/tfjs"></script>
    <script src="https://cdn.jsdelivr.net/npm/@tensorflow-models/mobilenet"></script>
  </head>
  <body>
    <div id="console"></div>
    <!-- Add an image that we will use to test -->
    <img id="img" crossorigin src="https://i.imgur.com/JlUvsxa.jpg" width="227" height="227"/>
    <!-- Load index.js after the content of the page -->
    <script src="index.js"></script>
  </body>
</html>
Em seguida, abra/crie o arquivo index.js em um editor de código e inclua o seguinte código:
let net;
async function app() {
  console.log('Loading mobilenet..');
  // Load the model.
  net = await mobilenet.load();
  console.log('Successfully loaded model');
  // Make a prediction through the model on our image.
  const imgEl = document.getElementById('img');
  const result = await net.classify(imgEl);
  console.log(result);
}
app();
Para executar a página da Web, basta abrir index.html em um navegador da Web. Se você estiver usando o Console do Cloud, basta atualizar a página de visualização.
Você verá uma imagem de um cachorro e, no Console JavaScript nas Ferramentas para desenvolvedores, as principais previsões do MobileNet. O download do modelo pode demorar um pouco.
A imagem foi classificada corretamente?
Vale lembrar que isso também funcionará em um celular.
Agora, vamos tornar esse processo mais interativo e em tempo real. Vamos configurar a webcam para fazer previsões sobre imagens que chegam por ela.
Primeiro configure o elemento de vídeo da webcam. Abra o arquivo index.html, adicione a seguinte linha na seção <body> e exclua a tag <img> que usamos para carregar a imagem do cachorro:
<video autoplay playsinline muted id="webcam" width="224" height="224"></video>
Abra o arquivo index.js e adicione o webcamElement ao topo do arquivo
const webcamElement = document.getElementById('webcam');
Agora, na função app() que você adicionou antes, é possível remover a previsão por meio da imagem e, em vez disso, criar um loop infinito que faz previsões pelo elemento da webcam.
async function app() {
  console.log('Loading mobilenet..');
  // Load the model.
  net = await mobilenet.load();
  console.log('Successfully loaded model');
  // Create an object from Tensorflow.js data API which could capture image
  // from the web camera as Tensor.
  const webcam = await tf.data.webcam(webcamElement);
  while (true) {
    const img = await webcam.capture();
    const result = await net.classify(img);
    document.getElementById('console').innerText = `
      prediction: ${result[0].className}\n
      probability: ${result[0].probability}
    `;
    // Dispose the tensor to release the memory.
    img.dispose();
    // Give some breathing room by waiting for the next animation frame to
    // fire.
    await tf.nextFrame();
  }
}
Se você abrir o console na página da Web, verá uma previsão do MobileNet com probabilidade de cada frame coletado na webcam.
Isso pode não ser muito intuitivo porque o conjunto de dados do ImageNet não parece muito com imagens que normalmente apareceriam em uma webcam. Uma maneira de testar isso é segurando uma foto do seu cachorro na frente da câmera do laptop.
Agora, vamos tornar esse modelo mais útil. Criaremos um classificador de objeto personalizado de três classes usando a webcam. Faremos uma classificação por meio do MobileNet, mas desta vez usaremos uma representação interna (ativação) do modelo para uma determinada imagem de webcam e a usaremos para classificação.
Usaremos um módulo chamado "K-Nearest Neighbors Classifier", que permite colocar imagens da webcam (na verdade, as ativações do MobileNet) em diferentes categorias (ou "classes") e, quando o usuário solicitar uma previsão, basta escolher a classe que tem a ativação mais semelhante à da previsão que está sendo realizada.
Adicione uma importação do KNN Classifier ao final das importações na tag <head> de index.html. Você ainda precisará do MobileNet, então não remova essa importação:
...
<script src="https://cdn.jsdelivr.net/npm/@tensorflow-models/knn-classifier"></script>
...
Adicione três botões para cada um dos botões em index.html abaixo do elemento de vídeo. Esses botões serão usados para adicionar imagens de treinamento ao modelo.
...
<button id="class-a">Add A</button>
<button id="class-b">Add B</button>
<button id="class-c">Add C</button>
...
Na parte superior de index.js, crie o classificador:
const classifier = knnClassifier.create();
Atualize a função do app:
async function app() {
  console.log('Loading mobilenet..');
  // Load the model.
  net = await mobilenet.load();
  console.log('Successfully loaded model');
  // Create an object from Tensorflow.js data API which could capture image
  // from the web camera as Tensor.
  const webcam = await tf.data.webcam(webcamElement);
  // Reads an image from the webcam and associates it with a specific class
  // index.
  const addExample = async classId => {
    // Capture an image from the web camera.
    const img = await webcam.capture();
    // Get the intermediate activation of MobileNet 'conv_preds' and pass that
    // to the KNN classifier.
    const activation = net.infer(img, true);
    // Pass the intermediate activation to the classifier.
    classifier.addExample(activation, classId);
    // Dispose the tensor to release the memory.
    img.dispose();
  };
  // When clicking a button, add an example for that class.
  document.getElementById('class-a').addEventListener('click', () => addExample(0));
  document.getElementById('class-b').addEventListener('click', () => addExample(1));
  document.getElementById('class-c').addEventListener('click', () => addExample(2));
  while (true) {
    if (classifier.getNumClasses() > 0) {
      const img = await webcam.capture();
      // Get the activation from mobilenet from the webcam.
      const activation = net.infer(img, 'conv_preds');
      // Get the most likely class and confidence from the classifier module.
      const result = await classifier.predictClass(activation);
      const classes = ['A', 'B', 'C'];
      document.getElementById('console').innerText = `
        prediction: ${classes[result.label]}\n
        probability: ${result.confidences[result.label]}
      `;
      // Dispose the tensor to release the memory.
      img.dispose();
    }
    await tf.nextFrame();
  }
}
Agora, ao carregar a página index.html, você pode usar objetos comuns ou gestos faciais/corporais para capturar imagens para cada uma das três classes. Cada vez que você clicar em um dos botões "Adicionar", uma imagem é adicionada à classe como exemplo de treinamento. Enquanto você faz isso, o modelo continua fazendo previsões sobre imagens de webcam recebidas e mostrando os resultados em tempo real.
Tente adicionar outra classe que não represente nenhuma ação.
Neste codelab, você implementou um app da Web de machine learning simples usando o TensorFlow.js. Você carregou e usou um modelo MobileNet pré-treinado para classificar imagens da webcam. Depois, você personalizou o modelo para classificar as imagens em três categorias personalizadas.
Acesse js.tensorflow.org para ver mais exemplos e demonstrações com código para saber como você pode usar o TensorFlow.js nos seus aplicativos.