端侧 AI · 15 天工程路线
目录首页 English
DAY 02

训练与推理

把可学习状态冻结为可移植、可验证的模型产物

建议阅读:约 20 分钟

学习目标

理解训练态与推理态的差异,并能把 checkpoint 转换为包含计算图、权重、版本和预处理契约的部署产物。

本章关键词

关键词解释ESP32 工程类比
eval 模式让 Dropout、BatchNorm 使用推理语义的模式。像从调试配置切换到量产配置。
优化器依据梯度更新参数的算法及其状态。像自动调参器;部署后不应留在固件里。
计算图以节点和边描述张量如何经过算子得到输出。像固件的数据流图或任务依赖图。
ONNX opset模型声明的算子语义版本。像通信协议版本;收发两端必须兼容。

承上:回顾与定位

上一章解释了张量、梯度和一次权重更新;本章追踪这些训练状态如何被冻结、转换并交付给不执行反向传播的设备 runtime。

从源头看今天

历史发展脉络

模型交付链由训练算法、运行模式、图表示与互操作标准共同形成。它把“一个实验能复现”推进为“一个产物能在另一套 runtime 上保持语义”。

1958

感知机学习规则形成最小训练循环

感知机依据预测错误修改连接权重,把样本、预测、误差、更新连接成闭环。虽然模型简单,它已经区分了“正在被样本改变的参数”和“使用当前参数给出判断”这两个时刻。

Rosenblatt 感知机原始论文 ↗
2014

Dropout 明确展示同一模块的两套运行语义

Dropout 在训练时随机丢弃单元,以降低共适应;测试时则使用完整网络的确定性近似。它使工程师必须显式切换模式,否则同一输入会因训练期随机行为而得到不稳定输出。

Dropout 原始论文 ↗
2017

轻量 runtime 把设备端职责收束为低延迟前向执行

TensorFlow Lite 的开发者预览面向移动和嵌入式设备,强调轻量、快速初始化与硬件加速。模型从训练框架转换为受限部署格式,训练状态、调试便利性与设备运行约束开始由工具链明确分工。

TensorFlow Lite 官方发布说明 ↗
2014

Caffe 用声明式网络与权重文件推动模型复用

Caffe 将网络结构、训练配置与学习到的参数组织为可交换产物,并以层为扩展单元。它展示了模型可以脱离单个研究脚本被分享和部署,也暴露了框架专属层与格式绑定的问题。

Caffe 原始论文 ↗
2017

ONNX v1 将互操作写成公开的图与算子契约

ONNX v1 面向多个框架发布生产就绪版本,以开放图格式和算子集推动模型转移。导出器、转换器和 runtime 从此可以围绕共同 IR 协作,但每一方仍必须支持模型声明的域与 opset。

ONNX v1 官方发布说明 ↗
2023

GGUF 强化单文件、可扩展与快速加载

GGUF 作为 GGML 系执行器的模型格式,把张量与键值 metadata 放入可扩展的二进制容器,并取代早期 GGML、GGMF、GGJT 格式。它说明 LLM 部署不仅要保存权重,还要可靠携带架构和 tokenizer 等解释信息。

GGUF 官方规范 ↗
今天为什么仍然重要: 今天应把 checkpoint、导出图、权重、metadata 与前后处理作为一个版本化模型包,并沿转换链逐层比较输出。
借熟悉的系统建立直觉

类比图解

从风洞试飞到封装进无人机的飞控程序

训练像在风洞中反复试飞:工程师改变参数,注入扰动,记录每次偏航并调整控制律。推理像量产无人机起飞,机上只带定型的控制表、传感器接口和必要状态,不会把整座风洞、试验日志与调参团队一同装进去。导出则是把试验配置审定为可烧录版本。

风洞与扰动 数据批次、增强和 Dropout 等训练随机性
调参工程师 优化器读取梯度并维护动量等更新状态
审定配置 eval 模式、checkpoint 选择与导出图冻结
机载飞控 设备 runtime 只执行受验证的前向路径

类比的边界: 飞控通常由明确物理模型和安全论证构成,而神经网络是统计模型,不能因“已定型”就视为覆盖所有现场条件。类比也不代表导出后图永远不变:常量折叠、量化与后端分区仍会改变数值和资源行为。

本章讲解

训练循环同时推进参数状态与优化器状态

一次 step 不只是执行 forward 与减去梯度:Adam 等优化器还维护每个参数的历史统计,学习率调度器也有自己的步数。若只恢复权重却遗漏优化器和 epoch,续训轨迹会改变;而这些状态对纯推理毫无用途。工程上应把“可续训 checkpoint”和“可部署权重”作为两种产物命名、校验和归档。

