Plataforma e ambiente

Mantenha tudo organizado com as coleções Salve e categorize o conteúdo com base nas suas preferências.

O TensorFlow.js funciona no navegador e no Node.js, e em ambas as plataformas há muitas configurações diferentes disponíveis. Cada plataforma tem um conjunto exclusivo de considerações que afetarão a maneira como os aplicativos são desenvolvidos.

No navegador, o TensorFlow.js é compatível com dispositivos móveis e computadores. Cada dispositivo tem um conjunto específico de restrições, como APIs WebGL disponíveis, que são determinadas e configuradas automaticamente para você.

No Node.js, o TensorFlow.js oferece suporte à vinculação direta à API do TensorFlow ou à execução com as implementações de CPU vanilla mais lentas.

Ambientes

Quando um programa TensorFlow.js é executado, a configuração específica é chamada de ambiente. O ambiente é composto por um único back-end global, bem como por um conjunto de sinalizadores que controlam recursos refinados do TensorFlow.js.

Back-ends

O TensorFlow.js oferece suporte a vários back-ends diferentes que implementam armazenamento de tensor e operações matemáticas. A qualquer momento, apenas um back-end está ativo. Na maioria das vezes, o TensorFlow.js escolherá automaticamente o melhor back-end para você de acordo com o ambiente atual. No entanto, às vezes é importante saber qual back-end está sendo usado e como alterá-lo.

Para descobrir qual back-end você está usando:

console.log(tf.getBackend());

Se você quiser alterar manualmente o back-end:

tf.setBackend('cpu');
console.log(tf.getBackend());

back-end WebGL

O backend WebGL, 'webgl', é atualmente o backend mais poderoso para o navegador. Este backend é até 100x mais rápido que o backend de CPU vanilla. Os tensores são armazenados como texturas WebGL e as operações matemáticas são implementadas em shaders WebGL. Aqui estão algumas coisas úteis para saber ao usar este back-end: \

Evite bloquear o thread da interface do usuário

Quando uma operação é chamada, como tf.matMul(a, b), o tf.Tensor resultante é retornado de forma síncrona, porém o cálculo da multiplicação da matriz pode ainda não estar pronto. Isso significa que o tf.Tensor retornado é apenas um handle para a computação. Quando você chama x.data() ou x.array() , os valores serão resolvidos quando a computação for realmente concluída. Isso torna importante usar os métodos assíncronos x.data() e x.array() sobre suas contrapartes síncronas x.dataSync() e x.arraySync() para evitar o bloqueio do encadeamento da interface do usuário enquanto a computação é concluída.

Gerenciamento de memória

Uma ressalva ao usar o back-end WebGL é a necessidade de gerenciamento de memória explícito. WebGLTextures, que é onde os dados do Tensor são armazenados, não são automaticamente coletados como lixo pelo navegador.

Para destruir a memória de um tf.Tensor , você pode usar o método Dispose dispose() :

const a = tf.tensor([[1, 2], [3, 4]]);
a.dispose();

É muito comum encadear várias operações em um aplicativo. Manter uma referência a todas as variáveis ​​intermediárias para descartá-las pode reduzir a legibilidade do código. Para resolver esse problema, o TensorFlow.js fornece um método tf.tidy() que limpa todos os tf.Tensor s que não são retornados por uma função depois de executá-la, semelhante à maneira como as variáveis ​​locais são limpas quando uma função é executada:

const a = tf.tensor([[1, 2], [3, 4]]);
const y = tf.tidy(() => {
  const result = a.square().log().neg();
  return result;
});
Precisão

Em dispositivos móveis, o WebGL pode suportar apenas texturas de ponto flutuante de 16 bits. No entanto, a maioria dos modelos de aprendizado de máquina são treinados com pesos e ativações de ponto flutuante de 32 bits. Isso pode causar problemas de precisão ao portar um modelo para um dispositivo móvel, pois números flutuantes de 16 bits só podem representar números no intervalo [0.000000059605, 65504] . Isso significa que você deve ter cuidado para que os pesos e ativações em seu modelo não ultrapassem essa faixa. Para verificar se o dispositivo suporta texturas de 32 bits, verifique o valor de tf.ENV.getBool('WEBGL_RENDER_FLOAT32_CAPABLE') , se for false então o dispositivo suporta apenas texturas de ponto flutuante de 16 bits. Você pode usar tf.ENV.getBool('WEBGL_RENDER_FLOAT32_ENABLED') para verificar se o TensorFlow.js está usando texturas de 32 bits.

