Conversion of a logistic regression into C#

Simple example which shows how to predict with a logistic regression using a code implemented in C. This configuration is significantly faster in case of one-off prediction. It usually happens when the machine learned model is embedded in a service.

Train a logistic regression

from sklearn.linear_model import LogisticRegression
from sklearn.datasets import load_iris
from mlprodict.grammar.grammar_sklearn import sklearn2graph

iris = load_iris()
X = iris.data[:, :2]
y = iris.target
y[y == 2] = 1
lr = LogisticRegression()
lr.fit(X, y)
LogisticRegression()
In a Jupyter environment, please rerun this cell to show the HTML representation or trust the notebook.
On GitHub, the HTML representation is unable to render, please try loading this page with nbviewer.org.


Conversion into a graph.

gr = sklearn2graph(lr, output_names=['Prediction', 'Score'])

Conversion into C

ccode = gr.export(lang='c')
print(ccode['code'])

Out:

int LogisticRegression (float* pred, float* Features)
{
    // 140200376907424-LogisticRegression - children
    // 140200376908096-concat - children
    // 140200376907808-sign - children
    // 140200376909152-+ - children
    // 140200376909392-adot - children
    float pred0c0c00c0[2] = {(float)3.3882975578308105, (float)-3.164527654647827};
    float* pred0c0c00c1 = Features;
    // 140200376909392-adot - itself
    float pred0c0c00;
    adot_float_float(&pred0c0c00, pred0c0c00c0, pred0c0c00c1, 2);
    // 140200376909392-adot - done
    float pred0c0c01 = (float)-8.323304176330566;
    // 140200376909152-+ - itself
    float pred0c0c0 = pred0c0c00 + pred0c0c01;
    // 140200376909152-+ - done
    // 140200376907808-sign - itself
    float pred0c0;
    sign_float(&pred0c0, pred0c0c0);
    // 140200376907808-sign - done
    // 140200376908096-concat - itself
    float pred0[2];
    concat_float_float(pred0, pred0c0, pred0c0c0);
    // 140200376908096-concat - done
    memcpy(pred, pred0, 2*sizeof(float));
    // 140200376907424-LogisticRegression - itself
    return 0;
    // 140200376907424-LogisticRegression - done
}

This approach may work on small models. On bigger models with many dimensions, it would be better to use AVX instructions and parallelisation. Below, the optimisation this machine can offer.

from mlprodict.testing.experimental_c_impl.experimental_c import code_optimisation
print(code_optimisation())

Out:

AVX-omp=8

Total running time of the script: ( 0 minutes 0.123 seconds)

Gallery generated by Sphinx-Gallery