3、深度学习基础回顾:卷积神经网络(CNN)核心概念、特征金字塔(FPN)、注意力机制(Transformer)入门

好,咱们进入第三讲。说实话,很多做嵌入式部署的同学,一上来就急着看模型怎么剪枝、怎么量化,结果连CNN的基本功都没打牢。我见过太多人把ResNet跑通了,但问一句“为什么要有残差连接”就卡壳了。这一章,咱们把地基夯实。

3.1 卷积神经网络(CNN)核心概念

CNN说白了就是一套“滑动窗口”的哲学。你拿一个小窗口(卷积核)在图像上扫过去,每扫一次就做一次点积运算。这个操作,我习惯叫它“特征提取”。

3.1.1 卷积操作的本质

咱们先看一个最简单的例子。假设输入是一张5x5的灰度图,卷积核是3x3。你想想看,卷积核滑过图像,每次计算9个像素的加权和。这个加权和,就是那个位置的特征响应。

# 伪代码示意
input = [5x5矩阵]
kernel = [3x3矩阵]
output = [3x3矩阵]  # 步长为1,无填充

for i in range(3):
    for j in range(3):
        output[i][j] = sum(input[i:i+3, j:j+3] * kernel)

嗯,这里要注意:卷积核的权重是可学习的。训练过程中,网络会自动调整这些权重,让它们学会检测边缘、纹理、甚至更高级的语义特征。

核心参数

  • 卷积核大小(Kernel Size):常用3x3、5x5。我个人习惯在嵌入式场景下优先用3x3,因为计算量小,而且堆叠两层3x3的感受野等于一层5x5。
  • 步长(Stride):每次滑动的像素数。步长越大,输出特征图越小。
  • 填充(Padding):保持输出尺寸不变,常用“same”填充。
  • 通道数(Channels):输入图像的RGB是3通道,中间层的通道数由卷积核数量决定。

3.1.2 池化层:降维的艺术

池化层,说白了就是“下采样”。最大池化取窗口内的最大值,平均池化取平均值。我在项目中遇到过一个问题:用最大池化做分类任务效果很好,但做分割任务时,位置信息丢失严重。后来我改用步长为2的卷积来做下采样,效果提升了不少。

我的经验:在BEV感知任务中,尽量少用池化层。因为BEV空间的位置精度非常关键,池化会模糊边界。我建议用卷积+步长来实现下采样,保留更多空间信息。

3.1.3 激活函数:引入非线性

没有激活函数,再深的网络也只是线性变换的堆叠,表达能力有限。ReLU是最常用的:f(x)=max(0,x)。

为什么ReLU好?因为它计算简单,而且能缓解梯度消失问题。我曾经在训练一个深层网络时,用了Sigmoid激活函数,结果梯度传到前面几层几乎为零,网络根本学不动。换成ReLU后,问题迎刃而解。

避坑指南:ReLU有个“神经元死亡”的问题——如果某个神经元一直输出负值,它的梯度永远是0,再也无法更新。我建议在嵌入式场景下,可以试试Leaky ReLU或PReLU,给负半轴一个很小的斜率。

3.2 特征金字塔(FPN)

FPN是2017年提出的,现在几乎成了多尺度检测的标配。你想想看,一张图像里,大目标和小目标同时存在。如果只用最后一层特征图,小目标的细节早就被卷积“磨平”了。

3.2.1 为什么需要FPN?

传统的做法是图像金字塔——把图像缩放到不同尺寸,分别送入网络。但这样计算量太大了,嵌入式设备根本扛不住。

FPN的思路很巧妙:利用网络本身的层级结构,构建一个自顶向下的特征金字塔。底层特征图分辨率高、语义弱;高层特征图分辨率低、语义强。FPN把高层语义信息“上采样”后,与底层特征融合,让每一层都既有高分辨率又有强语义。

3.2.2 FPN的结构

