Na maioria dos casos, algoritmos úteis de aprendizado de máquina requerem grandes quantidades de recursos computacionais (CPU e ciclos de RAM). No entanto, o TensorFlow Lite lançou recentemente uma versão experimental que funciona em vários microcontroladores. Assumindo que podemos construir um modelo adequado para um dispositivo com recursos limitados, podemos começar a transformar sistemas embarcados em pequenos dispositivos de aprendizado de máquina (TinyML).
O TensorFlow Lite Micro (TFLM) é uma estrutura de inferência de ML de código aberto para executar modelos de deep learning em sistemas embarcados. O TFLM atende aos requisitos de eficiência devido a restrições de recursos do sistema embarcado e problemas de fragmentação que tornam a interoperabilidade entre plataformas, quase impossível. A estrutura usa uma abordagem baseada em intérprete que supera esses desafios únicos ao mesmo tempo em que oferece flexibilidade.
A primeira etapa no desenvolvimento de uma aplicação TFLM é criar um objeto de modelo de rede neural ao vivo na memória. O desenvolvedor da aplicação cria um objeto “resolução de operador” por meio da API do cliente. A API “OpResolver” controla os operadores conectados ao binário final e minimiza o tamanho do arquivo.
O segundo passo é fornecer uma “arena” de memória contínua que contenha os resultados intermediários e outras variáveis que o interpretador precisa. Isso é necessário porque pressupõe que a alocação dinâmica de memória não está disponível.
A terceira etapa é criar um exemplo compilado e fornecer o modelo, o analisador do operador e a arena como argumentos. O compilador aloca toda a memória necessária na fase de inicialização para o campo. Evitamos qualquer alocação de mensagens para garantir que a fragmentação da pilha evite a ocorrência de erros em aplicações de execução longa. Aplicações de acionamento podem alocar memória para uso durante a avaliação, portanto, as funções de configuração do operador são chamadas neste ponto e permitem que sua memória seja transferida para o interpretador. O OpResolver fornecido pela aplicação mapeia os tipos de operadores listados no modelo serial para as funções de execução. As chamadas C API controlam todas as comunicações entre o intérprete e o operador, garantindo que a implementação do operador seja modular e independente dos detalhes do intérprete. Essa abordagem permite substituir facilmente a implementação do iniciador por uma versão aprimorada e facilita a reutilização de outras bibliotecas do iniciador do sistema (por exemplo, como parte de um projeto de geração de código).
A quarta etapa é a execução. A aplicação recupera ponteiros para áreas de memória que representam entradas de modelo e as preenche com valores (geralmente derivados de sensores ou outros dados fornecidos pelo usuário). Assim que as entradas estiverem disponíveis, a aplicação chama o interpretador para realizar os cálculos do modelo. Esse processo envolve a iteração de operações ordenadas topologicamente, usando os deslocamentos calculados durante o planejamento de memória para localizar entradas e saídas e chamando a função do avaliador para cada operação.
Por fim, após todas as operações terem sido avaliadas, o interpretador retorna o controle para a aplicação. A maioria dos MCUs são de thread único e usam interrupções para tarefas urgentes, o que é aceitável. No entanto, as aplicações ainda podem ser executados em um único thread e os operadores específicos da plataforma ainda podem distribuir o trabalho entre os processadores. Quando a chamada for concluída, a aplicação pode consultar o interpretador para determinar a localização da matriz que contém a saída do cálculo do modelo e, em seguida, usar essa saída.
O modelo, que é criado com Keras ou TensorFlow, precisa ser convertido para TensorFlow Lite e exportado para implantar em um microcontrolador. Usamos a API Python do TensorFlow Lite Converter para fazer isso. Ele pega nosso modelo Keras e o grava em disco na forma de um FlatBuffer, que é um formato de arquivo especial projetado para ser eficiente em termos de espaço. Como estamos implantando em dispositivos com memória limitada, isso será útil.
Para implantar o modelo no microcontrolador STM32 e no Arduino, usaremos a biblioteca EloquentTinyML para fazer isso sem problemas. Esta é uma biblioteca para executar modelos TinyML em seu microcontrolador sem mexer com procedimentos complexos de compilação e erros esotéricos.
Você deve primeiro instalar a biblioteca em sua versão mais recente (0.0.5 ou 0.0.4, se não estiver disponível), por meio do Library Manager ou diretamente do Github.
Abaixo está o código para executar e implantar o modelo TinyML de reconhecimento de dígitos nos microcontroladores STM32 e Arduino.
// copy the printed code from tinymlgen into this file
#include "digits_model.h"
#define NUMBER_OF_INPUTS 64
#define NUMBER_OF_OUTPUTS 10
#define TENSOR_ARENA_SIZE 8*1024
Eloquent::TinyML::TfLite<NUMBER_OF_INPUTS, NUMBER_OF_OUTPUTS, TENSOR_ARENA_SIZE> ml;
void setup() {
Serial.begin(115200);
ml.begin(digits_model);
}
void loop() {
// a random sample from the MNIST dataset (precisely the last one)
float x_test[64] = { 0., 0. , 0.625 , 0.875 , 0.5 , 0.0625, 0. , 0. ,
0. , 0.125 , 1. , 0.875 , 0.375 , 0.0625, 0. , 0. ,
0. , 0. , 0.9375, 0.9375, 0.5 , 0.9375, 0. , 0. ,
0. , 0. , 0.3125, 1. , 1. , 0.625 , 0. , 0. ,
0. , 0. , 0.75 , 0.9375, 0.9375, 0.75 , 0. , 0. ,
0. , 0.25 , 1. , 0.375 , 0.25 , 1. , 0.375 , 0. ,
0. , 0.5 , 1. , 0.625 , 0.5 , 1. , 0.5 , 0. ,
0. , 0.0625, 0.5 , 0.75 , 0.875 , 0.75 , 0.0625, 0. };
// the output vector for the model predictions
float y_pred[10] = {0};
// the actual class of the sample
int y_test = 8;
// let's see how long it takes to classify the sample
uint32_t start = micros();
ml.predict(x_test, y_pred);
uint32_t timeit = micros() - start;
Serial.print("It took ");
Serial.print(timeit);
Serial.println(" micros to run inference");
// let's print the raw predictions for all the classes
// these values are not directly interpretable as probabilities!
Serial.print("Test output is: ");
Serial.println(y_test);
Serial.print("Predicted proba are: ");
for (int i = 0; i < 10; i++) {
Serial.print(y_pred[i]);
Serial.print(i == 9 ? '\n' : ',');
}
// let's print the "most probable" class
// you can either use probaToClass() if you also want to use all the probabilities
Serial.print("Predicted class is: ");
Serial.println(ml.probaToClass(y_pred));
// or you can skip the predict() method and call directly predictClass()
Serial.print("Sanity check: ");
Serial.println(ml.predictClass(x_test));
delay(1000);
}
Contato da Newark no Brasil
Para mais informações e adquirir componentes contate a LATeRe , representante da Newark, pelo Telefone (11) 4066-9400 ou e-mail: vendas@laterebr.com.br
* Texto originalmente publicado em: link





