Olá pessoal, colegas!
Talvez os fãs da biblioteca Tensorflow, que já notaram
este livro em nossa pré-encomenda, também tenham analisado atentamente as possibilidades de aprendizado de máquina e profundo no navegador, principalmente porque o próprio
François Schollet não ignorou o tópico. Convidamos os interessados no gato, que informa como as imagens são reconhecidas usando a biblioteca Tensorflow.js.
O TensorFlow.js é uma nova versão da popular biblioteca de código aberto que enriquece o JavaScript com recursos de aprendizado profundo. Os desenvolvedores agora podem definir, treinar e executar modelos usando a
API da biblioteca de alto nível .
Graças aos
modelos pré-treinados, os desenvolvedores agora podem resolver facilmente tarefas complexas, como
reconhecimento de padrões ,
geração de música ou
determinação de posições humanas em apenas algumas linhas de JavaScript.
O Tensorflow.js começou como uma biblioteca front-end para trabalhar em um navegador, mas este ano foi adicionado
suporte experimental ao Node.js. Portanto, o TensorFlow.js também pode ser usado em aplicativos de back-end JavaScript, o que evita completamente a necessidade de recorrer ao Python.
Lendo sobre esta biblioteca, decidi experimentá-la em uma tarefa simples ...Use TensorFlow.js para reconhecimento visual de imagens em imagens ao usar JavaScript do Node.js.
Infelizmente, os
exemplos de documentação e
código descrevem principalmente o uso dessa biblioteca no navegador.Os
utilitários de projeto projetados para simplificar o carregamento e o uso de modelos pré-treinados no momento da redação não suportavam o Node.js. Eu tive que gastar muito tempo para ler bem as fontes Typescript desta biblioteca.
No entanto, depois de alguns dias de sacudidela, eu ainda consegui! Viva!
Antes de passar para uma análise detalhada do código, vamos falar sobre outras implementações da biblioteca TensorFlow.TensorflowO TensorFlow é uma biblioteca de software livre para aplicativos de aprendizado de máquina. O TensorFlow pode ser usado para criar redes neurais e implementar outros algoritmos de aprendizado profundo.
Esta é uma biblioteca lançada pelo Google em novembro de 2015, originalmente
escrita em Python . Para treinamento e avaliação de modelos criados, ele usa cálculos em uma CPU ou GPU. Inicialmente, essa biblioteca foi criada para funcionar em servidores de alto desempenho usando GPUs com muitos recursos.
Atualizações recentes tornaram possível otimizar essa biblioteca e usá-la em ambientes com recursos mais limitados - por exemplo, em dispositivos móveis e navegadores da web.
TensorFlow LiteO Tensorflow Lite , a versão lite desta biblioteca para dispositivos móveis e sistemas embarcados, foi lançado em maio de 2017. Juntamente com ele, é fornecido um novo conjunto de modelos profundos pré-treinados para tarefas relacionadas ao reconhecimento de padrões; essa coleção é chamada
MobileNet . Os modelos MobileNet foram projetados especificamente para operação eficiente em ambientes com uma quantidade limitada de recursos, como dispositivos móveis.
TensorFlow.js
Após o Tensorflow Lite, o TensorFlow.js foi
anunciado em março de 2018. Esta versão da biblioteca foi projetada para ser executada em um navegador e é baseada em um projeto anterior chamado
deeplearn.js . O WebGL fornece acesso de GPU à biblioteca. Os desenvolvedores usam a API JavaScript para treinar, carregar e executar modelos.
Posteriormente, o TensorFlow.js foi expandido para funcionar com o Node.js, o
add tfjs-node
biblioteca do tfjs-node
é usado para isso.
Importar modelos existentes para o TensorFlow.jsOs modelos TensorFlow e Keras prontos para execução podem ser executados usando a biblioteca TensorFlow.js. Antes de executar o modelo, você deve converter para um novo formato usando
esta ferramenta . Modelos pré-treinados e transformados para classificar imagens, definir poses e detectar vizinhos k-mais próximos
estão disponíveis no Github .
Usando TensorFlow.js com Node.jsInstalar bibliotecas do TensorFlow
O TensorFlow.js pode ser instalado a partir do
registro do
NPM .
npm install @tensorflow/tfjs @tensorflow/tfjs-node // ... npm install @tensorflow/tfjs @tensorflow/tfjs-node-gpu
Ambas as extensões do Node.js usam dependências nativas, que serão compiladas sob demanda.
Download de bibliotecas do TensorFlowA API JavaScript para Tensorflow é fornecida na biblioteca principal. Nenhuma API de extensão é fornecida nos módulos de extensão que oferecem suporte ao Node.js.
const tf = require('@tensorflow/tfjs')
Download dos modelos TensorFlowO TensorFlow.js fornece uma
biblioteca NPM (
tfjs-models
) que simplifica o carregamento de
tfjs-models
pré-treinados e transformados para
classificar imagens ,
definir poses e
detectar os vizinhos mais próximos .
O
modelo de classificação de imagens da
MobileNet é uma rede neural profunda treinada para distinguir entre
1000 classes diferentes de imagens .
No arquivo LEIA-ME para o projeto, o código a seguir é usado
como exemplo , usado para carregar o modelo.
import * as mobilenet from '@tensorflow-models/mobilenet';
Um dos primeiros problemas que encontrei é que esse código não funciona com o Node.js.
Error: browserHTTPRequest is not supported outside the web browser.
Após examinar o
código fonte , vemos que a biblioteca mobilenet é um invólucro para a classe
tf.Model
. Quando chamado, o método
load()
baixa automaticamente os arquivos de modelo necessários localizados em um endereço HTTP externo e instancia o modelo TensorFlow.
A extensão Node.js no momento da gravação ainda não suportava solicitações HTTP para recuperação de modelo dinâmico. Tudo o que restava era carregar manualmente os modelos no sistema de arquivos.
No entanto, depois de ler o código fonte da biblioteca, encontrei uma solução alternativa ...Fazendo Download de Modelos do Sistema de ArquivosSe a classe MobileNet for criada manualmente, não será possível chamar o método de
load
do módulo, mas reescrever o
path
variável gerado automaticamente
path
contém o endereço HTTP do modelo, substituindo esse endereço pelo caminho local no sistema de arquivos. Depois disso, quando o método
load
for chamado na instância da classe,
a classe
loader do sistema de arquivos será acionada; nesse caso, nos recusamos a usar um downloader HTTP baseado em navegador.
const path = "mobilenet/model.json" const mn = new mobilenet.MobileNet(1, 1); mn.path = `file://${path}` await mn.load()
Legal, tudo funciona!
Mas de onde vêm os arquivos de modelo?
Modelos MobileNetModelos para TensorFlow.js consistem em dois tipos de arquivos: um arquivo de configuração de modelo armazenado no formato JSON e os pesos do modelo armazenados no formato binário. Os pesos do modelo geralmente são fragmentados em várias partes para otimizar o cache do navegador.
Tendo considerado o
código de download automático dos modelos MobileNet, vemos que os modelos, suas configurações e fragmentos de peso são extraídos do contêiner público no seguinte endereço.
https://storage.googleapis.com/tfjs-models/tfjs/mobilenet_v${version}_${alpha}_${size}/
Os parâmetros do modelo na URL descrevem as versões do modelo listadas
aqui . A precisão da classificação resultante também é exibida na mesma página.
O código fonte indica que apenas os modelos do MobileNet v1 podem ser baixados usando a
tensorflow-models/mobilenet
.
O código de extração HTTP baixa o arquivo
model.json
do local de armazenamento e, em seguida, seleciona recursivamente todos os fragmentos de modelos com pesos referenciados. Esses são arquivos no formato
groupX-shard1of1
.
Download manual de modelosSe desejar salvar todos os arquivos de modelo no sistema de arquivos, faça o seguinte: extraia o arquivo de configuração do modelo, analise a sintaxe de todos os arquivos ponderados mencionados no arquivo de configuração e faça o download manual de cada arquivo ponderado.
Eu usaria o módulo MobileNet V1 com um valor alfa de 1,0 e uma imagem de 224 pixels . Então, recebo o
seguinte URL para o arquivo de configuração do modelo.
https://storage.googleapis.com/tfjs-models/tfjs/mobilenet_v1_1.0_224/model.json
Depois que o arquivo é baixado localmente, você pode usar a
ferramenta jq
para analisar os nomes de todos os arquivos ponderados.
$ cat model.json | jq -r ".weightsManifest[].paths[0]" group1-shard1of1 group2-shard1of1 group3-shard1of1 ...
Usando a ferramenta
sed
, você pode prefixar o nome de cada elemento HTTP com uma URL para gerar uma URL para cada arquivo de peso.
$ cat model.json | jq -r ".weightsManifest[].paths[0]" | sed 's/^/https:\/\/storage.googleapis.com\/tfjs-models\/tfjs\/mobilenet_v1_1.0_224\//' https:
Os comandos
parallel
e
curl
permitem baixar todos esses arquivos no meu diretório local.
cat model.json | jq -r ".weightsManifest[].paths[0]" | sed 's/^/https:\/\/storage.googleapis.com\/tfjs-models\/tfjs\/mobilenet_v1_1.0_224\//' | parallel curl -O
Classificação da imagemEste código de exemplo fornecido com o TensorFlow.js demonstra como retornar o resultado da classificação da imagem.
const img = document.getElementById('img');
Isso não funciona no Node.js devido à falta de suporte do DOM.
O método classify
aceita vários elementos DOM (
canvas
,
video
,
image
) e extrai e converte automaticamente os bytes "de imagem" desses elementos na classe
tf.Tensor3D
, usada como entrada de modelo. Como alternativa, a
tf.Tensor3D
pode ser transmitida diretamente.
Decidi não tentar usar um pacote externo para simular um elemento DOM manualmente, mas achei que tf.Tensor3D
mais fácil de montar manualmente .
Geramos Tensor3D a partir da imagemLendo o
código fonte do método usado para converter elementos DOM em classes Tensor3D, descobrimos que os seguintes parâmetros de entrada são usados para gerar a classe Tensor3D.
const values = new Int32Array(image.height * image.width * numChannels);
pixels
é uma matriz bidimensional do tipo
(Int32Array)
contém uma lista seqüencial de valores de canal para cada pixel.
numChannels
é o número de valores de canal por pixel.
Criando valores de entrada para JPEGA biblioteca jpeg-js
é um codificador / decodificador JPEG para Node.js escrito em JavaScript puro. Usando esta biblioteca, você pode extrair valores RGB para cada pixel.
const pixels = jpeg.decode(buffer, true);
Como resultado, obtemos um Uint8Array com quatro valores de canal (
RGBA
) para cada pixel (
width * height
). O modelo MobileNet usa apenas três canais de cores (
RGB
) para classificação, o canal alfa é ignorado. Esse código converte uma matriz de quatro canais em uma versão verdadeira de três canais.
const numChannels = 3; const numPixels = image.width * image.height; const values = new Int32Array(numPixels * numChannels); for (let i = 0; i < numPixels; i++) { for (let channel = 0; channel < numChannels; ++channel) { values[i * numChannels + channel] = pixels[i * 4 + channel]; } }
Requisitos de entrada para modelos MobileNetO
modelo MobileNet usado aqui classifica imagens de 224 pixels de altura e largura. Os tensores de entrada devem conter valores de ponto flutuante no intervalo de -1 a 1 para cada um dos três valores de canal de cada pixel.
Os valores de entrada para imagens com uma dimensão diferente devem ser convertidos no tamanho correto antes da classificação. Além disso, os valores de pixel obtidos do decodificador JPEG estão no intervalo de 0 a 255, e não de -1 a 1. Esses valores também precisam ser convertidos antes da classificação.
O TensorFlow.js possui métodos de biblioteca para simplificar esse processo, mas, melhor ainda, existe uma
tfjs-models/mobilenet
que resolve automaticamente esse problema !O desenvolvedor pode transmitir Tensor3Ds de entrada do tipo
int32
, bem como várias dimensões para o método
classify
, que converte os valores de entrada no formato correto antes da classificação. Ou seja, não temos nada a fazer aqui. Ótimo!
Obtendo previsõesOs modelos MobileNet da Tensorflow aprendem a reconhecer objetos das
1000 classes mais importantes do
conjunto de dados
do ImageNet . Na saída do modelo, forneça valores probabilísticos caracterizando quais são as chances de encontrar esses objetos na imagem classificada.
Uma lista completa de classes treinadas para o modelo usado está neste arquivo .
A
tfjs-models/mobilenet
oferece o método
classify
na classe
MobileNet
, que retorna o top-X das classes mais prováveis, com base no que é mostrado na figura.
const predictions = await mn_model.classify(input, 10);
predictions
é uma matriz de X classes e probabilidades no seguinte formato.
{ className: 'panda', probability: 0.9993536472320557 }
ExemploEntão, descobrimos como usar a biblioteca TensorFlow.js e os modelos MobileNet no Node.js, e agora vamos ver como esse script classifica a imagem especificada como um argumento da linha de comando.
Código fonteSalve este arquivo de script e o descritor de pacotes nos arquivos locais.
{ "name": "tf-js", "version": "1.0.0", "main": "script.js", "license": "MIT", "dependencies": { "@tensorflow-models/mobilenet": "^0.2.2", "@tensorflow/tfjs": "^0.12.3", "@tensorflow/tfjs-node": "^0.1.9", "jpeg-js": "^0.3.4" } }
const tf = require('@tensorflow/tfjs') const mobilenet = require('@tensorflow-models/mobilenet'); require('@tensorflow/tfjs-node') const fs = require('fs'); const jpeg = require('jpeg-js'); const NUMBER_OF_CHANNELS = 3 const readImage = path => { const buf = fs.readFileSync(path) const pixels = jpeg.decode(buf, true) return pixels } const imageByteArray = (image, numChannels) => { const pixels = image.data const numPixels = image.width * image.height; const values = new Int32Array(numPixels * numChannels); for (let i = 0; i < numPixels; i++) { for (let channel = 0; channel < numChannels; ++channel) { values[i * numChannels + channel] = pixels[i * 4 + channel]; } } return values } const imageToInput = (image, numChannels) => { const values = imageByteArray(image, numChannels) const outShape = [image.height, image.width, numChannels]; const input = tf.tensor3d(values, outShape, 'int32'); return input } const loadModel = async path => { const mn = new mobilenet.MobileNet(1, 1); mn.path = `file://${path}` await mn.load() return mn } const classify = async (model, path) => { const image = readImage(path) const input = imageToInput(image, NUMBER_OF_CHANNELS) const mn_model = await loadModel(model) const predictions = await mn_model.classify(input) console.log('classification results:', predictions) } if (process.argv.length !== 4) throw new Error('incorrect arguments: node script.js <MODEL> <IMAGE_FILE>') classify(process.argv[2], process.argv[3])
TesteFaça o download dos arquivos de modelo para o diretório mobilenet seguindo as instruções acima.
Definir dependências do projeto usando o NPM
npm install
Faça o download do arquivo JPEG de amostra para classificação
wget http://bit.ly/2JYSal9 -O panda.jpg

Execute o script, cujos argumentos serão o arquivo de modelo e a imagem de entrada.
node script.js mobilenet/model.json panda.jpg
Se tudo funcionou corretamente, a seguinte saída deve aparecer no console.
classification results: [ { className: 'giant panda, panda, panda bear, coon bear', probability: 0.9993536472320557 } ]
A imagem está corretamente classificada como contendo um panda com uma probabilidade de 99,93%!
ConclusãoA biblioteca TensorFlow.js abre oportunidades profundas de aprendizado para desenvolvedores de JavaScript. O uso de modelos pré-treinados com a biblioteca TensorFlow.js permite criar facilmente em aplicativos JavaScript novos recursos para resolver problemas complexos de aprendizado de máquina, com esforço mínimo e código conciso.
A biblioteca TensorFlow.js foi criada exclusivamente para trabalhar em um navegador, mas agora interage com o Node.js, embora nem todas as ferramentas e utilitários suportem esse novo tempo de execução. Tendo mexido com a biblioteca por vários dias, aprendi a usá-la com os modelos MobileNet para reconhecimento visual de imagens de um arquivo local.