├── .gitignore ├── MANIFEST ├── README.md ├── dist └── tinymlgen-0.2.tar.gz ├── setup.py └── tinymlgen ├── __init__.py └── tinymlgen.py /.gitignore: -------------------------------------------------------------------------------- 1 | try.py 2 | publish 3 | venv 4 | .idea 5 | tinymlgen/__pycache__ -------------------------------------------------------------------------------- /MANIFEST: -------------------------------------------------------------------------------- 1 | # file GENERATED by distutils, do NOT edit 2 | setup.py 3 | tinymlgen/__init__.py 4 | tinymlgen/tinymlgen.py 5 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # TinyML gen 2 | 3 | This is a simple package to export a model trained in Tensorflow Lite 4 | to a plain C array, ready to be used for inference on microcontrollers. 5 | 6 | ### Install 7 | 8 | ```shell script 9 | pip install tinymlgen 10 | ``` 11 | 12 | ### Use 13 | 14 | ```python 15 | from tinymlgen import port 16 | 17 | if __name__ == '__main__': 18 | tf_model = create_tf_model() 19 | c_code = port(tf_model) 20 | ``` 21 | 22 | ### Configuration 23 | 24 | You can pass a few parameters to the `port` function: 25 | 26 | - `optimize (=True)`: apply optimizers to the exported model. 27 | Can either be a list of optimizers or a boolean, in which case 28 | `OPTIMIZE_FOR_SIZE` is applied 29 | - `variable_name (='model_data')`: give the exported array a custom name 30 | - `pretty_print (=False)`: print the array in a nicely formatted arrangement 31 | 32 | 33 | -------------------------------------------------------------------------------- /dist/tinymlgen-0.2.tar.gz: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/eloquentarduino/tinymlgen/5798ed1857b1f9dc126f94537169d219db2d7cf0/dist/tinymlgen-0.2.tar.gz -------------------------------------------------------------------------------- /setup.py: -------------------------------------------------------------------------------- 1 | from distutils.core import setup 2 | setup( 3 | name = 'tinymlgen', 4 | packages = ['tinymlgen'], 5 | version = '0.3', 6 | license='MIT', 7 | description = 'Generate C code for microcontrollers from Tensorflow models', 8 | author = 'Simone Salerno', 9 | author_email = 'eloquentarduino@gmail.com', 10 | url = 'https://github.com/eloquentarduino/tinymlgen', 11 | download_url = 'https://github.com/eloquentarduino/tinymlgen/archive/v_03.tar.gz', 12 | keywords = ['ML', 'microcontrollers', 'tensorflow', 'machine learning'], 13 | install_requires=[ 14 | 'tensorflow', 15 | 'hexdump' 16 | ], 17 | classifiers=[ 18 | 'Development Status :: 3 - Alpha', 19 | 'Intended Audience :: Developers', 20 | 'Topic :: Software Development :: Code Generators', 21 | 'License :: OSI Approved :: MIT License', 22 | 'Programming Language :: Python :: 3', 23 | 'Programming Language :: Python :: 3.4', 24 | 'Programming Language :: Python :: 3.5', 25 | 'Programming Language :: Python :: 3.6', 26 | ], 27 | ) -------------------------------------------------------------------------------- /tinymlgen/__init__.py: -------------------------------------------------------------------------------- 1 | from tinymlgen.tinymlgen import port -------------------------------------------------------------------------------- /tinymlgen/tinymlgen.py: -------------------------------------------------------------------------------- 1 | import re 2 | import hexdump 3 | import tensorflow as tf 4 | 5 | 6 | def port(model, optimize=False, variable_name='model_data', pretty_print=False): 7 | converter = tf.lite.TFLiteConverter.from_keras_model(model) 8 | if optimize: 9 | if isinstance(optimize, bool): 10 | optimizers = [tf.lite.Optimize.OPTIMIZE_FOR_SIZE] 11 | else: 12 | optimizers = optimize 13 | converter.optimizations = optimizers 14 | tflite_model = converter.convert() 15 | bytes = hexdump.dump(tflite_model).split(' ') 16 | c_array = ', '.join(['0x%02x' % int(byte, 16) for byte in bytes]) 17 | c = 'const unsigned char %s[] DATA_ALIGN_ATTRIBUTE = {%s};' % (variable_name, c_array) 18 | if pretty_print: 19 | c = c.replace('{', '{\n\t').replace('}', '\n}') 20 | c = re.sub(r'(0x..?, ){12}', lambda x: '%s\n\t' % x.group(0), c) 21 | c += '\nconst int %s_len = %d;' % (variable_name, len(bytes)) 22 | preamble = ''' 23 | // if having troubles with min/max, uncomment the following 24 | // #undef min 25 | // #undef max 26 | 27 | #ifdef __has_attribute 28 | #define HAVE_ATTRIBUTE(x) __has_attribute(x) 29 | #else 30 | #define HAVE_ATTRIBUTE(x) 0 31 | #endif 32 | #if HAVE_ATTRIBUTE(aligned) || (defined(__GNUC__) && !defined(__clang__)) 33 | #define DATA_ALIGN_ATTRIBUTE __attribute__((aligned(4))) 34 | #else 35 | #define DATA_ALIGN_ATTRIBUTE 36 | #endif 37 | 38 | ''' 39 | return preamble + c --------------------------------------------------------------------------------