Compilação de shaders e uploads de texturas

O TensorFlow.js executa operações na GPU executando programas de sombreador WebGL. Esses shaders são montados e compilados preguiçosamente quando o usuário solicita a execução de uma operação. A compilação de um shader acontece na CPU no thread principal e pode ser lenta. O TensorFlow.js armazenará em cache os shaders compilados automaticamente, tornando muito mais rápida a segunda chamada para a mesma operação com tensores de entrada e saída da mesma forma. Normalmente, os aplicativos TensorFlow.js usam as mesmas operações várias vezes durante a vida útil do aplicativo, portanto, a segunda passagem por um modelo de aprendizado de máquina é muito mais rápida.

O TensorFlow.js também armazena dados tf.Tensor como WebGLTextures. Quando um tf.Tensor é criado, não enviamos os dados imediatamente para a GPU, mas mantemos os dados na CPU até que o tf.Tensor seja usado em uma operação. Se o tf.Tensor for usado uma segunda vez, os dados já estão na GPU, portanto não há custo de upload. Em um modelo típico de aprendizado de máquina, isso significa que os pesos são carregados durante a primeira previsão pelo modelo e a segunda passagem pelo modelo será muito mais rápida.

Se você se preocupa com o desempenho da primeira previsão por meio de seu modelo ou código do TensorFlow.js, recomendamos aquecer o modelo passando um tensor de entrada da mesma forma antes que os dados reais sejam usados.

Por exemplo:

const model = await tf.loadLayersModel(modelUrl);

// Warmup the model before using real data.
const warmupResult = model.predict(tf.zeros(inputShape));
warmupResult.dataSync();
warmupResult.dispose();

// The second predict() will be much faster
const result = model.predict(userData);

Back-end do TensorFlow do Node.js

No back-end TensorFlow Node.js, 'node', a API TensorFlow C é usada para acelerar as operações. Isso usará a aceleração de hardware disponível da máquina, como CUDA, se disponível.

Neste backend, assim como o backend WebGL, as operações retornam tf.Tensor s de forma síncrona. No entanto, ao contrário do backend WebGL, a operação é concluída antes de você recuperar o tensor. Isso significa que uma chamada para tf.matMul(a, b) bloqueará o thread da interface do usuário.

Por esse motivo, se você pretende usar isso em um aplicativo de produção, execute o TensorFlow.js em threads de trabalho para não bloquear o thread principal.

Para obter mais informações sobre Node.js, consulte este guia.

back-end WASM

O TensorFlow.js fornece um backend WebAssembly ( wasm ), que oferece aceleração de CPU e pode ser usado como uma alternativa aos backends Vanilla JavaScript CPU ( cpu ) e WebGL acelerado ( webgl ). Para usá-lo:

// Set the backend to WASM and wait for the module to be ready.
tf.setBackend('wasm');
tf.ready().then(() => {...});

Se seu servidor estiver servindo o arquivo .wasm em um caminho ou nome diferente, use setWasmPath antes de inicializar o backend. Consulte a seção "Usando Bundlers" no README para obter mais informações:

import {setWasmPath} from '@tensorflow/tfjs-backend-wasm';
setWasmPath(yourCustomPath);
tf.setBackend('wasm');
tf.ready().then(() => {...});
Por que WASM?

O WASM foi introduzido em 2015 como um novo formato binário baseado na web, fornecendo programas escritos em JavaScript, C, C++, etc. um destino de compilação para execução na web. O WASM é compatível com Chrome, Safari, Firefox e Edge desde 2017 e é compatível com 90% dos dispositivos em todo o mundo.

atuação

O backend WASM aproveita a biblioteca XNNPACK para implementação otimizada de operadores de rede neural.

