Transpile trained scikit-learn models to dependency-free C code, and deploy ML on any microcontroller.
python transpile_simple_model.py model.joblib
# → generated_model.c (pure C, no libraries, compiles anywhere)scikit-learn doesn't run on microcontrollers, and existing solutions (ONNX, TFLite Micro) require a runtime that adds significant flash/RAM overhead. sklearn2c walks the trained model's internal parameters and hard-codes them as a pure C function. There is no interpreter, no memory allocation, and no dependency beyond stdio.h.
The output compiles with gcc, arm-none-eabi-gcc, or any standard C compiler and drops directly into Arduino, STM32, ESP32 firmware.
| Model | Output type | Generated function |
|---|---|---|
LinearRegression |
float |
float predict(float *features, int n) |
LogisticRegression |
int |
int predict(float *features, int n) |
DecisionTreeClassifier |
int |
int predict(float *features, int n) |
# 1. Install
pip install scikit-learn pandas joblib numpy
# 2. Train a model
python train_model.py # LinearRegression on house prices
python train_decision_tree.py # DecisionTree on student data
# 3. Transpile to C
python transpile_simple_model.py regression.joblib
# → generated_model.c
# 4. Compile and run
gcc generated_model.c -o model && ./model
# 5. Copy predict() into your Arduino/firmware sketchDecision tree with depth 3 produces clean, readable C:
int predict(float *features, int n_features) {
if (features[1] <= -0.2990f) {
if (features[0] <= -0.0770f) {
return 1;
} else {
return 0;
}
} else {
return 2;
}
}Linear/logistic regression:
float prediction(float *features, int n_features) {
float result = 150432.123f; // intercept
result += features[0] * 85.34f;
result += features[1] * -312.77f;
return result;
}Note: regression models generate a function named
prediction(), decision trees generatepredict().
Copy the generated predict() into your sketch, no libraries needed:
// paste generated predict() here
void loop() {
float sensors[2] = { analogRead(A0) / 1023.0f, analogRead(A1) / 1023.0f };
float pred = predict(sensors, 2);
Serial.println(pred);
delay(1000);
}- Load the
.joblibmodel with Python - Introspect internal parameters (coefficients, tree nodes, thresholds)
- Generate C source with parameters as compile-time constants
- The
predict()function is a series of branches / dot products, with no loops over parameters
sklearn2c/
├── transpile_simple_model.py # Core transpiler
├── train_model.py # Example: LinearRegression
├── train_logistic.py # Example: LogisticRegression
├── train_decision_tree.py # Example: DecisionTree
├── generated_model.c # Example output
├── houses.csv / students.csv # Sample datasets
└── README.md
-
RandomForestClassifier(ensemble of trees) -
SVCwith RBF kernel -
MLPClassifier(dense layers) - Automated flash/RAM size estimation
- Arduino
.inofile output
MIT