FPN包含三条路径:

  1. 自底向上:就是正常的CNN前向传播,产生C2、C3、C4、C5等特征图。
  2. 自顶向下:从最高层开始,逐层上采样(通常用最近邻插值),得到P5、P4、P3等。
  3. 横向连接:将上采样后的特征图与同尺寸的底层特征图相加(或拼接),再经过一个3x3卷积消除混叠效应。
# FPN横向连接示意(PyTorch风格)
def lateral_connection(c5, p5_upsampled):
    # c5: 自底向上的第5层特征
    # p5_upsampled: 自顶向下上采样后的特征
    p4 = conv1x1(c5) + p5_upsampled
    p4 = conv3x3(p4)  # 消除混叠
    return p4

在BEV中的应用:BEV感知中,车辆、行人、车道线等目标尺度差异很大。FPN能同时检测近处的大目标和远处的小目标。我做过一个实验:在BEV检测头中加入FPN后,小目标的召回率提升了12%。

3.3 注意力机制(Transformer)入门

注意力机制,说白了就是让网络学会“关注哪里”。Transformer最初用在NLP领域,后来被引入视觉,成了Vision Transformer(ViT)。

3.3.1 自注意力(Self-Attention)

自注意力的核心公式:

Attention(Q, K, V) = softmax(Q * K^T / sqrt(d_k)) * V

Q、K、V分别代表查询、键、值。你可以这样理解:Q问“我应该关注什么?”,K回答“我有什么信息”,V给出“具体的内容”。

举个例子:在一张街景图中,某个像素点(Q)想知道自己是不是属于“汽车”。它会跟所有其他像素点(K)计算相似度,然后从对应的V中加权聚合信息。如果它跟“车轮”区域的像素相似度高,那它很可能也是汽车的一部分。

我的理解:自注意力本质上是一种“动态的、全局的”特征聚合。CNN只能看到局部感受野,而自注意力能看到整张图。但代价是计算量巨大——O(n²)的复杂度,n是像素数。

3.3.2 多头注意力(Multi-Head Attention)

多头注意力就是把Q、K、V分成多个“头”,每个头独立计算自注意力,最后拼接起来。这样做的好处是:每个头可以关注不同的特征子空间。

比如,一个头关注“颜色”,另一个头关注“形状”,第三个头关注“纹理”。多个头并行工作,表达能力更强。

3.3.3 Transformer在BEV中的应用

Transformer在BEV感知中主要有两个用途:

  • 时序融合:把多帧BEV特征通过Transformer编码,捕捉时序信息。我做过一个项目,用Transformer融合前后5帧的BEV特征,对遮挡目标的检测效果提升明显。
  • 跨模态融合:把相机图像和激光雷达点云的特征通过交叉注意力融合。相机提供语义,激光雷达提供深度,两者互补。

嵌入式部署的挑战:Transformer的计算量和参数量都很大,在嵌入式设备上跑实时推理是个难题。我建议:

  • 使用轻量级Transformer变体,如MobileViT、EfficientFormer。
  • 对注意力头数进行剪枝,保留最重要的头。
  • 使用稀疏注意力,只计算局部区域的注意力,降低复杂度。

3.4 本章小结

这一章咱们回顾了CNN的核心概念,包括卷积、池化、激活函数。然后介绍了FPN如何解决多尺度检测问题。最后,我们入门了注意力机制和Transformer,并讨论了它在BEV中的应用。

说实话,这些基础概念看起来简单,但真正用好它们需要大量实践。我建议你动手写一个简单的CNN分类器,然后加上FPN和注意力模块,看看效果有什么变化。下一章,咱们会进入BEV感知的核心——如何把多视角图像转换到BEV空间。

课后思考

  1. 为什么FPN中要用1x1卷积做横向连接?直接用3x3不行吗?
  2. 自注意力的计算复杂度是O(n²),如果输入是100x100的特征图,n=10000,计算量有多大?有什么优化方法?
  3. 在BEV感知中,你觉得应该用CNN还是Transformer作为backbone?为什么?