2、环境搭建:Python、ONNX Runtime、MicroPython/嵌入式工具链的安装与配置,以及开发板选型
TinyML 开发与传统嵌入式开发最大的差异在于:它处于“机器学习模型训练”与“微控制器资源受限部署”的交汇点。因此,环境搭建并非简单地安装一个 IDE,而是需要构建一条从 PC 端模型转换到设备端推理的完整工具链。本章将围绕 Python 基础环境、ONNX Runtime 推理引擎、MicroPython 与嵌入式交叉编译工具链的配置,以及开发板选型四个核心模块展开,帮助读者建立一套可复现、可调试的实战环境。
2.1 Python 基础环境与虚拟环境管理
核心原理:Python 是 TinyML 工具链的粘合剂。模型训练、ONNX 导出、量化校准、固件生成等环节均依赖 Python 生态。但不同工具对 Python 版本要求各异(例如 TensorFlow 2.10 最高支持 Python 3.10,而最新版 onnxruntime 可能要求 3.11+),因此必须使用虚拟环境隔离项目依赖,避免版本冲突。
操作流程:推荐使用 Miniconda 或 Python 自带的 venv 模块。以下为基于 Miniconda 的推荐配置流程:
# 创建 Python 3.10 虚拟环境
conda create -n tinyml python=3.10 -y
conda activate tinyml
# 安装基础依赖
pip install --upgrade pip
pip install numpy==1.24.3 scipy==1.10.1
pip install onnx==1.14.0 onnxruntime==1.16.0
pip install onnx-simplifier==0.4.17 netron==7.3.4
案例拆解:某学员在 Windows 上直接使用系统 Python 安装 onnxruntime,导致与已安装的 TensorFlow 2.15 产生 protobuf 版本冲突(TensorFlow 要求 protobuf<3.21,而 onnxruntime 要求 protobuf>=3.20.3)。通过创建独立虚拟环境后,两个项目互不干扰,问题解决。这验证了虚拟环境在 TinyML 工具链中的必要性。
2.2 ONNX Runtime 的安装与验证
核心原理:ONNX Runtime 是微软开源的跨平台推理引擎,支持 CPU、GPU、NPU 等多种执行提供程序(Execution Provider)。在 TinyML 场景中,我们主要使用其 CPU 版本进行模型正确性验证,以及通过 onnxruntime-extensions 进行自定义算子注册。
判断方法:安装完成后,通过以下脚本验证环境是否正常:
import onnxruntime as ort
print("ONNX Runtime version:", ort.__version__)
print("Available providers:", ort.get_available_providers())
# 创建一个最简单的 ONNX 模型进行推理测试
import onnx
from onnx import helper, TensorProto
# 定义输入输出
X = helper.make_tensor_value_info('input', TensorProto.FLOAT, [1, 10])
Y = helper.make_tensor_value_info('output', TensorProto.FLOAT, [1, 10])
# 定义节点(Relu)
node = helper.make_node('Relu', ['input'], ['output'])
# 创建图
graph = helper.make_graph([node], 'test_graph', [X], [Y])
model = helper.make_model(graph, opset_imports=[helper.make_opsetid("", 13)])
onnx.save(model, 'test_relu.onnx')
# 推理
sess = ort.InferenceSession('test_relu.onnx')
import numpy as np
result = sess.run(None, {'input': np.random.randn(1, 10).astype(np.float32)})
print("Inference OK, output shape:", result[0].shape)
常见误区:许多初学者直接使用 pip install onnxruntime 安装 GPU 版本,但在无 NVIDIA GPU 的机器上会导致推理失败。应明确安装 onnxruntime(CPU 版)或 onnxruntime-gpu(GPU 版),两者不可共存。
2.3 MicroPython 与嵌入式工具链配置
核心原理:MicroPython 是 Python 3 的精简实现,专为微控制器设计。它允许在资源受限设备上直接运行 Python 代码,但推理性能远低于 C 语言。因此,TinyML 部署通常采用“混合模式”:模型权重以 C 数组形式嵌入固件,而控制逻辑(如音频采集、预处理、结果输出)使用 MicroPython 编写。
操作流程:以 ESP32-S3 为例,配置 MicroPython 环境需要以下步骤:
- 下载官方 MicroPython 固件(.bin 文件)
- 使用 esptool 擦除 Flash 并烧录固件
- 安装 ampy 或 rshell 工具用于文件传输
- 使用 Thonny IDE 进行交互式开发
# 安装 esptool 和 ampy
pip install esptool adafruit-ampy
# 擦除 Flash
esptool.py --port COM3 erase_flash
# 烧录 MicroPython 固件
esptool.py --port COM3 --baud 460800 write_flash -z 0x1000 ESP32_GENERIC_S3-20231005-v1.21.0.bin
# 上传 Python 文件到开发板
ampy --port COM3 put main.py
案例拆解:某项目需要部署一个 20KB 的唤醒词检测模型到 ESP32-S3。由于 MicroPython 的浮点运算速度较慢(约 10 倍于 C 语言),直接使用 MicroPython 加载 ONNX 模型推理耗时 800ms,远超实时要求。解决方案是:使用 onnx2c 将模型转换为 C 数组,编译进固件,而 MicroPython 仅负责 I2S 音频采集和结果回调。最终推理耗时降至 45ms,满足实时性要求。
2.4 开发板选型决策
核心原理:开发板选型是 TinyML 项目成败的关键。核心约束包括:SRAM 容量(模型权重和中间特征图必须驻留 SRAM)、Flash 容量(固件+模型存储)、算力(MACs/s)、外设接口(I2S 麦克风、DMA 通道)以及功耗预算。
对比分析:以下为常见 TinyML 开发板的对比表:
| 开发板 | MCU | SRAM | Flash | 算力 | I2S | MicroPython | 典型场景 |
|---|---|---|---|---|---|---|---|
| ESP32-S3-DevKitC | Xtensa LX7 240MHz | 512KB | 8MB | ~600 MACs/cycle | 支持 | 官方支持 | 唤醒词、关键词识别 |
| STM32F746G-DISCO | Cortex-M7 216MHz | 320KB | 1MB | ~400 MACs/cycle | 支持 | 社区移植 | 工业级语音、振动分析 |
| Raspberry Pi Pico | RP2040 133MHz | 264KB | 2MB | ~200 MACs/cycle | 需外扩 | 官方支持 | 教育、原型验证 |
| nRF52840-DK | Cortex-M4F 64MHz | 256KB | 1MB | ~100 MACs/cycle | 支持 | 官方支持 | BLE 低功耗唤醒 |
判断方法:选型时遵循“SRAM 优先”原则。首先估算模型所需 SRAM:权重大小 + 最大中间特征图大小 × 2(输入输出缓冲)。例如,一个 20KB 的 int8 量化模型,中间特征图最大 10KB,则至少需要 40KB SRAM。其次考虑算力:若需实时处理 16kHz 音频,每帧 20ms,则需在 20ms 内完成推理,即算力需大于 模型MACs / 0.02s。
案例拆解:某智能门锁项目需部署 3 个唤醒词(“你好小智”、“打开门锁”、“关闭门锁”),模型为 DS-CNN 架构,int8 量化后 35KB。选择 ESP32-S3 后,实际测试 SRAM 占用 68KB(含音频缓冲),推理耗时 32ms,满足 50ms 实时要求。若选择 nRF52840,则 SRAM 可能不足(35KB 权重 + 15KB 特征图 + 音频缓冲 16KB = 66KB,接近极限),且推理耗时可能超过 100ms。