模式切换必须逐模块验证,不能只相信一个布尔值

eval 会递归切换 Dropout、BatchNorm 等模块的行为,但自定义层可能仍读取 training 标志或随机数。BatchNorm 的 running mean/variance 还可能因小批次、数据漂移而失真。导出前应对同一输入连续运行多次确认输出确定,并逐项检查随机算子、统计 buffer 和 requires-grad 状态是否符合预期。

部署图是经变换后的新产物,不是 checkpoint 的复印件

导出器可能内联函数、删除反向节点、折叠常量,把 Conv 与 BatchNorm 的参数合并,或依据 example input 固化控制流。这样能降低调度和内存开销,却也可能只捕获示例走过的分支。若模型包含依赖数据的循环、动态 shape 或自定义算子,应明确导出策略,不能假设源程序的所有路径都被保存。

把格式拆成语法、语义与随附资产三层

schema 只回答字段如何编码,算子规范才回答节点应算什么,tokenizer、标签表或归一化参数则可能存在 metadata 或外部文件中。解析成功只证明语法有效;缺少算子语义会导致 runtime 拒绝,缺少资产则可能运行却解释错输出。交付清单应逐层列出校验方式,而不是只记录一个模型文件哈希。

IR、opset 与 runtime 版本是三把不同的锁

IR version 约束模型容器与图结构,opset 约束特定域中算子的签名和语义,runtime 版本决定实现覆盖。降 opset 不是改一个整数:若旧集合没有等价表达,转换器必须分解节点或直接失败。自定义 domain 还要求随部署提供实现。兼容表应记录三者组合及目标芯片,而非笼统写“支持 ONNX”。

转换器会重写表达,必须审计差异清单

转换可能把一个高层算子展开为子图、把常量计算提前、把 NCHW 换成 NHWC,或将权重存为不同 dtype。数学上等价的重写仍可能改变舍入、workspace 和 backend 分区。应在转换日志中保存新增、删除、替换的节点统计,并对关键中间张量建立名称映射,避免最终输出异常时只能盲猜。

建立模型 ABI 测试包,而不只保存模型本体

为每个模型版本附上输入名称、shape 范围、dtype、量纲、前后处理版本和数个 golden 样本;样本应包含正常值、边界 shape 与非法输入。CI 先做 schema/checker 校验,再由目标 runtime 加载并比较输出容差。若模型使用外部权重或 tokenizer 文件,还要校验相对路径与哈希,防止“主文件没变、配套资产已漂移”。

让数据真正跑起来

动态过程演示

模型穿越五道格式闸门

同一组测试数据伴随模型从训练框架走到目标 backend;每道闸门检查一种契约,任何红灯都会停在最接近根因的位置。

步骤 1 / 6

框架对象 · modules + parameters + control flow

展开实际执行过的模块与参数引用

观察点

源程序可以包含无法直接序列化的动态行为

循环 / 返回条件: 当 runtime、opset、转换器或配套资产升级时,从受影响的闸门重新播放;golden 输入始终随模型同行,形成可回归的格式护照。

查看静态全景图
data + labels → train state → checkpoint
                              │ eval/freeze/export
                              ▼
input contract → graph + weights + metadata → runtime/backend

代码或命令示例

model.eval()
export(model, example_input, opset_version=...)
assert_close(reference_output, runtime_output)
# 同时保存 tokenizer/labels/preprocess/version

动手实验

训练一个小模型并保存 checkpoint;切换 eval 后导出 ONNX 或 LiteRT,列出图、权重、opset、输入 shape/dtype 和前处理版本。用三组金输入比较框架、导出图与目标 runtime 的中间或最终输出。
实验记录与导出

工程陷阱

避免误判: 只保存权重文件,或看到转换成功就认为语义一致。部署产物还依赖图版本、算子集、前后处理、标签与 runtime;每次变换都必须通过金向量验证。

核心测试

完成 3 道单选题后提交;提交前不会显示答案。

1. 为什么推理前要调用 model.eval()?
2. ONNX opset 主要声明什么?
3. 转换后最可靠的第一项验证是什么?

一起把本章讲清楚

在 GitHub 上讨论本章

登录 GitHub 后提问、补充实测或分享你的实现;评论会保存在本课程的 GitHub Discussions 中。

评论区需要 JavaScript;也可以直接打开 GitHub 讨论区: 打开 GitHub 讨论区 ↗

延伸阅读

启下:下一章如何使用本章能力

下一章研究量化:在明确模型 ABI 后,用校准与误差证据把浮点表示映射到低比特整数。

下一天: Day 3 · 模型量化