--- license: apache-2.0 library_name: pytorch pipeline_tag: image-classification tags: - executorch - zephyr - tinyml - mnist - cortex-m - esp32 - int8 datasets: - ylecun/mnist metrics: - accuracy model-index: - name: TinyDigitNet results: - task: type: image-classification name: Handwritten digit recognition dataset: type: ylecun/mnist name: MNIST test set metrics: - type: accuracy value: 0.9746 name: Top-1 accuracy (fp32, 10,000 test images) --- # TinyDigitNet A 14,410-parameter CNN for 28x28 grayscale digits, sized to run under [ExecuTorch](https://github.com/pytorch/executorch) on Zephyr RTOS boards with no delegate: it has been run on an RP2040 (Cortex-M0+, Arducam Pico4ML-BLE, reading digits from the on-board camera), an ESP32-S3 (Seeed XIAO ESP32S3 Sense), an ESP32 (M5Stack ATOM) and Cortex-M33 parts (Arduino UNO Q, nRF5340, MCX N947). ``` conv1 1->8 3x3, ReLU, maxpool 2 28x28 -> 13x13 conv2 8->16 3x3, ReLU, maxpool 2 13x13 -> 5x5 fc1 400->32, ReLU fc2 32->10 ``` Input: `(1, 1, 28, 28)` float, pixel/255 normalised with mean 0.1307 and std 0.3081 (the usual MNIST constants; the firmware applies the same transform to camera crops). Output: 10 logits. ## Files | File | What | |---|---| | `tiny_digit_net.py` | model definition (PyTorch) | | `tiny_digit_net.pt` | trained state dict, fp32 | | `executorch/fp32.pte` | ExecuTorch program, portable fp32 kernels (62.8 KB) | | `executorch/int8-cmsis-m0plus.pte`, `-m4.pte`, `-m33.pte`, `-m7.pte` | int8 via the ExecuTorch Cortex-M quantizer and `CortexMPassManager`, one per core (25.4 KB) | | `tflite/fp32.tflite`, `tflite/int8.tflite` | the same weights through a Keras twin, for TensorFlow Lite Micro comparisons (post-training int8 quantization) | | `test_vectors.h` | one test image plus reference logits for an on-device self-test | ## Results | Metric | Value | |---|---| | MNIST test accuracy (fp32) | 97.46 % | | Parameters | 14,410 | | Inference, RP2040 @ 133 MHz, fp32 portable kernels | 766 ms | ## Training Standard MNIST, Adam, a few epochs on CPU; the script is `train/train_mnist.py` in the [Pico4ML-BLE repo](https://github.com/eoinjordan/executorch-zephyr-arducam-pico4ML-BLE). Export with `torch.export` then `to_edge_transform_and_lower(...).to_executorch()`; the int8 variants use `CortexMQuantizer` + `prepare_pt2e`/`convert_pt2e` and the Cortex-M pass manager from ExecuTorch 1.5. ## Where it runs - [executorch-zephyr-arducam-pico4ML-BLE](https://github.com/eoinjordan/executorch-zephyr-arducam-pico4ML-BLE): camera to screen digit reader - [executorch-zephyr-xiao-esp32s3](https://github.com/eoinjordan/executorch-zephyr-xiao-esp32s3): same on the XIAO ESP32-S3 Sense - [executorch-vs-tflm-benchmarks](https://github.com/eoinjordan/executorch-vs-tflm-benchmarks): ExecuTorch vs TFLM, fp32 and int8, across boards ## License Apache-2.0. MNIST is the public dataset by LeCun, Cortes and Burges.