最近不少玩 STM32、ESP32 的朋友跟我说,想试试在单片机、RK3588 这些板子上跑 AI 功能,但上来就被「训练」「推理」两个词搞懵了:这不都是跑 AI 模型吗,有啥不一样?我写 C 代码几十年,怎么就没见过程序还要分「训练版」和「运行版」?
别急,咱们先从大家最熟悉的场景切入:你平时用的智能门锁里的人脸识别功能,本质就是个典型的 AI 应用,而它从无到有的过程,刚好把「训练」和「推理」的区别讲得明明白白。
一、先给个大白话定义:训练是上学刷题,推理是毕业干活
咱们先拿考驾照的过程打个比方,你一下子就能懂:
- 训练就像你在驾校练车:给你几千道科目一题库(带正确答案的标注数据),你反复做题、错题就纠正(算法迭代调整参数),练到模拟考试次次 90 分以上(模型精度达标),最后你脑子里就记住了所有交规知识(得到训练完成的模型参数)。
- 推理就像你拿到驾照后上路开车:遇到具体的路况(实际输入数据,比如人脸、语音指令),用你之前学到的交规知识直接做出判断(模型用训练好的参数计算得到结果),不需要再回去看题库。
回到 AI 的官方定义,咱们对应上就好理解了:
根据 NVIDIA 和 IBM 的官方解释:AI 的完整流程分为两个完全独立的阶段:
- AI 训练:是让模型「学会知识」的过程,通过海量带标注的样本数据,反复迭代调整模型内部的参数,直到模型对已知样本的判断准确率达到要求,最终输出一套可用的参数文件,就是我们常说的「AI 模型」。
- AI 推理:是把训练好的模型部署到实际设备上,输入真实的业务数据,直接用已经学好的参数计算出结果,是 AI 真正落地解决问题的阶段。
核心术语通俗解释(第一次接触 AI 必看)
首先给第一次接触 AI 的朋友补充几个核心术语的通俗解释,避免后面看懵:
- 神经网络模型:你可以理解为一套预设了计算规则的「答题模板」,训练就是给这个模板填充从数据里学到的「解题参数」,推理就是用填好参数的模板直接计算新问题的答案。
- 参数:就是模型从数据里学到的「知识」,比如人脸识别模型里存储的人脸特征值,类似你脑子里记的同事的长相特点。
- 标注数据:就是带正确答案的训练样本,比如人脸识别训练里的每一张人脸照片都会标注对应的人名,相当于考驾照时的题库答案。
很多新手上来就问:我能不能在单片机上自己训练模型?答案几乎是「几乎不可能」,就像你不可能一边上路开车一边学交规一样 —— 两个阶段的要求、资源消耗天差地别,咱们往下看。
二、看懂核心差异:嵌入式工程师只需要关心推理吗?
我把两个阶段的核心要求整理成了对比表,大家一眼就能看明白:
| 对比维度 | AI 训练 | AI 推理 |
|---|---|---|
| 核心目标 | 得到准确率足够高的模型参数 | 快速、稳定地输出预测结果 |
| 资源消耗 | 极高:通常需要几十上百张 GPU 集群,跑几天甚至几个月,显存、带宽要求极高 | 极低:嵌入式场景下甚至可以在几十 KB 内存的单片机上运行 |
| 运行环境 | 几乎都是离线云端服务器,对功耗不敏感 | 边缘设备、嵌入式板卡,优先考虑低延迟、低功耗 |
| 数据要求 | 需要海量带标注的训练集,比如做人脸识别需要几十万张带人名标注的人脸照片 | 只需要实际业务的输入数据,比如门锁摄像头拍到的某一张人脸 |
| 迭代频率 | 几个月甚至几年更新一次模型参数 | 每次输入新数据就运行一次,比如智能门锁每次有人按门铃就跑一次推理 |
| 精度要求 | 优先保证准确率,通常用 32 位浮点数计算 | 可以接受微小精度损失,优先保证速度和资源占用 |
看到这里嵌入式的朋友应该就懂了:咱们平时在嵌入式设备上做的绝大多数 AI 部署工作,都属于推理阶段的范畴,训练阶段基本都是算法工程师在云端完成的,我们拿到手的就是已经训练好的模型文件,只需要想办法把它移植到板子上跑起来就行。
举个真实的例子:智能门锁的人脸识别流程
咱们用大家天天见的智能门锁来拆解整个流程,你就完全懂了:
- 训练阶段(云端完成,绝大多数场景下和嵌入式工程师无关):
算法工程师收集几十万张不同年龄、不同光线、不同角度的人脸照片,每一张都标注好对应的人名,放到 GPU 集群里训练几周,得到一个几 MB 大小的人脸识别模型文件,在标准测试集下的识别准确率可达到 99.9% 以上(具体实际准确率需结合部署场景验证)。 - 推理阶段(嵌入式端实现,就是我们要做的工作):
我们把这个几 MB 的模型烧录到门锁的 MCU/NPU 里,有人按门铃的时候,摄像头拍一张人脸照片输入给模型,模型在百毫秒级以内计算出「这是住户张三」还是「陌生人」,直接控制门锁开不开。
这里提一下大家常听到的NPU(神经网络处理器):它就是专门给推理阶段设计的硬件,砍掉了 CPU、GPU 的通用计算能力,只保留了 AI 推理最常用的矩阵计算加速,就像专门算算术的计算器比通用的算盘快很多一样,(根据主流嵌入式 NPU 厂商公开参数,同等功耗下推理速度通常可达通用 CPU 的数倍到数十倍)。
三、嵌入式做 AI 推理的 3 个常见避坑点 + 排查建议
我接触过不少新手刚做嵌入式 AI 的时候,容易把训练阶段的要求套到推理上,踩了很多没必要的坑,这里给大家列 3 个最常见的,以及对应的排查方法:
坑 1:盲目追求大模型,忽略嵌入式资源限制
很多新手上来就想用手机上几 GB 的大模型跑在单片机上,完全忘了训练阶段的模型是「浮点数全精度」的,参数体积大、计算量高,根本不适合嵌入式。
这里给新手补充下「量化」的通俗解释:就是把模型里原本用 32 位浮点数存储的参数,压缩成 8 位甚至 4 位的整数,就像把高清照片压缩成小体积的普通照片,精度损失很小,但体积能缩小到原来的 1/4 甚至 1/8,计算速度也能有明显提升,刚好适合嵌入式的低资源场景。
排查建议:拿到模型先看两个参数:①模型体积(超过 10MB 的基本不适合普通单片机);②计算量(单位是 MAC,也就是乘加运算次数,STM32H7 这类单片机建议控制在 100MAC 以内)。如果太大,先要求算法工程师做量化,或者换轻量级模型架构(比如 MobileNet、Yolo-Fastest 等)。
坑 2:把训练的准确率当成推理的实际准确率
云端训练的时候准确率 99%,部署到板子上实际跑只有 90%?这太正常了:训练用的公开数据集大多是经过筛选的光线好、角度正的高质量样本,部分训练流程也会加入模拟复杂场景的增强数据,但嵌入式端实际采集的图像可能过曝、模糊、角度歪,这些都会影响准确率。
排查建议:拿到模型之后一定要做两步测试:①先用和训练集同质量的标准测试集跑一遍,确认移植过程没有引入精度损失;②再用实际场景采集的 1000 张以上本地数据测试,准确率达不到要求就反馈给算法工程师,用本地数据重新微调训练模型。
坑 3:推理只看 FPS 不看延迟
很多新手看性能只看FPS(每秒能处理多少帧数据,是衡量批量处理能力的吞吐量指标),但嵌入式场景下 ** 延迟(处理一帧数据需要多久)** 往往更重要:比如智能门锁的人脸识别,你 1 秒出结果和 0.1 秒出结果,用户体验天差地别,哪怕你 FPS 能到 100,但是单帧延迟超过 200ms,实际用起来就会觉得卡。
排查建议:测试性能的时候一定要同时测两个指标:①单帧推理延迟(从输入数据到输出结果的时间,实时场景建议控制在 100ms 以内);②FPS(连续跑多帧的平均速度,用于评估满负载下的功耗)。如果延迟太高,先检查有没有做量化,有没有用硬件 NPU 加速,有没有不必要的预处理 / 后处理操作。
给大家放一个最简单的 TFLite-Micro 推理代码示例,一看就懂
#include "tensorflow/lite/micro/micro_interpreter.h" #include "tensorflow/lite/micro/micro_mutable_op_resolver.h" #include "tensorflow/lite/schema/schema_generated.h" #include "model_data.h" // 训练好的量化模型文件,已经转成了C数组 // 定义模型需要用到的算子,这里只用了最基础的卷积和激活函数 static tflite::MicroMutableOpResolver<5> resolver; const tflite::Model* model = nullptr; tflite::MicroInterpreter* interpreter = nullptr; TfLiteTensor* input = nullptr; TfLiteTensor* output = nullptr; // 给模型分配内存,嵌入式场景下都是静态分配,避免堆溢出 constexpr int kTensorArenaSize = 64 * 1024; // 64KB内存足够跑轻量级关键词识别模型 uint8_t tensor_arena[kTensorArenaSize]; void ai_init() { // 1. 加载模型(已经是训练好、量化完成的参数) model = tflite::GetModel(g_model_data); if (model->version() != TFLITE_SCHEMA_VERSION) { printf("模型版本不匹配!\n"); return; } // 2. 注册需要用到的算子 resolver.AddConv2D(); resolver.AddMaxPool2D(); resolver.AddFullyConnected(); resolver.AddSoftmax(); resolver.AddReshape(); // 3. 初始化解释器 static tflite::MicroInterpreter static_interpreter( model, resolver, tensor_arena, kTensorArenaSize); interpreter = &static_interpreter; // 4. 分配张量内存 TfLiteStatus allocate_status = interpreter->AllocateTensors(); if (allocate_status != kTfLiteOk) { printf("内存分配失败!\n"); return; } // 5. 获取输入输出指针 input = interpreter->input(0); output = interpreter->output(0); printf("AI模型初始化完成!\n"); } void ai_infer(const uint8_t* input_data) { // 1. 填充输入数据(比如麦克风采集的音频特征、摄像头采集的图像数据) memcpy(input->data.uint8, input_data, input->bytes); // 2. 执行推理(就是用训练好的参数计算结果,不需要改任何参数) TfLiteStatus invoke_status = interpreter->Invoke(); if (invoke_status != kTfLiteOk) { printf("推理失败!\n"); return; } // 3. 处理输出结果(比如0=没检测到关键词,1=检测到“开门”指令) uint8_t result = output->data.uint8[0]; if (result > 200) { // 置信度阈值,根据实际场景调整 printf("检测到开门指令,正在开锁...\n"); } }你看,整个推理过程其实就是个普通的函数,和你平时写的传感器数据处理函数没有本质区别,只是内部计算逻辑是模型训练时确定好的而已。
四、新手必记的 4 条核心结论
最后给大家提炼几个最关键的结论,搞懂了这些,你就不会在 AI 入门的时候被概念绕晕了:
- 训练是造模型,推理是用模型:嵌入式工程师绝大多数日常工作都是处理推理阶段的部署,入门阶段不需要你自己训练模型,先把推理搞明白再碰训练也不迟。
- 训练看精度、看算力,推理看速度、看功耗:两个阶段的优化目标完全不一样,不要用训练的要求去衡量推理的效果,也不要盲目追求训练时的高精度而忽略嵌入式端的资源限制。
- 嵌入式跑 AI 不用怕资源不够:现在很多量化后的轻量级模型,只需要几百 KB 内存、几十 MHz 的 MCU 就能跑,比如关键词识别、人脸检测这些基础功能,STM32H7 这类单片机完全可以适配,甚至 ESP32-S3 都能跑简单的关键词识别。
- 不要纠结模型原理,先跑起来再说:很多新手一上来就想搞懂神经网络的数学原理,其实完全没必要,你就把模型当成一个「输入数据、输出结果」的黑盒函数,先把它移植到板子上跑通,再慢慢优化效果就好。
如果大家想试试在单片机上跑第一个 AI 推理应用,推荐可以先玩一下 GitHub 上的TensorFlow Lite Micro项目,官方提供了很多 STM32、RP2040 的示例,几行代码就能跑关键词识别、人员检测的 demo,入门非常友好。