跳转到内容

ESP-DL — 把小模型塞进 ESP32 的推理库

待复核

ESP-DL 是 Espressif 给 ESP32 系列芯片准备的神经网络推理库:它把训练好的模型压成 .espdl 文件,再让小板子在本地跑识别、检测、传感器判断。

日常类比:像把一位大厨的菜谱改写成露营炉可执行的版本。原菜谱可以很复杂,但露营炉火力小、锅也小,所以要先改分量、换步骤、安排锅具,最后才能在户外稳定做出来。

最小使用感大概是这样:

#include "dl_model_base.hpp"
extern const uint8_t model_espdl[] asm("_binary_model_espdl_start");
dl::Model *model = new dl::Model((const char *)model_espdl,
fbs::MODEL_LOCATION_IN_FLASH_RODATA);
model->run();

这段代码背后的前提是:模型已经用 ESP-PPQ 量化并导出为 .espdl,然后作为二进制资源放进 ESP-IDF 工程。

不理解 ESP-DL,下面这些事会很难解释:

  • 为什么不能把 PyTorch 的 .pth 文件直接拷进 ESP32-S3,然后期待它像电脑上一样运行。
  • 为什么模型要先量化成 8bit 或 16bit;小芯片缺的不是“会不会算”,而是内存、带宽和算力余量。
  • 为什么同一个模型给 ESP32、ESP32-S3、ESP32-P4 要用不同导出配置;底层算子和舍入策略不完全一样。
  • 为什么部署时总在 FLASH、PSRAM、internal RAM 之间纠结;模型不仅要“放得下”,还要“跑得动”。
  1. 先换成板子能读的菜谱:ESP-DL 不直接吃训练框架文件,而是吃 .espdl。它类似 ONNX 的“模型描述”,但用 FlatBuffers 做得更轻,适合嵌入式加载。

  2. 算子是厨房里的工具:Conv、Gemm、Add、Mul 这些算子相当于刀、锅、烤盘。ESP-DL 把常见工具做了 ESP32-S3 / ESP32-P4 优化,还支持部分双核调度,让重活尽量两只手一起做。

  3. 内存规划像收纳箱:模型输入、中间结果、输出会挤在有限 RAM 里。静态内存规划器会按你给的 internal RAM 上限安排位置,在速度和省内存之间做取舍。

案例 1:把一个 sin 小模型量化成 .espdl

Section titled “案例 1:把一个 sin 小模型量化成 .espdl”

官方教程用 quantize_sin_model 演示 PTQ:先训练一个拟合 sin 函数的小 PyTorch 模型,再导出 ONNX,最后用 ESP-PPQ 量化。

Terminal window
python sin_model.py
python quantize_torch_model.py
# 或者:
python quantize_onnx_model.py

逐部分解释:

  • sin_model.py:在电脑上训练小模型,并导出权重 / ONNX,等于先把原始菜谱写出来。
  • quantize_torch_model.py:从 PyTorch 模型入口量化,适合你还保留训练代码的情况。
  • quantize_onnx_model.py:从 ONNX 入口量化,适合其他框架先统一转成 ONNX 的情况。
  • 输出通常包含 .espdl.info.json:一个给板子跑,一个给人检查,一个保存量化信息。

案例 2:把模型嵌进固件并做板端自测

Section titled “案例 2:把模型嵌进固件并做板端自测”

最简单的加载方式是把 .espdl 嵌到应用的 .rodata 区。这样工程一烧录,模型也跟着进 FLASH。

set(embed_files your_model_path/model_name.espdl)
idf_component_register(...)
target_add_aligned_binary_data(${COMPONENT_LIB} ${embed_files} BINARY)
#include "dl_model_base.hpp"
extern const uint8_t model_espdl[] asm("_binary_model_espdl_start");
dl::Model *model = new dl::Model((const char *)model_espdl,
fbs::MODEL_LOCATION_IN_FLASH_RODATA);
ESP_ERROR_CHECK(model->test());
model->profile(true);

逐部分解释:

  • target_add_aligned_binary_data:把模型当二进制资源塞进固件,并保证对齐。
  • _binary_model_espdl_start:链接器生成的符号,C++ 用它找到模型开头。
  • model->test():用导出时保存的测试输入输出,确认板端结果没有跑偏。
  • profile(true):同时看内存和耗时,并按耗时排序,方便先优化最慢层。

案例 3:部署 YOLO11n 这类检测模型

