TensorFlow.js: converter um SavedModel do Python para o formato TensorFlow.js

1. Introdução

Você já deu seus primeiros passos com o TensorFlow.js, testou nossos modelos pré-criados ou até criou os seus próprios, mas viu algumas pesquisas inovadoras em Python, e ficou curioso para saber se ela será executada no navegador da Web para transformar a ideia que você tinha se tornado uma realidade para milhões de pessoas de maneira escalonável. Soa familiar? Se esse for o caso, este é o codelab para você.

A equipe do TensorFlow.js criou uma ferramenta conveniente para converter modelos que estão no formato SavedModel para TensorFlow.js por meio de um conversor de linha de comando. Assim, você pode aproveitar esses modelos com o alcance e a escala da Web.

O que você vai aprender

Neste codelab, você vai aprender a usar o conversor de linha de comando do TensorFlow.js para portar um SavedModel gerado pelo Python para o formato model.json necessário para execução no lado do cliente em um navegador da Web.

Especificamente:

  • Como criar um modelo simples de ML em Python e salvá-lo no formato exigido pelo conversor do TensorFlow.js.
  • Como instalar e usar o conversor do TensorFlow.js no SavedModel exportado do Python.
  • Use os arquivos resultantes da conversão no seu aplicativo da Web JS.
  • Saiba o que fazer quando algo der errado (nem todos os modelos serão convertidos) e quais opções você tem.

Imagine ser capaz de pegar algumas pesquisas recém-lançadas e disponibilizar esse modelo para milhões de desenvolvedores de JS globalmente. Ou talvez você mesmo use isso em sua própria criação, que qualquer pessoa no mundo pode ver se ele for executado no navegador da Web, uma vez que nenhuma dependência complexa ou configuração de ambiente é necessária. Pronto para começar? Vamos lá!

Compartilhe o que você converteu com a gente.

Você pode usar o que aprendemos hoje para tentar converter alguns dos seus modelos favoritos do Python. Se você conseguir fazer isso e criar um site de demonstração funcional do modelo em ação, marque-nos nas redes sociais usando a hashtag #MadeWithTFJS para que seu projeto tenha a chance de aparecer no nosso blog do TensorFlow ou até mesmo em futuros eventos de demonstração. Adorariamos ver mais pesquisas incríveis sendo adaptadas para a Web e permitir que um número maior de pessoas usasse esses modelos de maneiras inovadoras ou criativas, como este ótimo exemplo.

2. O que é o TensorFlow.js?

1aee0ede85885520.png

O TensorFlow.js é uma biblioteca de machine learning de código aberto que pode ser executada em qualquer lugar com JavaScript. Ele é baseado na biblioteca original do TensorFlow escrita em Python e tem como objetivo recriar essa experiência de desenvolvedor e o conjunto de APIs para o ecossistema do JavaScript.

Onde pode ser usado?

Devido à portabilidade do JavaScript, agora é possível escrever em um idioma e realizar machine learning em todas as seguintes plataformas com facilidade:

  • Lado do cliente no navegador da Web usando JavaScript básico
  • lado do servidor e até dispositivos de IoT, como o Raspberry Pi, que usam Node.js
  • Aplicativos para computador que usam o Electron
  • Aplicativos nativos para dispositivos móveis que usam o React Native

O TensorFlow.js também oferece suporte a vários back-ends em cada um desses ambientes, ou seja, os ambientes reais baseados em hardware em que ele pode executar, como a CPU ou o WebGL, por exemplo. Um "back-end" neste contexto não significa um ambiente no lado do servidor (o back-end para execução pode ser no lado do cliente no WebGL, por exemplo) para garantir a compatibilidade e manter tudo funcionando rapidamente. Atualmente, o TensorFlow.js é compatível com:

  • Execução de WebGL na placa de vídeo do dispositivo (GPU): essa é a maneira mais rápida de executar modelos maiores (com mais de 3 MB) com aceleração de GPU.
  • Execução do Web Assembly (WASM) na CPU: para melhorar o desempenho da CPU em vários dispositivos, incluindo smartphones das gerações mais antigas, por exemplo. Isso é mais adequado para modelos menores (com menos de 3 MB), que podem ser executados mais rapidamente na CPU com o WASM do que com o WebGL, devido à sobrecarga do upload de conteúdo para um processador gráfico.
  • Execução da CPU: o substituto não deverá estar disponível para nenhum dos outros ambientes. Este é o mais lento dos três, mas está sempre lá para você.

