{ "version": "https://jsonfeed.org/version/1.1", "user_comment": "This feed allows you to read the posts from this site in any feed reader that supports the JSON Feed format. To add this feed to your reader, copy the following URL -- https://eloquentarduino.github.io/tag/tinyml/feed/json/ -- and add it your reader.", "home_page_url": "https://eloquentarduino.github.io/tag/tinyml/", "feed_url": "https://eloquentarduino.github.io/tag/tinyml/feed/json/", "language": "en-US", "title": "tinyml – Eloquent Arduino Blog", "description": "Machine learning on Arduino, programming & electronics", "items": [ { "id": "https://eloquentarduino.github.io/?p=864", "url": "https://eloquentarduino.github.io/2020/01/easy-tinyml-on-esp32-and-arduino/", "title": "Easy Tensorflow TinyML on ESP32 and Arduino", "content_html": "

In this post I will show you how to easily deploy your Tensorflow Lite model to an ESP32 using the Arduino IDE without any compilation stuff.

\n

\"tf

\n

\n

So I finally settled on giving a try to TinyML, which is a way to deploy Tensorflow Lite models to microcontrollers.
\nAs a first step, I downloaded the free chapters from the TinyML book website and rapidly skimmed through them.

\n

Let me say that, even if it starts from "too beginner" level for me (they explain why you need to use the arrow instead of the point to access a pointer's property), it is a very well written book. They uncover every single aspect you may encounter during your first steps and give a very sound introduction to the general topic of training, validating and testing a dataset on a model.

\n

If I will go on with this TinyML stuff, I'll probably buy a copy: I strongly recommend you to at least read the free sample.

\n

Once done reading the 6 chapters, I wanted to try the described tutorial on my ESP32. Sadly, it is not mentioned in the supported boards on the book, so I had to solve it by myself.

\n

In this post I'm going to make a sort of recap of my learnings about the steps you need to follow to implement TF models to a microcontroller and introduce you to a tiny library I wrote for the purpose of facilitating the deployment in the Arduino IDE: EloquentTinyML.

\n

Building our first model

\n

First of all, we need a model to deploy.

\n

The book guides us on building a neural network capable of predicting the sine value of a given number, in the range from 0 to Pi (3.14).

\n

It's an easy model to get started (the "Hello world" of machine learning, according to the authors), so we'll stick with it.

\n

I won't go into too much details about generating data and training the classifier, because I suppose you already know that part if you want to port Tensorflow on a microcontroller.

\n

Here's the code from the book.

\n
import math\nimport numpy as np\nimport tensorflow as tf\nfrom tensorflow.keras import layers\n\ndef get_model():\n    SAMPLES = 1000\n    np.random.seed(1337)\n    x_values = np.random.uniform(low=0, high=2*math.pi, size=SAMPLES)\n    # shuffle and add noise\n    np.random.shuffle(x_values)\n    y_values = np.sin(x_values)\n    y_values += 0.1 * np.random.randn(*y_values.shape)\n\n    # split into train, validation, test\n    TRAIN_SPLIT =  int(0.6 * SAMPLES)\n    TEST_SPLIT = int(0.2 * SAMPLES + TRAIN_SPLIT)\n    x_train, x_test, x_validate = np.split(x_values, [TRAIN_SPLIT, TEST_SPLIT])\n    y_train, y_test, y_validate = np.split(y_values, [TRAIN_SPLIT, TEST_SPLIT])\n\n    # create a NN with 2 layers of 16 neurons\n    model = tf.keras.Sequential()\n    model.add(layers.Dense(16, activation='relu', input_shape=(1,)))\n    model.add(layers.Dense(16, activation='relu'))\n    model.add(layers.Dense(1))\n    model.compile(optimizer='rmsprop', loss='mse', metrics=['mae'])\n    model.fit(x_train, y_train, epochs=200, batch_size=16,\n                        validation_data=(x_validate, y_validate))\n    return model
\n

Exporting the model

\n

Now that we have a model, we need to convert it into a form ready to be deployed on our microcontroller. This is actually just an array of bytes that the TF interpreter will read to recreate the model.

\n
model = get_model()\nconverter = tf.lite.TFLiteConverter.from_keras_model(model)\nconverter.optimizations = [tf.lite.Optimize.OPTIMIZE_FOR_SIZE]\ntflite_model = converter.convert()\n\n# Save the model to disk\nopen("sine_model_quantized.tflite", "wb").write(tflite_model)
\n

Then you have to convert to a C array in the command line.

\n
xxd -i sine_model_quantized.tflite > sine_model_quantized.cc
\n

This is copy-paste code that hardly would change, so, for ease my development cycle, I wrapped this little snippet in a tiny package you can use: it's called tinymlgen.

\n
pip install tinymlgen
\n
from tinymlgen import port\n\nmodel = get_model()\nc_code = port(model, pretty_print=True)\nprint(c_code)
\n

I point you to the Github repo for a couple more options you can configure.

\n

Using this package, you don't have to open a terminal and use the xxd program to get a usable result.

\n\r\n
\r\n
\r\n
\r\n\t

Finding this content useful?

\r\n
\r\n\t\r\n
\r\n\t
\r\n\t\t
\r\n\t\t
\r\n\t
\r\n
\r\n
\r\n
\r\n
\r\n
\r\n\r\n\n

Use the model

\n

Now it is finally the time we deploy the model on our microcontroller.

\n

This part can be tricky, actually, if you don't have one of the supported boards in the book (Arduino Nano 33, SparkFun Edge or STM32F746G Discovery kit).

\n

I tried just setting "ESP32" as my target in the Arduino IDE and I got tons of errors.

\n

Luckily for us, a man called Wezley Sherman wrote a tutorial on how to get a TinyML project to compile using the PlatformIO environment. He saved me the effort to try to fix all the broken import errors on my own.

\n

Since I could get the project to compile using PlatformIO (which I don't use in my everyday tinkering), I settled to get the project to compile in the Arduino IDE.

\n

Fortunately, it was not difficult at all, so I can finally bring you this library that does all the heavy lifting for you.

\n

Thanks to the library, you won't need to download the full Tensorflow Lite framework and compile it on your own machine: it has been already done for you.

\n

As an added bonus, I created a wrapper class that incapsulates all the boring repetitive stuff, so you can focus solely on the application logic.

\n

Install the library from the library manager in the Arduino IDE: search for "EloquentTinyML", or from Github first.

\n
git clone https://github.com/eloquentarduino/EloquentTinyML.git
\n

#EloquentTinyML escapes you from compiling Tensforflow on your own machine
Click To Tweet


\n

Here is an example on how you use it.

\n
#include "EloquentTinyML.h"\n// sine_model.h contains the array you exported from the previous step\n// with either xxd or tinymlgen\n#include "sine_model.h"\n\n#define NUMBER_OF_INPUTS 1\n#define NUMBER_OF_OUTPUTS 1\n// in future projects you may need to tweak this value\n// it's a trial and error process\n#define TENSOR_ARENA_SIZE 2*1024\n\nEloquent::TinyML::TfLite<NUMBER_OF_INPUTS, NUMBER_OF_OUTPUTS, TENSOR_ARENA_SIZE> ml(sine_model);\n\nvoid setup() {\n    Serial.begin(115200);\n}\n\nvoid loop() {\n    // pick up a random x and predict its sine\n    float x = 3.14 * random(100) / 100;\n    float y = sin(x);\n    float input[1] = { x };\n    float predicted = ml.predict(input);\n\n    Serial.print("sin(");\n    Serial.print(x);\n    Serial.print(") = ");\n    Serial.print(y);\n    Serial.print("\\t predicted: ");\n    Serial.println(predicted);\n    delay(1000);\n}
\n

Does it look easy to use? I bet so.

\n

For simple cases like this example where you have a single output, the predict method returns that output so you can esaily assign it to a variable.

\n

If this is not the case and you expect multiple output from your model, you have to declare an output array.

\n
float input[10] = { ... };\nfloat output[5] = { 0 };\n\nml.predict(input, output);
\n

You will find the complete code on Github, with the sine_model.h file too.

\n

Wrapping up

\n

I hoped this post helped you kickstart your next TinyML project on your ESP32.

\n

It served me as a foundation for the next experiments I'm willing to do on this platform which is really in its early stages, so needs a lot of investigation about its capabilities.

\n

I plan to do a comparison with my MicroML framework when I get more experience in both, so staty tuned for the upcoming updates.

\n

Disclaimer

\n

I tested the library on both Ubuntu 18.04 and Windows 10 64 bit: if you are on a different platform and get compiling errors, please let me know in the comments so I can fix them.

\n

L'articolo Easy Tensorflow TinyML on ESP32 and Arduino proviene da Eloquent Arduino Blog.

\n", "content_text": "In this post I will show you how to easily deploy your Tensorflow Lite model to an ESP32 using the Arduino IDE without any compilation stuff.\n\n\nSo I finally settled on giving a try to TinyML, which is a way to deploy Tensorflow Lite models to microcontrollers.\nAs a first step, I downloaded the free chapters from the TinyML book website and rapidly skimmed through them.\nLet me say that, even if it starts from "too beginner" level for me (they explain why you need to use the arrow instead of the point to access a pointer's property), it is a very well written book. They uncover every single aspect you may encounter during your first steps and give a very sound introduction to the general topic of training, validating and testing a dataset on a model.\nIf I will go on with this TinyML stuff, I'll probably buy a copy: I strongly recommend you to at least read the free sample.\nOnce done reading the 6 chapters, I wanted to try the described tutorial on my ESP32. Sadly, it is not mentioned in the supported boards on the book, so I had to solve it by myself.\nIn this post I'm going to make a sort of recap of my learnings about the steps you need to follow to implement TF models to a microcontroller and introduce you to a tiny library I wrote for the purpose of facilitating the deployment in the Arduino IDE: EloquentTinyML.\nBuilding our first model\nFirst of all, we need a model to deploy.\nThe book guides us on building a neural network capable of predicting the sine value of a given number, in the range from 0 to Pi (3.14).\nIt's an easy model to get started (the "Hello world" of machine learning, according to the authors), so we'll stick with it.\nI won't go into too much details about generating data and training the classifier, because I suppose you already know that part if you want to port Tensorflow on a microcontroller.\nHere's the code from the book.\nimport math\nimport numpy as np\nimport tensorflow as tf\nfrom tensorflow.keras import layers\n\ndef get_model():\n SAMPLES = 1000\n np.random.seed(1337)\n x_values = np.random.uniform(low=0, high=2*math.pi, size=SAMPLES)\n # shuffle and add noise\n np.random.shuffle(x_values)\n y_values = np.sin(x_values)\n y_values += 0.1 * np.random.randn(*y_values.shape)\n\n # split into train, validation, test\n TRAIN_SPLIT = int(0.6 * SAMPLES)\n TEST_SPLIT = int(0.2 * SAMPLES + TRAIN_SPLIT)\n x_train, x_test, x_validate = np.split(x_values, [TRAIN_SPLIT, TEST_SPLIT])\n y_train, y_test, y_validate = np.split(y_values, [TRAIN_SPLIT, TEST_SPLIT])\n\n # create a NN with 2 layers of 16 neurons\n model = tf.keras.Sequential()\n model.add(layers.Dense(16, activation='relu', input_shape=(1,)))\n model.add(layers.Dense(16, activation='relu'))\n model.add(layers.Dense(1))\n model.compile(optimizer='rmsprop', loss='mse', metrics=['mae'])\n model.fit(x_train, y_train, epochs=200, batch_size=16,\n validation_data=(x_validate, y_validate))\n return model\nExporting the model\nNow that we have a model, we need to convert it into a form ready to be deployed on our microcontroller. This is actually just an array of bytes that the TF interpreter will read to recreate the model.\nmodel = get_model()\nconverter = tf.lite.TFLiteConverter.from_keras_model(model)\nconverter.optimizations = [tf.lite.Optimize.OPTIMIZE_FOR_SIZE]\ntflite_model = converter.convert()\n\n# Save the model to disk\nopen("sine_model_quantized.tflite", "wb").write(tflite_model)\nThen you have to convert to a C array in the command line.\nxxd -i sine_model_quantized.tflite > sine_model_quantized.cc\nThis is copy-paste code that hardly would change, so, for ease my development cycle, I wrapped this little snippet in a tiny package you can use: it's called tinymlgen.\npip install tinymlgen\nfrom tinymlgen import port\n\nmodel = get_model()\nc_code = port(model, pretty_print=True)\nprint(c_code)\nI point you to the Github repo for a couple more options you can configure. \nUsing this package, you don't have to open a terminal and use the xxd program to get a usable result.\n\r\n\r\n\r\n \r\n\tFinding this content useful?\r\n\r\n\t\r\n\r\n\t\r\n\t\t\r\n\t\t\r\n\t \r\n \r\n \r\n \r\n\r\n\r\n\r\n\nUse the model\nNow it is finally the time we deploy the model on our microcontroller. \nThis part can be tricky, actually, if you don't have one of the supported boards in the book (Arduino Nano 33, SparkFun Edge or STM32F746G Discovery kit). \nI tried just setting "ESP32" as my target in the Arduino IDE and I got tons of errors.\nLuckily for us, a man called Wezley Sherman wrote a tutorial on how to get a TinyML project to compile using the PlatformIO environment. He saved me the effort to try to fix all the broken import errors on my own.\nSince I could get the project to compile using PlatformIO (which I don't use in my everyday tinkering), I settled to get the project to compile in the Arduino IDE.\nFortunately, it was not difficult at all, so I can finally bring you this library that does all the heavy lifting for you.\nThanks to the library, you won't need to download the full Tensorflow Lite framework and compile it on your own machine: it has been already done for you.\nAs an added bonus, I created a wrapper class that incapsulates all the boring repetitive stuff, so you can focus solely on the application logic.\nInstall the library from the library manager in the Arduino IDE: search for "EloquentTinyML", or from Github first.\ngit clone https://github.com/eloquentarduino/EloquentTinyML.git\n#EloquentTinyML escapes you from compiling Tensforflow on your own machineClick To Tweet\nHere is an example on how you use it.\n#include "EloquentTinyML.h"\n// sine_model.h contains the array you exported from the previous step\n// with either xxd or tinymlgen\n#include "sine_model.h"\n\n#define NUMBER_OF_INPUTS 1\n#define NUMBER_OF_OUTPUTS 1\n// in future projects you may need to tweak this value\n// it's a trial and error process\n#define TENSOR_ARENA_SIZE 2*1024\n\nEloquent::TinyML::TfLite<NUMBER_OF_INPUTS, NUMBER_OF_OUTPUTS, TENSOR_ARENA_SIZE> ml(sine_model);\n\nvoid setup() {\n Serial.begin(115200);\n}\n\nvoid loop() {\n // pick up a random x and predict its sine\n float x = 3.14 * random(100) / 100;\n float y = sin(x);\n float input[1] = { x };\n float predicted = ml.predict(input);\n\n Serial.print("sin(");\n Serial.print(x);\n Serial.print(") = ");\n Serial.print(y);\n Serial.print("\\t predicted: ");\n Serial.println(predicted);\n delay(1000);\n}\nDoes it look easy to use? I bet so.\nFor simple cases like this example where you have a single output, the predict method returns that output so you can esaily assign it to a variable.\nIf this is not the case and you expect multiple output from your model, you have to declare an output array.\nfloat input[10] = { ... };\nfloat output[5] = { 0 };\n\nml.predict(input, output);\nYou will find the complete code on Github, with the sine_model.h file too.\nWrapping up\nI hoped this post helped you kickstart your next TinyML project on your ESP32.\nIt served me as a foundation for the next experiments I'm willing to do on this platform which is really in its early stages, so needs a lot of investigation about its capabilities.\nI plan to do a comparison with my MicroML framework when I get more experience in both, so staty tuned for the upcoming updates.\nDisclaimer\nI tested the library on both Ubuntu 18.04 and Windows 10 64 bit: if you are on a different platform and get compiling errors, please let me know in the comments so I can fix them.\nL'articolo Easy Tensorflow TinyML on ESP32 and Arduino proviene da Eloquent Arduino Blog.", "date_published": "2020-01-25T20:36:29+01:00", "date_modified": "2020-06-03T19:10:18+02:00", "authors": [ { "name": "simone", "url": "https://eloquentarduino.github.io/author/simone/", "avatar": "http://1.gravatar.com/avatar/d670eb91ca3b1135f213ffad83cb8de4?s=512&d=mm&r=g" } ], "author": { "name": "simone", "url": "https://eloquentarduino.github.io/author/simone/", "avatar": "http://1.gravatar.com/avatar/d670eb91ca3b1135f213ffad83cb8de4?s=512&d=mm&r=g" }, "tags": [ "ml", "tinyml", "Arduino Machine learning" ] } ] }