Section titled “案例 3:部署 YOLO11n 这类检测模型”

YOLO11n 示例展示了更接近真实产品的路线:选模型、量化、看误差,再把模型接到检测应用里。

from ppq import QuantizationSettingFactory
quant_setting = QuantizationSettingFactory.espdl_setting()
quant_setting.quantize_activation_setting.calib_algorithm = "percentile"
quant_setting.tqt_optimization = True
Terminal window
idf.py set-target esp32s3
idf.py flash monitor -p /dev/ttyUSB0

逐部分解释:

  • espdl_setting():选择和 ESP-DL 对齐的量化规则,而不是随便用通用量化配置。
  • percentile:校准激活值范围,减少少数极端值把量化区间拉歪。
  • tqt_optimization:用训练式的阈值微调降低精度损失,尤其适合检测模型。
  • idf.py set-target esp32s3:告诉 ESP-IDF 这次要按 ESP32-S3 编译,目标芯片不能含糊。
  1. 把平台混用:ESP32、ESP32-S3、ESP32-P4 的 .espdl 不能随便互换,否则推理结果可能不准。
  2. 忘记看算子支持表:模型里有不支持的算子,量化或部署会卡住;先查表比事后排错省很多时间。
  3. 以为 batch 可以随便开:ESP-DL 当前按 batch size 1 的部署方式来设计,新手从训练代码照搬多 batch 会踩坑。
  4. 把输入输出指针长期保存:推理时中间结果会复用同一块内存,model_input 里的数据可能被后续输出覆盖。

适用

  • ESP32-S3 / ESP32-P4 上的轻量视觉、语音、传感器分类、目标检测。
  • 已有 ONNX / PyTorch / TensorFlow 模型,愿意先做量化和板端验证。
  • 对云端延迟、联网依赖、隐私传输敏感,希望设备本地先做判断。
  • 需要和 ESP-IDF、Espressif BSP、组件注册表一起工作的项目。

不适用

  • 大语言模型、扩散模型、超大视觉模型;这类模型超出微控制器资源边界。
  • 需要动态 batch、复杂动态图、训练时推理混合的场景。
  • 算子很冷门且没人愿意实现;ESP-DL 的优势来自已优化算子。
  • 完全不想碰量化、编译、烧录、串口日志的纯 Web / 纯 App 项目。
  • 2018 年前后:Espressif 开始围绕 ESP 系列芯片建设 AIoT 软件栈,ESP-DL 成为本地推理这块拼图。
  • 2024 年 12 月:ESP-DL v3.0.0 发布,项目进入更系统的模型格式、算子和部署流程阶段。
  • 2025 年:模型 zoo、YOLO11n、猫检测示例和 ESP-PPQ 包名迁移陆续出现,说明它不只服务玩具 demo。
  • 2026 年:AutoQuant、TQT、operator agent、PIE SIMD 相关工具进入文档,优化重心从“能跑”走向“更准、更快、更少手调”。
  • 社区状态:GitHub 上约 1.1k stars,语言组成里 Assembly / C++ / C 占大头,很能说明它贴近芯片底层。
  • 嵌入式 AI 的核心不是“把模型复制过去”,而是“把模型改造成目标芯片能稳定执行的形状”。
  • .espdl 是部署边界:训练框架在电脑端,ESP-DL 在板端,中间靠量化和模型格式交接。
  • 速度来自一串工程选择:算子优化、双核调度、8bit LUT 激活、静态内存规划,而不是单一魔法开关。
  • 真正上线前要同时看三件事:精度是否还能接受、内存是否放得下、最慢层是否值得优化。
  • pytorch —— 负责训练和导出,ESP-DL 负责板端推理。
  • onnx —— 多框架模型进入 ESP-PPQ 的常见中转格式。
  • tensorflow-lite —— 同样面向端侧推理,但生态和模型格式不同。
  • esp-idf —— ESP-DL 工程编译、烧录、组件管理依赖它。
  • quantization —— 8bit / 16bit 量化是小芯片跑模型的关键前置步骤。
  • edge-ai —— ESP-DL 是边缘设备本地智能的具体实现之一。
  • cmsis-nn —— CMSIS-NN — Arm Cortex-M 的神经网络算子加速库
  • esphome —— ESPHome — 用 YAML 给 ESP32 / ESP8266 生成智能家居固件
  • mediapipe —— MediaPipe — Google ML 多模态流水线
  • ncnn —— ncnn — 腾讯开源的端侧神经网络推理框架