eloquentarduino / micromlgen

Generate C code for microcontrollers from Python's sklearn classifiers
MIT License
188 stars 35 forks source link

'division or modulo by zero' in micromlgen for xgboost. #5

Closed ankaiser4711 closed 6 months ago

ankaiser4711 commented 3 years ago

File "train_XGDBoost.py", line 415, in exportModel cppCode = port(clf, classmap=classmap) File "/home/andreas/.local/lib/python3.6/site-packages/micromlgen/micromlgen.py", line 44, in port return port_xgboost(locals(), kwargs) File "/home/andreas/.local/lib/python3.6/site-packages/micromlgen/xgboost.py", line 41, in port_xgboost }, *kwargs) File "/home/andreas/.local/lib/python3.6/site-packages/micromlgen/utils.py", line 79, in jinja code = template.render(data) File "/home/andreas/.local/lib/python3.6/site-packages/jinja2/environment.py", line 1090, in render self.environment.handle_exception() File "/home/andreas/.local/lib/python3.6/site-packages/jinja2/environment.py", line 832, in handle_exception reraise(rewrite_traceback_stack(source=source)) File "/home/andreas/.local/lib/python3.6/site-packages/jinja2/_compat.py", line 28, in reraise raise value.with_traceback(tb) File "/home/andreas/.local/lib/python3.6/site-packages/micromlgen/templates/xgboost/xgboost.jinja", line 1, in top-level template code {% extends '_skeleton.jinja' %} File "/home/andreas/.local/lib/python3.6/site-packages/micromlgen/templates/_skeleton.jinja", line 14, in top-level template code {% block predict %}{% endblock %} File "/home/andreas/.local/lib/python3.6/site-packages/micromlgen/templates/xgboost/xgboost.jinja", line 6, in block "predict" {% for k, tree in f.enumerate(trees) %} ZeroDivisionError: integer division or modulo by zero

versions:

andreas@krwork:/media/sourcen/ml_tools$ pip3 install --upgrade micromlgen Defaulting to user installation because normal site-packages is not writeable Requirement already satisfied: micromlgen in /home/andreas/.local/lib/python3.6/site-packages (1.1.20) Requirement already satisfied: jinja2 in /home/andreas/.local/lib/python3.6/site-packages (from micromlgen) (2.11.2) Requirement already satisfied: MarkupSafe>=0.23 in /home/andreas/.local/lib/python3.6/site-packages (from jinja2->micromlgen) (1.1.1)

andreas@krwork:/media/sourcen/ml_tools$ pip3 install --upgrade xgboost Defaulting to user installation because normal site-packages is not writeable Requirement already satisfied: xgboost in /home/andreas/.local/lib/python3.6/site-packages (1.3.1) Requirement already satisfied: scipy in /home/andreas/.local/lib/python3.6/site-packages (from xgboost) (1.5.4) Requirement already satisfied: numpy in /home/andreas/.local/lib/python3.6/site-packages (from xgboost) (1.19.4)

eloquentarduino commented 3 years ago

Please share the code you're running and the dataset you're using.

ankaiser4711 commented 3 years ago

https://github.com/ankaiser4711/test

hope it works - it's the first time i publish a github repo...

eloquentarduino commented 3 years ago

I know this problem: as of now, micromlgen is not working with binary problems: as a workaround just create a dummy class with a single sample.

import numpy as np
from xgboost import XGBClassifier
from sklearn.datasets import load_digits
from micromlgen import port

if __name__ == '__main__':
    X, y = load_digits(return_X_y=True, n_class=2)

    # create a dummy class
    X[-1] = np.zeros(len(X[-1]))
    y[-1] = y.max() + 1

    clf = XGBClassifier()
    clf.fit(X, y)
    print(clf.predict(X) == y)
    print(port(clf))
ns96 commented 6 months ago

Verified. Code is not generated when only two classes are used, but works with three classes.