Skip to content

Machine Learning inference engine for Microcontrollers and Embedded devices

License

Notifications You must be signed in to change notification settings

emlearn/emlearn

Repository files navigation

Tests DOI]

emlearn

Machine learning for microcontroller and embedded systems. Train in Python, then do inference on any device with a C99 compiler.

emlearn logo

Status

Actively maintained since 2018.

License

emlearn is MIT licensed.

Key features

Convert machine learning models to C

Embedded-friendly Inference

  • Portable C99 code
  • No dynamic allocations
  • Small code size (from 2kB FLASH)
  • Small RAM size (from 50 bytes RAM)
  • Support integer/fixed-point math (some models)
  • No libc required (some models)

Easy to integrate in project

Feature extraction and data processing utilities

  • Infinite Impulse Response (IIR) filters
  • Fast Fourier Transform (FFT)
  • Read/write CSV files, with streaming support

Model validation tools

  • Access generated C classifier via Python, to verify prediction correctness
  • Estimate model computational cost and size (using scikit-learn compatible metrics). Example.
  • Measure tools for model program/FLASH size. Example.

Platform support

Should work anywhere that has working C99 compiler. Tested running on a large range of bare-metal, RTOS and desktop operating systems. Such as ESP8266, ESP32, AVR Atmega (8 bit), ARM Cortex M (STM32), Linux, Mac OS and Windows.

Projects using emlearn

emlearn has been used in many projects by many different developers, across a range of usecases and applications. See the Made with emlearn section in documentation.

Model support

Classification:

  • eml_trees: sklearn.RandomForestClassifier, sklearn.ExtraTreesClassifier, sklearn.DecisionTreeClassifier
  • eml_net: sklearn.MultiLayerPerceptron, Keras.Sequential with fully-connected layers
  • eml_bayes: sklearn.GaussianNaiveBayes

Regression:

  • eml_trees: sklearn.RandomForestRegressor, sklearn.ExtraTreesRegressor, sklearn.DecisionTreeRegressor
  • eml_net: Keras.Sequential with fully-connected layers

Unsupervised / Outlier Detection / Anomaly Detection

  • eml_distance: sklearn.EllipticEnvelope (Mahalanobis distance)
  • eml_mixture: sklearn.GaussianMixture, sklearn.BayesianGaussianMixture

Documentation

For full documentation see examples, the user guide.

Other learning resources

emlearn and emlearn-micropython has been covered in the following presentations.

  • Microcontrollers + Machine Learning in 1-2-3 (PyData Global 2024). Slides etc
  • Sensor data processing on microcontrollers with MicroPython and emlearn (PyConZA 2024). Slides etc
  • 6 years of open source TinyML with emlearn - a scikit-learn for microcontrollers (TinyML EMEA 2024) YouTube video | Slides etc
  • emlearn - Machine Learning for Tiny Embedded Systems (Embedded Online Conference 2024). Youtube video | Slides etc
  • Machine Learning on microcontrollers using MicroPython and emlearn (PyCon DE & PyData Berlin 2024). Slides etc | YouTube video.

Installing

Install from PyPI

pip install --user emlearn

Usage

The basic usage consist of 3 steps:

  1. Train your model in Python
from sklearn.ensemble import RandomForestClassifier
estimator = RandomForestClassifier(n_estimators=10, max_depth=10)
estimator.fit(X_train, Y_train)
...
  1. Convert it to C code
import emlearn
cmodel = emlearn.convert(estimator, method='inline')
cmodel.save(file='sonar.h', name='sonar')
  1. Use the C code

Simple classifiers

#include "sonar.h"

const int32_t length = 60;
int16_t values[length] = { ... };

// using generated "inline" code for the decision forest
const int32_t predicted_class = sonar_predict(values, length):

// ALT: using the generated decision forest datastructure
const int32_t predicted_class = eml_trees_predict(&sonar, length):

Neural net regressor

Copy the generated .h file, the eml_net.h and eml_common.h into your project, then

#include "nnmodel.h" // the generated code basedon on keras.Sequential

float values[6] = { ... };

const float_t predicted_value = nnmodel_regress1(values, 6);
if (predicted_value == NAN) {
    exit(-1);
}
// Process the value as needed

// Or, passing in a result array directly if more than 1 output is generated
float out[2];
EmlError err = nnmodel_regress(values, 6, out, 2);
if (err != EmlOk)
{
    // something went wrong
}
else {
    // predictions are in the out array
}

For a complete runnable code see Getting Started.

Contributing

See docs/CONTRIBUTING.md for contribution guidelines, and docs/developing.md for how to develop.

Contributors

Jon Nordby
Mark Cooke

Citations

If you use emlearn in an academic work, please reference it using:

@misc{emlearn,
  author       = {Nordby, Jon AND Cooke, Mark AND Horvath, Adam},
  title        = {{emlearn: Machine Learning inference engine for 
                   Microcontrollers and Embedded Devices}},
  month        = mar,
  year         = 2019,
  doi          = {10.5281/zenodo.2589394},
  url          = {https://doi.org/10.5281/zenodo.2589394}
}