2. 深度学习模型基础回顾

做模型移植这些年,我最大的感触是:很多部署翻车,根源不在工具链,而在对模型本身的理解不够深。你想想看,一个卷积层参数排布搞错了,量化后精度直接掉 5 个点,查半天都不知道问题出在哪。

所以这一章,咱们把基础打牢。我不会跟你念教科书,而是结合我实际踩过的坑,把神经网络里最核心的几个概念讲透。

2.1 神经网络的核心构成

说白了,神经网络就是一个多层可微分的函数组合。每一层干两件事:线性变换 + 非线性激活。

核心公式(单层前向传播):

z = W · x + b      # 线性变换
a = f(z)           # 非线性激活

其中 W 是权重,b 是偏置,f 是激活函数。

我个人习惯把网络拆成三块来看:

  • 特征提取器:卷积层、池化层 —— 负责从原始数据里提取有意义的模式
  • 特征转换器:激活函数 —— 引入非线性,让网络能拟合复杂函数
  • 决策器:全连接层 + Softmax —— 把特征映射到最终输出

嗯,这里要注意:移植时这三块的优化重点完全不同。卷积层看计算密度,全连接层看内存带宽,激活函数看计算精度。

神经网络核心构成 输入层 特征提取器 卷积层 池化层 激活函数 特征转换器 ReLU / Sigmoid Tanh / GELU 非线性映射 决策器 全连接层 Softmax 分类/回归 💡 移植要点: 卷积层 → 优化计算密度 | 全连接层 → 优化内存带宽 | 激活函数 → 保证精度

2.2 卷积层:特征提取的核心

卷积层是 CNN 的基石。它的核心思想就四个字:局部连接 + 权值共享。

你想想看,一张 224×224 的图片,如果用全连接层,光第一层就有 5 万个神经元,每个连到 5 万个像素,参数量直接爆炸。卷积层用一个小窗口(卷积核)滑过整张图,同一个核在所有位置共享权重,参数量瞬间降到几千。

卷积层关键参数:

参数含义移植影响
卷积核大小 (K)窗口尺寸,常用 3×3、5×5K 越大,计算量越大
步长 (S)窗口每次滑动的像素数S > 1 可降采样,减少输出尺寸
填充 (P)输入边缘补零的圈数影响输出尺寸,需对齐硬件
输入通道 (C_in)输入特征图的通道数决定卷积核的深度
输出通道 (C_out)卷积核的个数决定输出特征图的通道数

输出特征图尺寸公式:

H_out = (H_in + 2P - K) / S + 1
W_out = (W_in + 2P - K) / S + 1

我曾经在移植一个 MobileNetV2 到 RK3588 时,就因为填充计算没对齐,导致输出尺寸差了一个像素,后面所有层都错位了。排查了整整两天……嗯,从那以后我每次写卷积层都会手动算一遍输出尺寸。

2.3 全连接层:特征到决策的映射

全连接层就是传统的神经网络层。每个输入节点都连接到每个输出节点,所以参数量巨大。

举个例子:一个 2048 维的特征向量,连到 1000 类的分类层,参数量就是 2048 × 1000 + 1000 ≈ 205 万个参数。这在部署时是个大问题——全连接层的权重往往占模型总大小的一半以上。

移植避坑指南:

我曾经在部署一个 ResNet-50 到边缘设备时,发现模型加载时间特别长。一查,全连接层的权重占了 45MB,而卷积层总共才 30MB。后来用全局平均池化替代了全连接层,模型大小直接砍半,精度只掉了 0.3%。

全连接层在部署时有两个优化方向:

  • 权重压缩:用 8-bit 量化,参数量不变但存储减 4 倍
  • 结构替换:用 GAP(全局平均池化)+ 小全连接层替代

2.4 激活函数:非线性的灵魂

没有激活函数,再多层也只是线性变换的堆叠,表达能力有限。激活函数给网络注入了非线性。

常用的激活函数就几种,我列个表对比一下:

激活函数公式优点缺点部署注意
ReLUmax(0, x)计算简单,缓解梯度消失神经元死亡(负半轴梯度为 0)大部分硬件原生支持
Sigmoid1 / (1 + e⁻ˣ)输出范围 (0,1),适合概率梯度饱和,计算开销大量化时精度损失明显
Tanh(eˣ - e⁻ˣ) / (eˣ + e⁻ˣ)输出范围 (-1,1),零中心梯度饱和边缘设备慎用
GELUx · Φ(x)Transformer 标配,性能好计算复杂需查表或近似实现

我个人习惯:能选 ReLU 就选 ReLU。原因很简单——几乎所有边缘 AI 芯片都对 ReLU 做了硬件加速,零开销。而 Sigmoid 和 Tanh 在量化后精度掉得厉害,我踩过这个坑。

ReLU 的变种:

  • Leaky ReLU:负半轴给一个小斜率(如 0.01),解决神经元死亡
  • PReLU:斜率可学习,精度更高但部署复杂
  • ReLU6:限制输出最大值 6,对量化友好(MobileNet 常用)

2.5 池化层:降维与特征聚合

池化层的作用就两个:降采样和特征聚合。它没有可学习参数,但能有效减少特征图尺寸,降低后续层的计算量。

最常见的两种池化:

  • 最大池化(Max Pooling):取窗口内的最大值。保留最显著的特征,对纹理和边缘敏感。
  • 平均池化(Average Pooling):取窗口内的平均值。保留整体特征,对背景和区域更鲁棒。

嗯,这里有个小技巧:在移植时,尽量用步长卷积代替池化。为什么?因为很多边缘芯片对池化的支持不如卷积优化得好。我在移植 YOLOv5 到 TensorRT 时,把 2×2 最大池化换成 stride=2 的 3×3 卷积,推理速度反而快了 15%。

池化层移植检查清单:

  1. 确认硬件是否支持该池化操作(有些 NPU 只支持最大池化)
  2. 检查池化窗口大小和步长是否对齐(常见 2×2, stride=2)
  3. 注意填充模式(same / valid)是否与训练时一致
  4. 量化时池化层一般不需要校准,直接继承输入量化参数

2.6 本章小结

这一章我们回顾了神经网络最核心的几个组件:

  • 卷积层:局部连接 + 权值共享,特征提取的主力
  • 全连接层:参数量大,部署时需重点优化
  • 激活函数:非线性来源,ReLU 是部署首选
  • 池化层:降采样,可考虑用步长卷积替代

这些基础概念,在后面的模型移植中会反复用到。尤其是卷积层的参数计算和激活函数的选择,直接决定了你的模型能不能在目标硬件上跑起来、跑得快不快。