Add Machine Learning to a New or Existing Project

This guide provides details of adding Machine Learning to a new or existing project, making use of the wrapper APIs for TensorFlow Lite for Microcontrollers provided by Silicon Labs for automatic initialization of the TFLM framework.

The guide assumes that a project already exists in the Simplicity Studio workspace. If you're starting from scratch, you may start with any sample application or the Empty C++ application. TFLM has a C++ API, so the application code interfacing with it will also need to be written in C++. If you're starting with an application that is predominantly C code, see the section on interfacing with C code for tips on how to structure your project by adding a separate C++ file for the TFLM interface.

Install the TensorFlow Lite Micro Component

Browse the Software Components library in the project to find the TensorFlow Lite Micro component in Machine Learning > TensorFlow.

Install the TensorFlow Lite Micro component

If your project didn't already contain an I/O Stream implementation, you may get a dependency validation warning. This is not a problem, but simply means that a choice of I/O Stream backend needs to be made. The USART or EUSART backends are the most common, as these can communicate with a connected PC through the development kit virtual COM port (VCOM).

Dismiss the warning about missing I/O Stream

Install the IO Stream: EUSART or USART component

Accept the default suggestion of "vcom" as the instance name, which will automatically configure the pinout to connect to the development board's VCOM lines. If you're using your own hardware, you can set any instance name and configure the pinout manually.

Model Inclusion

With the TensorFlow Lite Micro component added in the Project Configurator, the next step is to load the model file into the project. To do this, create a tflite directory inside the config directory of the project, and copy the .tflite model file into it. The project configurator provides a tool that will automatically convert .tflite files into sl_tflite_micro_model source and header files. The full documentation for this tool is available at Flatbuffer Converter Tool.

Automatic Initialization

The TensorFlow framework is automatically initialized using the system initialization framework described in SDK Programming Model. This includes allocating a tensor arena, instantiating an interpreter and loading the model.

Configuration

If the model was produced using the Silicon Labs Machine Learning Toolkit (MLTK), it already contains metadata indicating the required size of the Tensor Arena, the memory area used by TensorFlow for runtime storage of input, output, and intermediate arrays. The required size of the arena depends on the model used.

If not using the MLTK, the arena size needs to be configured manually. Best practice is to start with a large number during development, and reduce the allocation until initialization fails as part of size optimization.

Open the Component Configuration UI for the TensorFlow component

Configure the Tensor Arena Size

Run the Model

Include the Silicon Labs TensorFlow Init API

#include "sl_tflite_micro_init.h"

For default behavior in bare metal application, it is recommended to run the model during app_process_action() in app.cpp to ensure that periodic inferences occur during the standard event loop. Running the model involves three stages:

Provide Input to the Interpreter

Sensor data is pre-processed (if necessary) and then is provided as input to the interpreter.

TfLiteTensor* input = sl_tflite_micro_get_input_tensor();
// stores 0.0 to the input tensor of the model
input->data.f[0] = 0.;

Run Inference

The interpreter is then invoked to run all layers of the model.

TfLiteStatus invoke_status = sl_tflite_micro_get_interpreter()->Invoke();
if (invoke_status != kTfLiteOk) {
TF_LITE_REPORT_ERROR(sl_tflite_micro_get_error_reporter(),
                        "Bad input tensor parameters in model");
return;
}

Read Output

The output prediction is read from the interpreter.

TfLiteTensor* output = sl_tflite_micro_get_output_tensor();
// Obtain the output value from the tensor
float value = output->data.f[0];

At this point, application-dependent behavior based on the output prediction should be performed. The application will run inference on each iteration of app_process_action().

Full Code Snippet

After following the steps above, the resulting app.cpp now appears as follows:

#include "sl_tflite_micro_init.h"

/***************************************************************************//**
 * Initialize application.
 ******************************************************************************/
void app_init(void)
{
    // Init happens automatically
}

/***************************************************************************//**
 * App ticking function.
 ******************************************************************************/
void app_process_action(void)
{
    TfLiteTensor* input = sl_tflite_micro_get_input_tensor();
    // stores 0.0 to the input tensor of the model
    input->data.f[0] = 0.;

    TfLiteStatus invoke_status = sl_tflite_micro_get_interpreter()->Invoke();
    if (invoke_status != kTfLiteOk) {
    TF_LITE_REPORT_ERROR(sl_tflite_micro_get_error_reporter(),
                            "Bad input tensor parameters in model");
    return;
    }

    TfLiteTensor* output = sl_tflite_micro_get_output_tensor();
    // Obtain the output value from the tensor
    float value = output->data.f[0];
}

Addendum: Interfacing with C code

If your project is written in C rather than C++, place the code interfacing with TFLM into a separate file that exports a C API through an interface header. For this example, a filename app_ml.cpp is assumed that implements the function ml_process_action() with the same content as in the example above.

app_ml.h

#ifdef __cplusplus
extern "C" {
#endif

void ml_process_action(void);

#ifdef __cplusplus
}
#endif

app_ml.cpp

#include "app_ml.h"
#include "sl_tflite_micro_init.h"

extern "C" void ml_process_action(void)
{
    // ...
}

app.c

#include "app_ml.h
// ...
void app_process_action(void)
{
    ml_process_action();
}