Observação:é possível forçar um desses back-ends se você souber em qual dispositivo vai executar a execução. Também é possível deixar o TensorFlow.js decidir por você se você não especificar isso.

Superpoderes do lado do cliente

Executar o TensorFlow.js no navegador da Web da máquina cliente pode gerar vários benefícios que valem a pena considerar.

Privacidade

Você pode treinar e classificar os dados na máquina cliente sem nunca enviá-los a um servidor da Web de terceiros. Em alguns casos, isso pode ser um requisito para obedecer à legislação local, como o GDPR, ou ao processar dados que o usuário quer manter na máquina e não enviar a terceiros.

Speed

Como você não precisa enviar dados a um servidor remoto, a inferência (o ato de classificar os dados) pode ser mais rápida. Melhor ainda, você tem acesso direto aos sensores do dispositivo, como a câmera, o microfone, o GPS, o acelerômetro, entre outros, caso o usuário permita o acesso.

Alcance e escala

Com um clique, qualquer pessoa no mundo pode clicar em um link que você enviou, abrir a página da Web no navegador e utilizar o que você criou. Para usar o sistema de machine learning, você não precisa de uma configuração complexa do Linux no lado do servidor com drivers CUDA e muito mais.

Custo

A ausência de servidores significa que você só precisa pagar por uma CDN para hospedar seus arquivos HTML, CSS, JS e de modelo. O custo de uma CDN é muito mais barato do que manter um servidor (possivelmente com uma placa de vídeo conectada) funcionando 24 horas por dia, 7 dias por semana.

Recursos do lado do servidor

Utilizar a implementação do TensorFlow.js em Node.js ativa os recursos a seguir.

Suporte completo para CUDA

No lado do servidor, para acelerar a placa gráfica, é necessário instalar os drivers NVIDIA CUDA para permitir que o TensorFlow funcione com a placa de vídeo (ao contrário do navegador que usa WebGL. Não é necessário instalar). No entanto, com o suporte total a CUDA, você aproveita ao máximo os recursos de nível mais baixo da placa de vídeo, o que agiliza o treinamento e a inferência. O desempenho está em paridade com a implementação do TensorFlow em Python, já que ambos compartilham o mesmo back-end em C++.

Tamanho do modelo

Para modelos modernos de pesquisa, você pode estar trabalhando com modelos muito grandes, talvez em gigabytes. No momento, esses modelos não podem ser executados no navegador da web devido às limitações de uso da memória por guia do navegador. Para executar esses modelos maiores, use o Node.js no seu próprio servidor com as especificações de hardware necessárias para executar esse modelo com eficiência.

I/T

O Node.js é compatível com computadores de placa única conhecidos, como o Raspberry Pi (link em inglês), o que significa que você também pode executar modelos do TensorFlow.js nesses dispositivos.

Speed

O Node.js é escrito em JavaScript, o que significa que ele se beneficia da compilação no momento certo. Isso significa que talvez você note ganhos de desempenho ao usar o Node.js, já que ele será otimizado no tempo de execução, especialmente para qualquer pré-processamento que você esteja fazendo. Um ótimo exemplo disso é este estudo de caso, que mostra como a Hugging Face usou o Node.js para dobrar o desempenho do modelo de processamento de linguagem natural.

Agora que você já conhece os conceitos básicos do TensorFlow.js, onde ele pode ser executado e alguns dos benefícios, vamos começar a usá-lo de forma prática.

