神经网络基础
从张量、层与损失函数建立神经网络直觉
建议阅读:约 18 分钟
学习目标
本章关键词
| 关键词 | 解释 | ESP32 工程类比 |
|---|---|---|
| 张量 | 带形状与数据类型的多维数值块,是模型输入、权重和中间结果的统一表示。 | 像注明采样数、通道数和位宽的 DMA buffer。 |
| Shape | 描述各维长度及其语义,例如 NCHW 的 batch、通道、高和宽。 | 像协议帧的字段布局,顺序错了数据仍存在但含义全错。 |
| 激活函数 | 在线性变换后加入非线性,使多层网络能表达复杂边界。 | 像状态机中的条件分支,不能被简单合并。 |
| MAC | 一次乘加运算;常用于粗略估算计算量。 | 像内层 DSP 循环的工作次数,还需结合取数成本。 |
承上:回顾与定位
这是课程起点。你已经熟悉 ESP32 中“外设产生数据、DMA 搬运数据、任务消费数据”的链路;本章把这条链路抽象为神经网络的输入、层和输出,为后续讨论训练与部署建立共同语言。
历史发展脉络
神经网络并不是突然从“大模型”时代出现的。它经历了从逻辑化神经元、可学习的线性分类器,到多层网络的信用分配,再到 GPU 上的大规模表示学习这一条长线。今天在端侧工程里看到的张量、算子、自动微分和部署图,正是这条历史逐步沉淀出的分层接口。
神经元第一次被写成可计算的逻辑单元
McCulloch 与 Pitts 用阈值化单元和连接网络描述神经活动,证明一组简单单元可以组合出逻辑行为。它没有现代训练算法,却奠定了“复杂功能可由大量统一小单元连接而成”的计算视角。
McCulloch 与 Pitts 原始论文 ↗感知机把“连接”变成可由样本修正的权重
Rosenblatt 的感知机引入依据分类误差调整连接权重的机制,使神经网络从手工逻辑结构走向数据驱动学习。它主要解决线性可分问题,也让“模型参数是训练结果”成为后来网络的核心观念。
Rosenblatt 感知机原始论文 ↗反向传播让隐藏层收到可计算的误差信号
Rumelhart、Hinton 与 Williams 展示了误差反向传播如何逐层计算导数并调整权重。隐藏单元不再依赖人工指定含义,而能为任务形成内部表示;这让多层非线性网络拥有了实用的统一训练方法。
Nature 反向传播原始论文 ↗AlexNet 把深层表示学习推入大数据与 GPU 时代
AlexNet 在大规模图像数据上训练深卷积网络,并用 GPU 承担密集张量计算。突破不只来自网络结构,还来自数据、并行计算和正则化共同到位;从此参数量、MAC、显存与吞吐成为同一套工程预算。
AlexNet 原始论文 ↗命令式张量程序与自动微分成为日常工具
PyTorch 论文总结了命令式前端、动态图与高性能张量后端的组合。研究者可以像普通程序一样写控制流,同时由系统记录运算关系并求梯度;今天导出前先确认动态图路径,也源自这种灵活性。
PyTorch 系统原始论文 ↗类比图解
一座会根据试音记录自动调节的连锁调音台
想象一支乐队的多轨录音进入几排调音台。每排先按旋钮比例混合声道,再经过只允许某些信号通过的噪声门;末端监听员把成品与参考录音比较,并把“哪里偏响、哪里偏弱”的修正便签沿线路反向传回。重复试音后,旋钮位置就是学到的权重。
类比的边界: 这个类比只帮助理解信号变换与误差反馈。真实网络的一个“旋钮”会参与高维批量运算,梯度是局部导数的精确组合而不是主观意见;类比也无法表示参数共享、卷积布局和数值精度造成的耦合。
本章讲解
Shape 之外还要读 stride 与轴语义
同样是 3072 个数,[1,3,32,32] 与 [1,32,32,3] 的物理含义完全不同;即使 shape 相同,转置后的 view 也可能不连续。层通常按约定的轴做归一化、卷积或归约,广播又可能让错误 shape “合法运行”。读网络时应给每一轴标注 N/C/H/W、单位和 dtype,并在边界打印 stride,避免把可执行误当作语义正确。
非线性真正改变的是可组合的决策边界
仿射层只做旋转、缩放和平移,多层仿射映射仍可折成一次矩阵乘法。ReLU 等激活把输入空间切成多个区域,不同区域使用不同线性关系,于是层叠才会增长表达能力。工程上还要关注激活的输出范围:大面积恒为零可能意味着输入偏移或坏初始化,过大数值则可能在低精度部署时饱和。
损失是目标接口,梯度是逐层信用账本
损失函数规定什么差异值得惩罚;链式法则再把总误差对每个中间量的敏感度逐层相乘。梯度为零不等于已经学好,可能是饱和激活、断开的计算图或数值下溢;梯度爆大也会使一次更新越过有效区域。训练实验应同时记录 loss、梯度范数与参数更新量,而不是只盯最终准确率。
参数、MAC 与峰值激活回答三种不同问题
参数量近似回答权重需要多少存储,MAC 粗略回答进行了多少乘加,激活生命周期才决定运行时工作台有多大。卷积的权重可很少,却可能产生巨大的特征图;逐元素算子几乎没有参数,仍会完整读写张量。端侧预算应按执行顺序画出存活区间,再把 workspace、对齐填充和 I/O buffer 加入峰值。
用有限差分和中间张量验证“会算”
为一个极小网络固定权重与输入,保存每层输出、损失和解析梯度;再让单个参数增加与减少一个很小的 ε,用两次损失差近似导数。两者不符时,常见原因是转置、批量归约、原地修改或激活边界。部署侧不需要反向传播,但这份 golden tensor 可继续验证导出、量化和 kernel 是否保持前向语义。
动态过程演示
一拍训练脉冲:数据如何变成一次权重更新
播放器每前进一步就点亮一个张量及其所有者;前半程信号向右流,后半程梯度向左回传,最后权重刻度发生细小移动。
装载样本 · x:[B,2],y:[B,1]
高亮 batch 轴,并把输入送入第一层
先确定 shape、dtype 与轴语义,后续计算才有共同契约
循环 / 返回条件: 更新后的权重重新接收下一批样本;动画回到装载样本,并保留一条逐步下降的 loss 轨迹作为跨轮次状态。
查看静态全景图
输入 x │ Linear(Wx+b) ▼ 激活 f(·) ──► 预测 ŷ ──► Loss(ŷ,y) ▲ │ └────── 梯度反传 ◄─────────┘
代码或命令示例
y = x @ W.T + b
y = relu(y)
loss = mean((y - target) ** 2)
loss.backward()动手实验
实验记录与导出
工程陷阱
核心测试
完成 3 道单选题后提交;提交前不会显示答案。
在 GitHub 上讨论本章
登录 GitHub 后提问、补充实测或分享你的实现;评论会保存在本课程的 GitHub Discussions 中。
评论区需要 JavaScript;也可以直接打开 GitHub 讨论区: 打开 GitHub 讨论区 ↗
延伸阅读
启下:下一章如何使用本章能力
下一章把训练态、推理态、计算图、权重与格式契约连成一条可验证的模型交付链。
下一天: Day 2 · 训练与推理