Versus JavaScript : os binários WASM são geralmente muito mais rápidos do que os pacotes JavaScript para os navegadores carregarem, analisarem e executarem. O JavaScript é tipado dinamicamente e coletado como lixo, o que pode causar lentidão no tempo de execução.

Versus WebGL : O WebGL é mais rápido que o WASM para a maioria dos modelos, mas para modelos pequenos o WASM pode superar o WebGL devido aos custos fixos de execução de sombreadores WebGL. A seção “Quando devo usar o WASM” abaixo discute a heurística para tomar essa decisão.

Portabilidade e Estabilidade

O WASM possui aritmética flutuante de 32 bits portátil, oferecendo paridade de precisão em todos os dispositivos. O WebGL, por outro lado, é específico do hardware e dispositivos diferentes podem ter precisão variável (por exemplo, fallback para floats de 16 bits em dispositivos iOS).

Assim como o WebGL, o WASM é oficialmente suportado por todos os principais navegadores. Ao contrário do WebGL, o WASM pode ser executado em Node.js e ser usado no lado do servidor sem a necessidade de compilar bibliotecas nativas.

Quando devo usar o WASM?

Tamanho do modelo e demanda computacional

Em geral, o WASM é uma boa escolha quando os modelos são menores ou você se preocupa com dispositivos de baixo custo que não possuem suporte WebGL (extensão OES_texture_float ) ou têm GPUs menos potentes. O gráfico abaixo mostra os tempos de inferência (a partir do TensorFlow.js 1.5.2) no Chrome em um MacBook Pro 2018 para 5 de nossos modelos oficialmente compatíveis nos back-ends WebGL, WASM e CPU:

Modelos menores

Modelo WebGL WASM CPU Memória
BlazeFace 22,5 ms 15,6 ms 315,2ms 0,4 MB
FaceMesh 19,3 ms 19,2 ms 335 ms 2,8 MB

Modelos maiores

Modelo WebGL WASM CPU Memória
PoseNet 42,5 ms 173,9 ms 1514,7ms 4,5 MB
BodyPix 77 ms 188,4ms 2683 ms 4,6 MB
MobileNet v2 37 ms 94 ms 923,6 ms 13 MB

A tabela acima mostra que o WASM é 10-30x mais rápido que o backend de CPU JS simples em todos os modelos e competitivo com WebGL para modelos menores como BlazeFace , que é leve (400 KB), mas tem um número decente de operações (~ 140). Dado que os programas WebGL têm um custo fixo fixo por execução operacional, isso explica por que modelos como BlazeFace são mais rápidos no WASM.

Esses resultados variam dependendo do seu dispositivo. A melhor maneira de determinar se o WASM é adequado para seu aplicativo é testá-lo em nossos diferentes back-ends.

Inferência vs Treinamento

Para abordar o caso de uso principal para implantação de modelos pré-treinados, o desenvolvimento de back-end WASM priorizará a inferência sobre o suporte ao treinamento . Veja uma lista atualizada de operações com suporte no WASM e informe-nos se o seu modelo tem uma operação sem suporte. Para modelos de treinamento, recomendamos usar o back-end Node (TensorFlow C++) ou o back-end WebGL.

back-end da CPU

O back-end da CPU, 'cpu', é o back-end de menor desempenho, porém é o mais simples. As operações são todas implementadas em JavaScript vanilla, o que as torna menos paralelizáveis. Eles também bloqueiam o thread da interface do usuário.

Este backend pode ser muito útil para testes ou em dispositivos onde o WebGL não está disponível.

Bandeiras

O TensorFlow.js possui um conjunto de sinalizadores de ambiente que são avaliados automaticamente e determinam a melhor configuração na plataforma atual. Esses sinalizadores são principalmente internos, mas alguns sinalizadores globais podem ser controlados com a API pública.

  • tf.enableProdMode(): habilita o modo de produção, que removerá a validação do modelo, verificações de NaN e outras verificações de correção em favor do desempenho.
  • tf.enableDebugMode() : habilita o modo de depuração, que registrará no console todas as operações executadas, bem como informações de desempenho de tempo de execução, como espaço de memória e tempo total de execução do kernel. Observe que isso tornará seu aplicativo muito lento, não use isso em produção.