2. 深度学习模型基础回顾:神经网络核心概念、卷积与全连接层、激活函数与池化
做模型移植这些年,我最大的感触是:很多部署翻车,根源不在工具链,而在对模型本身的理解不够深。你想想看,一个卷积层参数排布搞错了,量化后精度直接掉 5 个点,查半天都不知道问题出在哪。
所以这一章,咱们把基础打牢。我不会跟你念教科书,而是结合我实际踩过的坑,把神经网络里最核心的几个概念讲透。
2.1 神经网络的核心构成
说白了,神经网络就是一个多层可微分的函数组合。每一层干两件事:线性变换 + 非线性激活。
核心公式(单层前向传播):
z = W · x + b # 线性变换
a = f(z) # 非线性激活
其中 W 是权重,b 是偏置,f 是激活函数。
我个人习惯把网络拆成三块来看:
- 特征提取器:卷积层、池化层 —— 负责从原始数据里提取有意义的模式
- 特征转换器:激活函数 —— 引入非线性,让网络能拟合复杂函数
- 决策器:全连接层 + Softmax —— 把特征映射到最终输出
嗯,这里要注意:移植时这三块的优化重点完全不同。卷积层看计算密度,全连接层看内存带宽,激活函数看计算精度。
2.2 卷积层:特征提取的核心
卷积层是 CNN 的基石。它的核心思想就四个字:局部连接 + 权值共享。
你想想看,一张 224×224 的图片,如果用全连接层,光第一层就有 5 万个神经元,每个连到 5 万个像素,参数量直接爆炸。卷积层用一个小窗口(卷积核)滑过整张图,同一个核在所有位置共享权重,参数量瞬间降到几千。
卷积层关键参数:
| 参数 | 含义 | 移植影响 |
|---|---|---|
| 卷积核大小 (K) | 窗口尺寸,常用 3×3、5×5 | K 越大,计算量越大 |
| 步长 (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 激活函数:非线性的灵魂
没有激活函数,再多层也只是线性变换的堆叠,表达能力有限。激活函数给网络注入了非线性。
常用的激活函数就几种,我列个表对比一下:
| 激活函数 | 公式 | 优点 | 缺点 | 部署注意 |
|---|---|---|---|---|
| ReLU | max(0, x) | 计算简单,缓解梯度消失 | 神经元死亡(负半轴梯度为 0) | 大部分硬件原生支持 |
| Sigmoid | 1 / (1 + e⁻ˣ) | 输出范围 (0,1),适合概率 | 梯度饱和,计算开销大 | 量化时精度损失明显 |
| Tanh | (eˣ - e⁻ˣ) / (eˣ + e⁻ˣ) | 输出范围 (-1,1),零中心 | 梯度饱和 | 边缘设备慎用 |
| GELU | x · Φ(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%。
池化层移植检查清单:
- 确认硬件是否支持该池化操作(有些 NPU 只支持最大池化)
- 检查池化窗口大小和步长是否对齐(常见 2×2, stride=2)
- 注意填充模式(same / valid)是否与训练时一致
- 量化时池化层一般不需要校准,直接继承输入量化参数
2.6 本章小结
这一章我们回顾了神经网络最核心的几个组件:
- 卷积层:局部连接 + 权值共享,特征提取的主力
- 全连接层:参数量大,部署时需重点优化
- 激活函数:非线性来源,ReLU 是部署首选
- 池化层:降采样,可考虑用步长卷积替代
这些基础概念,在后面的模型移植中会反复用到。尤其是卷积层的参数计算和激活函数的选择,直接决定了你的模型能不能在目标硬件上跑起来、跑得快不快。