3. Configurar o sistema

Para este tutorial, vamos usar o Ubuntu, uma distribuição Linux conhecida que muitas pessoas usam e que está disponível no Compute Engine do Google Cloud como uma imagem de base se você optar por acompanhar em uma máquina virtual baseada na nuvem.

No momento da gravação, podemos selecionar a imagem do Ubuntu 18.04.4 LTS ao criar uma nova instância do baunilha do Compute Engine, que é o que vamos usar. É claro que você pode usar um computador próprio ou até mesmo um sistema operacional diferente, mas as instruções e dependências de instalação podem variar de acordo com o sistema.

Como instalar o TensorFlow (versão do Python)

Agora, como você provavelmente está tentando converter algum modelo baseado em Python que encontrou / ou vai escrever, antes de exportarmos um "SavedModel" do Python, você precisa ter a versão Python do TensorFlow configurada na instância se o "SavedModel" ainda não está disponível para download.

Conecte-se por SSH à máquina na nuvem que você criou acima e digite o seguinte na janela do terminal:

Janela do terminal:

sudo apt update
sudo apt-get install python3

Isso garantirá que o Python 3 esteja instalado na máquina. O Python 3.4 ou superior precisa estar instalado para usar o TensorFlow.

Para verificar se a versão correta está instalada, digite o seguinte:

Janela do terminal:

python3 --version

Você verá uma saída indicando o número da versão, como Python 3.6.9. Se for exibido corretamente e a versão for superior a 3.4, estamos prontos para continuar.

Em seguida, instalaremos o PIP para Python 3, que é o gerenciador de pacotes do Python, e o atualizaremos. Tipo:

Janela do terminal:

sudo apt install python3-pip
pip3 install --upgrade pip

Mais uma vez, podemos verificar a instalação do pip3 via:

Janela do terminal:

pip3 --version

No momento da gravação, vemos pip 20.2.3 impresso no terminal depois da execução desse comando.

Antes de podermos instalar o TensorFlow, ele exige o pacote Python "setuptools" da versão 41.0.0 ou superior. Execute o comando a seguir para garantir que ele esteja atualizado para a versão mais recente:

Janela do terminal:

pip3 install -U setuptools

Por fim, instale o TensorFlow para Python:

Janela do terminal:

pip3 install tensorflow

Isso pode levar algum tempo. Portanto, aguarde até que a execução seja concluída.

Vamos conferir se o TensorFlow foi instalado corretamente. Crie um arquivo Python chamado test.py no seu diretório atual:

Janela do terminal:

nano test.py

Depois que o nano é aberto, podemos escrever um código Python para imprimir a versão do TensorFlow instalada:

test.py:

import tensorflow as tf
print(tf.__version__)

Pressione CTRL + O para gravar as mudanças no disco e CTRL + X para sair do editor nano.

Agora podemos executar este arquivo Python para conferir a versão do TensorFlow impressa na tela:

Janela do terminal:

python3 test.py

No momento da gravação, vemos 2.3.1 impresso no console para nossa versão do TensorFlow Python instalada.

4. Como criar um modelo Python

A próxima etapa deste codelab vai mostrar como criar um modelo Python simples para mostrar como salvar esse modelo treinado resultante no "SavedModel" para usar com nosso conversor de linha de comando do TensorFlow.js. O princípio seria semelhante para qualquer modelo Python que você estivesse tentando converter, mas devemos manter esse código simples para que todos possam entender.

Vamos editar o arquivo test.py que criamos na primeira seção e atualizar o código da seguinte forma:

test.py:

import tensorflow as tf
print(tf.__version__)

# Import NumPy - package for working with arrays in Python.
import numpy as np

# Import useful keras functions - this is similar to the
# TensorFlow.js Layers API functionality.
from tensorflow.keras import Sequential
from tensorflow.keras.layers import Dense

# Create a new dense layer with 1 unit, and input shape of [1].
layer0 = Dense(units=1, input_shape=[1])
model = Sequential([layer0])

