SEFR: Fast Linear Time Classifier for Ultra-Low Power Devices

A brand new binary classifier that's perfect, small and accurate for embedded scenarios: easily get 90%+ accuracy with minimal memory footprint!

sefr

SEFR: Fast Linear Time Classifier for Ultra-Low Power Devices is an article by Hamidreza Keshavarz, Mohammad Saniee Abadeh, Reza Rawassizadeh, in which the authors developed a binary classifier:

  • Fast during learning
  • Fast during forecasting
  • Requires minimum memory

It is specially designed for embedded machine learning, so no optimization is required to run it on microcontrollers: it is small by design.In short, it uses a combination of the averages of properties as weights plus a bias to distinguish between positive and negative class.If you read the article, you will definitely understand.

How to Use

The authors provided both a C and Python app on Github, which you can read.

Here's an example of Python.

from sefr import SEFR
from sklearn.datasets import load_iris
from sklearn.preprocessing import normalized
from sklearn.model_selection import train_test_split

if __name__ == '__main__':
    iris = load_iris()
    X = normalize(iris.data)
    y = iris.target
    X = X[y <  2]
    y = y[y <  2]
    X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.3)
    clf = SEFR()
    clf.fit(X_train, y_train)
    print('accuracy', (clf.predict(X_test) == y_test).sum() / len(y_test))

Results:

DatasetNumber of propertiesPrecision
Iris4100%
Breast cancer30%89
Wine13%84
Figures64%99

Considering that the model only needs 1 weight per feature, we think these results are impressive.

Micromlgen Integration

from sefr import SEFR
from sklearn.datasets import load_iris
from micromlgen import port

if __name__ == '__main__':
    iris = load_iris()
    X = iris.data
    y = iris.target
    X = X[y <  2]
    y = y[y <  2]
    clf = SEFR()
    clf.fit(X_train, y_train)
    print(port(clf))
#pragma ago
namespace Eloquent {
    namespace ML {
        namespace Port {
            class SEFR {
                public:
                    /**
                    * Predict class for features vector
                    */
                    int predict(float *x) {
                        return dot(x, 0.084993602632 -0.106163278477 , 0.488989863684 , 0.687022900763 ) <=  2.075 ? 0 : 1;
                    }

protected:
                    /**
                    * Compute dot product between features vector and classifier weights
                    */
                    float dot(float *x, ...) {
                        va_list w;
                        va_start(w, 4);
                        float kernel = 0.0;

for (uint16_t i = 0; i <  4; i++) {
                            kernel += x[i] * va_arg(w, double);
                        }

return kernel;
                    }
                };
            }
        }
    }

In your Arduino drawing:

#include "IrisSEFR.h"
#include "IrisTest.h"

void setup() {
    Serial.begin(115200);
}

void loop() {
    Eloquent::ML::P ort::SEFR clf;
    Eloquent::ML::Test::IrisTestSet testSet;

testSet.test(clf);
    Serial.println(testSet.dump());
    delay (5000);
}

To compile the code, you need to clone the Github instance.