TinyML实战入门:在单片机上部署机器学习模型的完整流程

发布时间:2026/10/20 14:16:28
TinyML实战入门:在单片机上部署机器学习模型的完整流程 TinyML 这个名字这两年出现在嵌入式社区交流里的频率越来越高。说白了它就是把机器学习模型压缩到可以跑在单片机上——内存占用从几百 MB 压到几十 KB功耗从几瓦降到毫瓦级推理过程完全在本地完成不依赖云服务器。很多人一听“机器学习”就下意识想躲也有不少嵌入式老手觉得这是另一个领域的事儿。我在带过几个从零起步的朋友之后越来越确信这件事没有想象中难关键是路径别选错。这篇是系列的第一篇目标很简单——把概念讲明白把开发环境搭起来再真正在板子上跑通一个最小可用的推理程序。它适合三类人想拓展技能栈的嵌入式工程师、想了解模型怎么落地的算法工程师、以及刚入手这块但又不知道从哪开始的学生。1. 先搞明白 TinyML 到底是什么1.1 它凭什么把模型塞进单片机要理解 TinyML先要认清微控制器和普通电脑的差距。电脑跑一个常规神经网络内存通常是几个 GBCPU 主频几个 GHz还有独立显卡辅助。单片机呢常见的是几十 MHz 的 CPUSRAM 可能只有几十到几百 KBFlash 能到 1MB 就算不错了。这种差距不是“优化一下”就能抹平的而是得把模型的存储形态和计算形态都做了根本性的修改。这里最关键的一招是量化。神经网络模型里权重和激活值默认是 float32 表示一个数占 4 个字节。量化把它变成 int8一个数只占 1 个字节模型体积直接缩到四分之一。不止是存得下计算时整型运算在单片机上比浮点快很多内存带宽压力也小很多。举个具体例子一个全精度训练好的 1MB 模型量化之后大约 256KB再把运行时和算子代码算进去塞进 1MB Flash 的板子是可行的。但这还不够。真正占用 RAM 的大头是推理过程中的中间激活值不是权重本身。打个比方神经网络像一条流水线权重是每道工序的“模具”激活值是“半成品”。工序的人数少但半成品可能堆在流水线上占不少地方。所以 TinyML 除了用量化压缩模型文件工程上还要尽量控制网络结构、降低中间层的特征通道数甚至避免某些特别吃内存的算子结构。这就是为什么 TinyML 从业者总说“设计一个能跑得动的模型”比“把大模型硬塞进去”更重要。1.2 哪些场景真正需要 TinyML讲应用场景之前先泼一盆冷水不是所有 AI 场景都需要往单片机上搬。如果你要跑的是大语言模型或者高清图像生成别想这事老老实实用服务器或边缘盒子。TinyML 适合的是那种“识别/判断任务很轻量但对成本、功耗、延时、隐私有硬要求”的场景。最典型的例子是语音唤醒。智能音箱里那个“你好某某”的唤醒词其实很多产品就是一颗小芯片加一个 TinyML 模型在本地时刻监听只有在唤醒确认之后才把主处理器拉起来。低功耗靠的是整体策略平时只有这颗小芯片在工作功耗能压到毫瓦级一节纽扣电池能撑很久。换做人坐在电脑前持续跑神经网络功耗和成本完全不是一个量级。工业预测性维护是另一个热门方向。在电机或泵上贴一个带加速度计的传感器节点用 TinyML 模型在本地分析振动波形判断是否出现异常。数据不出设备不占网络带宽出问题还能在几毫秒内给出结果比把振动信号上传云端判断靠谱得多。还有可穿戴设备里的手势识别、农业物联网里的环境状态分类、医疗贴片里的异常心电检测逻辑都差不多数据敏感、设备分散、不能依赖网络。在动手之前想清楚自己的场景是不是真的需要 TinyML这很重要。它能省电、省钱、省带宽但会牺牲一部分“模型可以随便改、设备可以随便加资源”的灵活性。需求不匹配后面的路会特别别扭。2. 动工前要准备的“三样东西”2.1 嵌入式基本功要到什么程度很多人一听 TinyML 要写 C、要配置工具链、要烧录固件就想着是不是得先把单片机的寄存器全部啃完。其实不需要。我自己的体会是有这三个能力就能顺利起步能看懂 C 语言的基本结构与指针能改一改别人写好的工程如果写过 C 更好引擎部分用到但初学不要求精通。会使用串口调试能通过串口打印信息来判断程序跑到了哪一步。会编译、烧录一个最简单的工程比如控制 LED 闪烁哪怕全程跟着教程敲命令都行。嵌入式领域最劝退新人的不是代码本身而是“不知道程序跑没跑、死在哪里了”。串口打印就是最简单的调试武器。你只要能把一条打印从板子发到电脑上后面的 TinyML 开发进度就会顺畅很多。如果单片机也是一片空白也别慌。第一步先不要碰 AI先花一两天把一个“点灯 串口打印”的工程跑通。这件事的价值在于把工具链里的编译、烧录、串口通信三个环节打通后面所有 TinyML 实验都是在这条已经验证过的链路上做加法。2.2 机器学习知识需要补哪些反向传播、梯度下降这些训练细节在刚开始部署 TinyML 模型时基本用不上。你需要的是对神经网络“前向推理”的感觉这比会调参训练重要得多。核心就几句一个模型本质上就是一个函数输入一个张量输出一个张量。中间每一层做的都是把上一个张量变成下一个张量。张量是有形状的多维数组。比如语音特征常常是“若干个时间窗口 × 每个窗口的数值”的二维结构图像则往往是“高 × 宽 × 通道”的三维结构。卷积层和全连接层的差别不用深究先知道它们是“对输入做某种变换”就行了。等你看到部署日志里出现某个算子名字时再回头查它的具体作用效率更高。最容易卡住初学者的概念是“输入张量”和“输出张量”的处理。比如一个图像分类模型输入往往是“1 × 224 × 224 × 3”的数组输出是“1 × 10”的数组。部署到单片机上要做的就是把一张真实的图像数据塞进输入数组推理完再读输出数组找到数值最大的那个下标作为分类结果。听起来是不是根本没多神秘2.3 一套可执行的入门路线我见过太多人一上来就下载一个复杂模型想在板子上跑 YOLO结果内存直接爆掉心态也崩了。合理的路线应该是这样的跑通一个最小示例确认“编译 → 烧录 → 串口输出”的链路没问题。找一个只有一层或者几层全连接的简单分类模型部署上去理解数据是怎么从输入张量流到输出张量的。修改模型输入比如从跑官方示例数据换成你自己录的一段数据观察输出结果怎么变化。用少量真实采集的数据训练一个自己的小模型走完整的“训练 → 量化 → 部署”流程。最后才是为了压缩内存、降低延迟去做算子优化和模型结构精简。前四步都能顺畅走完你其实已经算入门了。第五步属于进阶真正体现了 TinyML 工程和普通机器学习开发的差异。这个系列的后续文章会把每一步展开这一篇重点完成第一步和第二步之间的衔接。3. 硬件选型与开发环境搭建3.1 开发板怎么选硬件选择上有一个容易被忽略的真相入门阶段买一块“参数够用、社区示例丰富”的板子比买一块“旗舰性能”的板子有用得多。TinyML 跑不跑得动最核心的指标不是主频而是 SRAM 大小和 Flash 大小。我的建议是选 SRAM 在 192KB 以上、Flash 在 512KB 以上的板子空间不至于太紧张能覆盖大部分入门示例。如果目标是视觉类应用尽量挑 SRAM 更大256KB 以上的型号否则运行几个模型就会发现内存紧张得可怜。选生态成熟的板子。所谓成熟不是看参数而是看有没有大量可参考的工程、有没有官方示例工程模板、烧录调试是否方便。这一步直接影响你后续排查问题的效率。串口得方便接。很多调试信息都要靠串口打印如果还得自己飞线或者折腾驱动体验会直线下降。预算方面几十元的板子足够走完入门阶段。千万不要一上来就买几千元的高性能板子反而容易因为没人用、示例稀少而卡壳。3.2 搭建环境的完整流程以常见的 Arm Cortex-M 内核开发板为例整个环境搭建可以拆成三块编译工具链、烧录工具、串口工具。我这边的习惯是用开源工具链配合命令行完成清晰且不依赖某个特定 IDE方便后面自动化。安装编译工具链的命令大致是这样不同操作系统命令不同思路一致sudo apt install gcc-arm-none-eabi cmake make安装完之后验证一下版本arm-none-eabi-gcc --version如果能看到类似arm-none-eabi-gcc (GNU Arm Embedded Toolchain 10.x.x)的输出说明编译器装好了。然后是烧录工具常用的开源烧录方式是 OpenOCD。安装后通过板载调试器连接板子烧录命令类似openocd -f interface.cfg -f target.cfg -c program build/app.elf verify reset exit这里的两个配置文件分别对应调试器和芯片型号通常在板级示例里都能找到不需要自己从头写。串口工具就不固定了Linux 环境下可以是任何支持 tty 的串口终端Windows 下用各种串口助手都行。注意波特率要和工程代码里初始化的一致一般是 115200。3.3 先让 LED 闪起来确保环境没问题环境装好后第一件事不是跑神经网络而是先跑一个 LED 闪烁程序。这一步能够验证编译链路的配置没问题、烧录过程没问题、板子时钟和基本外设初始化正常。用伪代码示意逻辑十分简单int main(void) { board_init(); led_init(); while (1) { led_on(); delay_ms(500); led_off(); delay_ms(500); } }把工程编译烧录进去如果 LED 能按半秒间隔闪烁就说明开发板的基本通路全部打通了。紧接着再加一行串口打印每次进入主循环打印一个计数printf(counter: %d\n, counter);然后在电脑上打开串口终端看到不断滚动的计数说明串口链路也是通的。走到这一步就具备开始 TinyML 实验的全部基础了。这个“点灯确认”步骤很多教程会直接跳过但我强烈建议别省它会把后续所有“奇怪问题”的排查范围缩小一大半。4. 从训练好的模型到单片机最小部署流程4.1 模型量化与格式转换这一节是整个系列里最核心的实操环节。我以“关键词唤醒”这一类任务为例模型输入是一段音频特征输出是几个分类标签。实际用到的网络可以是一个若干层全连接加 Softmax 的小网络参数规模很小特别适合演示。首先要有一个训练好的模型可以是你自己用少量数据训练出来的也可以先用某个社区公开的小模型。接下来做量化转换。这里我用的是一个比较主流的转换工具代码看起来像这样import tensorflow as tf converter tf.lite.TFLiteConverter.from_keras_model(model) converter.optimizations [tf.lite.Optimize.DEFAULT] converter.representative_dataset representative_dataset tflite_model converter.convert() with open(model.tflite, wb) as f: f.write(tflite_model)注意representative_dataset是量化时必需的“校准数据”。它的作用是提供一批有代表性的输入样本让转换工具统计激活值的取值范围从而确定每一层量化的缩放系数。校准数据并不需要带标签普通训练集输入就够了给 100 个左右的样本就能得到不错的结果。如果你在转换时省略校准数据集会得到纯 float32 模型体积和内存消耗都会大很多到单片机上大概率跑不顺。这是很多新手第一次转换就失败的原因。4.2 生成 C 数组并接入工程模型转换完成后得到的是一个.tflite文件但单片机工程里没法直接读文件系统最常见的做法是把它变成一个 C 语言数组直接烧进 Flash。我习惯在 Linux 下用一条命令完成xxd -i model.tflite model_data.cc这条命令会把模型文件的所有字节输出成十六进制初始化列表保存为model_data.cc。文件顶部会有一个变量名通常是model_tflite对应的还有一个model_tflite_len表示长度。如果用的是其他工具链也可以用写脚本读取文件并生成 C 数组本质思路一样。把生成的.cc文件添加进工程后记得在部署代码里声明对这个外部数组的引用extern const unsigned char model_tflite[]; extern const unsigned int model_tflite_len;模型和分析代码就分开了。以后想换模型只需要重新生成这个数组文件再编译一次。4.3 加载、推理、读取结果到了这一步整个部署流程的主体就出来了。省略掉与具体芯片相关的初始化代码核心逻辑是四个步骤创建解释器、分配张量内存、填入输入、执行推理。以轻量级推理框架 TFLMTensorFlow Lite for Microcontrollers为例代码骨架大致如下static tflite::MicroMutableOpResolver10 resolver; resolver.AddFullyConnected(); resolver.AddSoftmax(); static uint8_t tensor_arena[40 * 1024]; tflite::MicroInterpreter interpreter(model_tflite, resolver, tensor_arena, sizeof(tensor_arena)); interpreter.AllocateTensors(); auto* input interpreter.input(0); // 将原始数据按输入张量的 scale 和 zero_point 做量化后写入 input-data.int8 interpreter.Invoke(); auto* output interpreter.output(0);这里的tensor_arena是模型在推理时使用的“内存池”大小需要根据模型手动调整。模型越大、中间激活值越多需要的 arena 就越大。刚开始可以用一个较大的值比如 40KB 或 60KB跑通了再逐步调小找到下界。关于输入数据的处理有个细节容易被忽略模型量化后期望的输入类型通常是 int8不是 float。也就是说你得先把真实采集到的浮点特征映射到 int8 范围内。映射关系由输入张量的scale和zero_point决定公式是q round(real_value / scale) zero_point输出反方向算回来real_value (output_int8_value - zero_point) * scale推理完成后取出 output 张量里数值最大的下标那就是模型预测的类别。4.4 一次完整的实操记录我拿一块 SRAM 256KB、Flash 1MB 的开发板做实验部署一个简单的音频特征分类模型。输入的音频特征总共 128 维模型输出 3 个类别。整个流程走下来几个关键数据是这样的先说量化效果。全精度模型文件大小是 96KBint8 量化后变成 25KBFlash 占用压力大幅下降。再说内存arena 从 16KB 起步试运行时报错“arena allocation is too small”改成 32KB 后正常。这说明这个简单模型的实际激活内存需求大约在 20KB 上下。串口输出打印了预测结果和一次推理耗时当时测下来单个样本推理大约几毫秒对这个场景来说完全够用。第一次在单片机上看到自己的模型给出正确分类结果时那种“原来也不是很难”的直观感受和看多少篇教程都不一样。5. 部署过程中常见的“坑”与排查思路5.1 内存不足与 arena新手遇到的第一个报错十有八九是 arena 不够。这类报错明确、好定位因为框架通常会直接提示分配失败。解决方案就三条路调大 tensor_arena 数组换用更小的模型启用模型优化压缩中间激活值。实际项目中arena 大小需要跑几次才能确定。我个人习惯是先把数组设成 60KB 跑通再二分法往下调。调到恰好不报错的上限就是比较合适的大小。别一上来就追求极致的 RAM 占用那不是入门阶段该做的事。5.2 算子不兼容与注册每个模型里都有若干算子而 MCU 上的推理框架并不会把所有算子都内置进去。加载模型时遇到“didnt find op”之类的错误多半是某个算子在解释器里没有注册。解决办法是在调用解释器之前用resolver.AddXxx()显式注册对应的算子。如果你在编程时不确定模型里有哪些算子可以用前面的 Python 转换工具在 PC 上先解析一遍模型把算子列表打印出来再逐个注册。需要注意的是有的算子比如 Softmaxregister 版本很多请按模型实际版本注册不然运行结果会异常。5.3 精度下降与输入输出映射量化后的模型精度下降是正常现象但如果下降得离谱就要查数据映射。一个非常典型的错误是模型已经量化成 int8但输入张量里塞的还是 float 数据或者中间没按scale和zero_point做转换把 int8 当成了纯整数处理。还有一类问题出现在输出侧。不少模型输出层是反量化的输出张量本身可能是 int8 也可能是 float 类型得先确认类型再做后续处理。如果直接拿字节当成 float 解析结果当然全乱。第二个常见原因是校准集不好。之前提到的representative_dataset覆盖范围太窄导致量化时激活值统计不准部署后的精度就会显著变差。多采集不同场景下的数据重新转换一次往往能解决一大半精度问题。5.4 常见问题速查表现象可能原因处理建议部署后板子完全没反应编译烧录链路没跑通先回退到 LED 闪烁实验确认基础环境串口无打印波特率不对或串口引脚接错检查初始化代码与终端配置是否一致加载模型报 op 错误模型包含未注册算子打印算子列表逐一注册arena allocation 太小内存池不够增大 arena 或换小模型烧录成功但推理结果全乱输入数据未正确量化确认 scale 与 zero_point 计算后再填充输入精度比 PC 上低不少校准集不具代表性扩充校准数据重新量化推理耗时无法接受模型冗余或未用优化模式考虑量化、算子裁剪或换轻量网络结构这几点如果能在实验阶段就避开后面做真实项目能省下大量时间。6. 系列后续规划与我给初学者的几点建议6.1 后续计划这一篇只完成了“认识 TinyML、搭环境、跑通一个最小模型”这个阶段。接下来几篇我会沿着更深入的路径继续写第二篇重点讲量化原理与剪枝让你能自己把控模型体积和精度的取舍第三篇用一个真实传感器数据分类项目把完整的“数据采集 → 训练 → 部署 → 调试”走一遍第四篇再讲性能优化包括算子加速、内存复用、低功耗调度这些真正影响产品落地的细节。6.2 给初学者的几点提醒一路带人走过来我觉得有几点经验值得在这里先分享。第一不要一上来就追求“高级模型”。先用最小的模型把整条链路跑通比纠结模型精度重要得多。链路通了后面怎么换模型都顺。第二善用串口打印。在代码的关键位置加上打印能帮你迅速判断是模型没加载、内存不够、还是推理没执行。这不丢人反而是最有效的调试方式。第三量化不是万能的。有些模型结构量化后精度衰减非常严重这时候要从模型结构本身找原因比如某些层是否可以用其他结构替代。不要死磕一个方案。第四先“能跑”再“想省”。我见过不少人在第一个实验就想用极致的手段优化内存占用结果变量太多问题怎么来的都搞不清楚。把基准跑出来再做针对性优化才是高效路径。最后说一句自己的体会TinyML 最大的门槛不是技术难度而是“心智模型”的转变。习惯了服务器上无限资源的人刚面对单片机会觉得处处受制但只要亲手把一个模型部署到几毫瓦功耗的设备上并且看它稳定地跑起来这种约束下的成就感是纯软件项目很难给的。按这个系列走下来你很快也能体会到。

关于本文作者

来自尧图内容编辑团队

尧图内容编辑团队 内容团队

尧图内容编辑团队

本文由尧图网络内容编辑团队执笔。团队由资深项目经理、前端工程师与设计师组成,所有内容均来自亲手交付的真实项目,先讲清问题、再给出可落地的解法。尧图深耕北京网站建设十年,服务过京华建材集团、智造科技等各行业客户,把一线经验沉淀为可复用的行业观察。

  • 十年建站经验,覆盖建材、制造、服务、文创等
  • 项目经理把关选题与事实准确性
  • 工程师与设计师联合撰写专业细节
  • 统一编辑规范,保证文风与排版一致
  • 每月复盘转化数据,迭代选题方向

延伸阅读

相关资讯与近期热门内容

深度阅读推荐

建站决策前值得细读的三篇

网站改版的5个关键决策
2024-08-12

网站改版的5个关键决策

什么时候该改版、改到什么程度、如何避免流量掉光,京华建材集团改版复盘给出答案。

获取专属建站方案

看完文章,把您的行业与预算告诉我们,免费获取一份量身定制的官网建设方案与报价。

立即免费咨询