# Compile the model using stochastic gradient descent as optimiser
# and the mean squared error loss function.
model.compile(optimizer='sgd', loss='mean_absolute_error')

# Provide some training data! Here we are using some fictional data 
# for house square footage and house price (which is simply 1000x the 
# square footage) which our model must learn for itself.
xs = np.array([800.0, 850.0, 900.0, 950.0, 980.0, 1000.0, 1050.0, 1075.0, 1100.0, 1150.0, 1200.0, 1250.0, 1300.0, 1400.0, 1500.0, 1600.0, 1700.0, 1800.0, 1900.0, 2000.0], dtype=float)

ys = np.array([800000.0, 850000.0, 900000.0, 950000.0, 980000.0, 1000000.0, 1050000.0, 1075000.0, 1100000.0, 1150000.0, 1200000.0,  1250000.0, 1300000.0, 1400000.0, 1500000.0, 1600000.0, 1700000.0, 1800000.0, 1900000.0, 2000000.0], dtype=float)

# Train the model for 500 epochs.
model.fit(xs, ys, epochs=500, verbose=0)

# Test the trained model on a test input value
print(model.predict([1200.0]))

# Save the model we just trained to the "SavedModel" format to the
# same directory our test.py file is located.
tf.saved_model.save(model, './')

Este código treinará uma regressão linear muito simples para aprender a estimar a relação entre as entradas de x e as saídas fornecidas. Depois, o modelo treinado resultante será salvo em disco. Verifique os comentários inline para saber mais detalhes sobre o que cada linha faz.

Se verificarmos nosso diretório depois de executar o programa (chamando python3 test.py), veremos alguns arquivos e pastas criados no diretório atual:

  • test.py
  • saved_model.pb
  • recursos
  • variables

Agora geramos os arquivos que precisam ser usados pelo conversor do TensorFlow.js para converter esse modelo e executá-lo no navegador.

5. Como converter o SavedModel para o formato TensorFlow.js

Instalar o conversor do TensorFlow.js

Para instalar o conversor, execute o seguinte comando:

Janela do terminal:

pip3 install tensorflowjs

Foi fácil.

Considerando que estávamos usando o conversor de linha de comando (tensorflowjs_converter), e não a versão do assistente mostrada acima, podemos chamar o comando a seguir para converter o modelo salvo que acabamos de criar e transmitir explicitamente os parâmetros ao conversor:

Janela do terminal:

tensorflowjs_converter \
    --input_format=keras_saved_model \
    ./ \
    ./predict_houses_tfjs

O que está acontecendo aqui? Primeiro, vamos chamar o binário tensorflowjs_converter que acabamos de instalar e especificar que estamos tentando converter um modelo salvo do Keras.

No código de exemplo acima, você vai notar que importamos o Keras e usamos as APIs de camadas de nível superior para criar o modelo. Se você não usou o Keras em seu código Python, use um formato de entrada diferente:

  • keras: para carregar o formato keras (tipo de arquivo HDF5)
  • tf_saved_model: para carregar o modelo que usa as APIs básicas do TensorFlow em vez do Keras.
  • tf_frozen_model: para carregar um modelo que contém pesos congelados.
  • tf_hub: para carregar um modelo gerado no hub do TensorFlow.

Saiba mais sobre esses outros formatos aqui.

Os próximos dois parâmetros especificam em qual pasta o modelo salvo está localizado. Na demonstração acima, especificamos o diretório atual e, por fim, especificamos para qual diretório queremos gerar nossa conversão, que especificamos acima como uma pasta chamada "predict_houses_tfjs". no diretório atual.

A execução do comando acima cria uma nova pasta no diretório atual chamada predict_houses_tfjs, que contém :

  • model.json
  • Grupo1-shard1of1.bin

Esses são os arquivos necessários para executar o modelo no navegador da Web. Salve esses arquivos, porque eles serão usados na próxima seção.

6. Como usar nosso modelo convertido no navegador

Hospedar os arquivos convertidos

Primeiro, precisamos colocar nossos arquivos model.json e *.bin que foram gerados em um servidor da Web para podermos acessá-los na nossa página da Web. Para esta demonstração, vamos usar o Glitch.com, para que você possa acompanhar facilmente. No entanto, se você tem formação em engenharia da Web, pode optar por acionar um servidor HTTP simples na sua instância atual do servidor Ubuntu. A escolha é sua.

Como fazer upload de arquivos para o Glitch

  1. Faça login no Glitch.com
  2. Use este link para clonar nosso projeto padrão do TensorFlow.js. Ele contém um esqueleto de arquivos html, css e js que importam a biblioteca do TensorFlow.js, pronta para uso.
  3. Clique em "Recursos". pasta no painel à esquerda.
  4. Clique em "Fazer o upload de um recurso" e selecione group1-shard1of1.bin para fazer o upload nesta pasta. Ele vai ficar assim após o upload: 25a2251c7f165184.png
  5. Se você clicar no arquivo group1-shard1of1.bin que acabou de enviar, poderá copiar o URL para o local dele. Copie este caminho agora como mostrado: 92ded8d46442c404.png
  6. Agora edite model.json usando seu editor de texto favorito na máquina local e pesquise (usando CTRL+F) o arquivo group1-shard1of1.bin que será mencionado em algum lugar.

Substitua esse nome de arquivo pelo URL que você copiou na etapa 5, mas exclua o https://cdn.glitch.com/ inicial gerado pela falha do caminho copiado.

Depois da edição, ele terá esta aparência (observe como o caminho principal do servidor foi removido para que apenas o nome de arquivo resultante enviado seja mantido): d5a338f2dc1f31d4.png 7. Agora salve e faça upload do arquivo model.json editado com falha clicando em "Recursos" e, em seguida, em "Fazer upload de um recurso" Botão (important). Se você não usar o botão físico e arrastar e soltar, ele será enviado como um arquivo editável em vez de no CDN, que não estará na mesma pasta, e o caminho relativo será assumido quando o TensorFlow.js tentar fazer o download dos arquivos binários de um determinado modelo. Se você tiver feito isso corretamente, dois arquivos vão aparecer na pasta assets, como estes: 51a6dbd5d3097ffc.png

Ótimo! Agora estamos prontos para usar nossos arquivos salvos com um código real no navegador.

Como carregar o modelo

Agora que hospedamos nossos arquivos convertidos, podemos criar uma página da Web simples para carregar esses arquivos e usá-los para fazer uma previsão. Abra script.js na pasta do projeto Glitch e substitua o conteúdo desse arquivo pelo seguinte após mudar o const MODEL_URL para apontar para o link Glitch.com gerado para o arquivo model.json que você enviou ao Glitch:

script.js:

// Grab a reference to our status text element on the web page.
// Initially we print out the loaded version of TFJS.
const status = document.getElementById('status');
status.innerText = 'Loaded TensorFlow.js - version: ' + tf.version.tfjs;

// Specify location of our Model.json file we uploaded to the Glitch.com CDN.
const MODEL_URL = YOUR MODEL.JSON URL HERE! CHANGE THIS!';
// Specify a test value we wish to use in our prediction.
// Here we use 950, so we expect the result to be close to 950,000.
const TEST_VALUE = 950.0

// Create an asynchronous function.
async function run() {
    // Load the model from the CDN.
    const model = await tf.loadLayersModel(MODEL_URL);

    // Print out the architecture of the loaded model.
    // This is useful to see that it matches what we built in Python.
    console.log(model.summary());

    // Create a 1 dimensional tensor with our test value.
    const input = tf.tensor1d([TEST_VALUE]);

    // Actually make the prediction.
    const result = model.predict(input);

    // Grab the result of prediction using dataSync method
    // which ensures we do this synchronously.
    status.innerText = 'Input of ' + TEST_VALUE + 
        'sqft predicted as $' + result.dataSync()[0];
}

// Call our function to start the prediction!
run();

Executar o código acima depois de mudar a constante MODEL_URL para apontar para o caminho model.json resulta em uma saída mostrada abaixo.

c5e8457213058ec3.png

Se inspecionarmos o console do navegador da Web (pressione F12 para abrir as ferramentas do desenvolvedor no navegador), também poderemos ver a descrição do modelo carregado que imprime:

35e79d70dbd66f27.png

Em comparação com nosso código Python no início deste codelab, podemos confirmar que essa é a mesma rede que criamos com uma entrada densa e uma camada densa com um nó.

Parabéns! Você acabou de executar um modelo convertido treinado em Python no navegador da Web.

7. Modelos que não geram conversões

Haverá momentos em que modelos mais complexos compilados para usar operações menos comuns não terão suporte para conversão. A versão baseada em navegador do TensorFlow.js é uma reescrita completa do TensorFlow e, por isso, atualmente não é compatível com todas as operações de baixo nível da API C++ do TensorFlow (há milhares). No entanto, com o tempo, mais operações foram adicionadas à medida que crescemos e as operações principais se tornam mais estáveis.

No momento em que este artigo foi escrito, uma função no TensorFlow Python que gera uma operação sem suporte quando exportada como um modelo salvo é linalg.diag. Se tentarmos converter um modelo salvo que usa isso em Python (que suporta as operações resultantes que ele produz), vamos ver um erro semelhante ao mostrado abaixo:

5df94fc652393e00.png

Aqui, podemos destacar em vermelho que a chamada linalg.diag compilada para produzir uma operação chamada MatrixDiagV3, que não era compatível com o TensorFlow.js no navegador da Web no momento da criação deste codelab.

O que fazer?

Você tem duas opções:

  1. Implemente essa operação ausente no TensorFlow.js. Somos um projeto de código aberto e queremos receber contribuições para, por exemplo, novas operações. Confira este guia sobre como escrever novas operações (em inglês) para o TensorFlow.js. Se você conseguir fazer isso, use a flag Skip_op_check no nosso conversor de linha de comando para ignorar esse erro e continuar a conversão de qualquer forma. Presume-se que essa operação está disponível no novo build do TensorFlow.js que você criou e que tem a operação ausente compatível.
  2. Determine qual parte do seu código Python produziu a operação sem suporte no arquivo savedmodel que você exportou. Em um pequeno conjunto de códigos, isso pode ser fácil de localizar. No entanto, em modelos mais complexos, isso pode exigir bastante investigação, já que não há um método para identificar a chamada de função Python de alto nível que produziu determinada operação apenas uma vez no formato de arquivo savedmodel. No entanto, depois de localizado, você pode alterá-lo para usar um método diferente que seja suportado.

8. Parabéns

Parabéns! Você deu os primeiros passos para usar um modelo Python com o TensorFlow.js no navegador da Web.

Resumo

Neste codelab, você aprendeu a:

  1. Configurar nosso ambiente Linux para instalar o TensorFlow baseado em Python
  2. Exportar um "SavedModel" do Python
  3. Instalar o conversor de linha de comando do TensorFlow.js
  4. Use o conversor de linha de comando do TensorFlow.js para criar os arquivos necessários do lado do cliente
  5. Usar os arquivos gerados em um aplicativo da Web real
  6. Identifique os modelos que não serão convertidos e o que precisaria ser implementado para permitir a conversão no futuro.

Qual é a próxima etapa?

Não se esqueça de nos marcar em qualquer conteúdo que você criar usando a hashtag #MadeWithTFJS para ter a chance de aparecer nas mídias sociais ou até mesmo aparecer em futuros eventos do TensorFlow. Adoraríamos saber o que você converte e usa no lado do cliente no navegador.

Mais codelabs do TensorFlow.js para mais detalhes

Sites para conferir