1.ImageNet挑战赛与深度学习的革命
1.1. K-最近邻(K-Nearest Neighbors, K-NN)算法
1.1.1. CIFAR-10 数据集
CIFAR-10数据集
- 它包含60000张非常小的彩色图片(32×32 像素)。
- 这些图片共分为10个类别,例如飞机、汽车、鸟、猫等。
这个数据集在机器学习领域非常经典,可以把它想象成是图像分类任务的“新手村”。我们的目标就是训练一个模型,让它能够正确识别出任意一张CIFAR-10图片属于哪个类别。
K-NN的思想非常直观,可以概括为“近朱者赤,近墨者黑”。要判断一个新样本(测试图片)属于哪个类别,我们不进行复杂的“学习”,而是直接在所有已知样本(训练图片)中找到和它最相似的K个邻居,然后采取“少数服从多数”的原则,看这K个邻居中哪个类别的数量最多,就把新样本归为那一类。
要实现这个算法,有两个关键问题需要解决:
- 如何衡量两张图片之间的“相似度”或“距离”?
- K的值(邻居的数量)应该如何选择?
一种最简单的距离计算方法:逐像素差值(Pixel-wise value difference)。这也被称为 L1距离 或 曼哈顿距离。
它的工作方式是:将两张图片对齐,计算每个对应位置上像素值的差的绝对值,最后将所有这些差值加起来,得到一个总的距离分数。分数越小,代表两张图片在像素层面上越相似。在实际分类时,我们会计算测试图片与所有训练图片的距离,然后进行排序。
K值的选择如何影响分类结果。
- 如果 K=1:我们只看离测试样本(绿色圆点)最近的一个邻居。在这个例子中,最近的是一个红色三角,所以模型会把绿色圆点预测为“红色三角”类。此时模型会非常依赖个别训练样本,对噪声很敏感。这可能导致模型的过拟合。PPT下方的“NN classifier”图就展示了这种情况,它的决策边界非常复杂、犬牙交错,试图将每一个样本都完美分开。
- 如果 K=5:我们会看最近的5个邻居。圈出的范围内有3个蓝色方块和2个红色三角。根据少数服从多数的原则,模型会把绿色圆点预测为“蓝色方块”类。如果K值过大,可能会导致欠拟合,即模型过于简单,无法捕捉到数据中类别的真实边界。
![[Pasted image 20251002154816.png]]
虽然K-NN非常简单直观,但它在现代图像分类任务中几乎不被使用,主要有以下几个致命缺陷:
- 计算效率极低:在预测阶段,它需要计算测试图片与所有训练图片的距离。对于CIFAR-10,这意味着每预测一张图片,就要做50000次(假设用5万张图作训练集)高维向量的距离计算,非常耗时。这与深度学习模型(如CNN)正好相反,CNN是训练慢,但预测非常快。
- 像素距离不等于语义距离:L1或L2距离对于衡量图片的视觉相似性非常糟糕。例如,将一张猫的图片整体向右平移一个像素,其内容和语义完全没变,但L1距离可能会变得非常大。同样,改变光照、旋转角度、背景等都会极大地影响像素距离,但对人类来说图片内容可能还是一样的。
- 维度灾难图像数据是高维的(CIFAR-10是 32×32×3=3072 维)。在高维空间中,所有点之间的距离都趋向于变得很远,这使得“邻居”这个概念本身变得不再那么有意义。
基于像素距离的分类器的根本问题:像素上的相似不等于语义上的相似。模型并没有真正“理解”图片的内容。它之所以会把汽车和轮船匹配在一起,很可能是因为这两张图片的背景(比如天空和水面)和颜色分布(大面积的蓝色和灰色)在像素层面上非常接近。模型只是在进行一个“数学游戏”,而不是在进行“视觉识别”。它匹配的是颜色和纹理,而不是“汽车”或“轮船”这两个概念。
准确率(Accuracy)
- Random: 10%
- 这是我们的基准线。因为CIFAR-10有10个类别,如果你完全随机地乱猜,你将有10%的概率猜对。任何一个有用的分类器都必须远超这个水平。
- Image difference (L1): 38.6% 与 (L2): 35.4%
- 这是我们之前讨论的K-NN分类器的真实成绩。L1代表使用曼哈顿距离,L2代表使用欧几里得距离。
- 可以看到,它们的表现虽然远好于随机猜测,但38.6%的最高准确率意味着模型在超过60%的情况下都是错的。这在实际应用中是完全不可接受的。
- Human: 94%
- 这个数字代表了人类专家在这个数据集上的识别水平。这告诉我们,尽管这些 32×32 的图片很模糊,但绝大多数图片的内容是可以被清晰辨认的。这为我们设立了一个很高的目标。
- CNN: 95%
- 卷积神经网络 在这个任务上的表现极好,甚至超越了人类。
1.2. ImageNet
ImageNet的基本情况:
- 这是一个极其庞大的图像数据集,包含了从互联网上收集的大约 1500万张 图片,整个整理和标注过程耗时 3年。
- 这些图片被精细地分入了大约 22000个 类别。这些类别包罗万象,从动物、植物到食物、人物、体育运动等等。
在ImageNet(2010年)出现之前,机器学习领域用于图像识别的数据集规模要小得多(例如我们之前看到的CIFAR-10只有6万张图片)。深度学习模型,尤其是深度卷积神经网络(CNN),就像强大的引擎,但它们需要海量的“燃料”(也就是数据)才能运转起来。ImageNet的出现,首次为训练这种大规模、数据驱动的模型提供了可能性。可以说,没有ImageNet,就没有后来深度学习在计算机视觉领域的革命。这个项目由斯坦福大学的李飞飞教授团队主导,他们通过亚马逊的众包平台(Amazon Mechanical Turk)动员了全球数万名工作者,才完成了这项艰巨的标注工作。
图像识别的真正难点在于,不只是有海量的数据就可以。图片物体的标准照是物体清晰、巨大,位于画面中央,背景干净,光线良好。比如一张侧面特写的金鱼,或是一张蓝天背景下的航天飞机。
但是真实世界的样子,物体可能:
- 被部分遮挡(比如被亲吻的金鱼)。
- 处于复杂的场景中(一群金鱼)。
- 角度刁钻(夜晚发射的航天器、日落时的桥梁剪影)。
- 形态各异(各种不同种类的洋蓟)。
这种同一类别内部的巨大差异,在学术上被称为“类内差异”。一个真正强大的图像识别模型,必须能够克服这些干扰,准确地识别出物体的本质。
1.3. ImageNet挑战赛(ILSVRC)
ILSVRC的性质:
- 它是一场年度图像分类竞赛 。
- 竞赛使用的数据集是ImageNet的一个子集,包含1000个类别的120万张图片 (1.2M images in 1K categories)。
比赛的评分规则没有采用传统的“唯一答案”模式,而是给了模型5次猜测机会。这就是Top-5错误率的核心思想。
- 模型输出一个列表:对于一张输入的图片,模型不再只给出一个它认为最可能的答案,而是输出一个包含5个候选答案的、按可能性从高到低排序的列表。
- 判断是否正确:我们检查这张图片的真实标签是否存在于这个5个候选答案的列表中。
- 如果存在,那么这次预测就被认为是正确的。
- 如果不存在,那么这次预测就被认为是错误的。
- 计算错误率:Top-5错误率就是用“错误”预测的图片总数除以全部测试图片的总数。
- 容忍语义上的模糊性:ImageNet中的类别非常精细,很多类别之间在视觉上极为相似。例如以豹子为例子,模型把它和美洲豹(jaguar)、猎豹(cheetah)、雪豹(snow leopard)搞混是情有可可原的,因为它们都是大型猫科动物,外形相似。人类也可能犯类似的错误。Top-5标准承认了这种模糊性,只要模型能把正确答案圈定在一个很小的范围内,就算它答对了。
- 适应现实世界的多样性:一张图片里可能包含多个物体。如果一张图片的主体是一只狗,但背景里也有一只猫,一个好的模型可能会把“狗”预测为第一名,“猫”预测为第二名。在Top-5标准下,如果这张图片的标签恰好是“猫”,这次预测依然是正确的。
- 更贴近实际应用:在很多真实应用场景中(比如图片搜索),返回5个最相关的结果通常比只返回1个不那么确定的结果更有用。
1.3.1. 分类的难点
分类对人类来说也非易事,如下图:
![[Pasted image 20251002160441.png]]
图中展示了两只狗,它们在外观上极为相似,都有黑、白、棕三色相间的毛发和相似的脸部斑纹。一只被标记为 EntleBucher(恩特勒布赫山犬),另一只是 Appenzeller(阿彭策尔山犬)。除非你是犬类专家,否则普通人几乎不可能区分这两个犬种。这引出了一个重要概念——细粒度视觉分类(Fine-Grained Visual Classification)。
细粒度分类指的是在大的类别下,对非常相似的子类别进行区分。比如“鸟”是一个大类,而区分“白头海雕”和“金雕”就是细粒度分类。“汽车”是一个大类,而区分“2021款宝马3系”和“2022款宝马3系”也是细粒度分类。ImageNet数据集中包含了超过120个犬种的分类,其难度可想而知。
既然连人类都觉得困难,那么我们就不能苛求AI模型在每次预测时都给出100%唯一的正确答案。这也再次印证了上一节课我们讨论的 Top-5错误率 这一评价标准的合理性与必要性。
AI在预测中的真实表现也有区别,如下:
![[Pasted image 20251002160548.png]]
我们可以将其表现分为以下几类:
- 成功
- 例子:“mite”(螨虫)和“container ship”(集装箱船)。
- 分析:在这两个例子中,模型给出的第一个答案就是正确标签,并且置信度(蓝色条的长度)非常高。这表明对于特征清晰、明确的物体,模型可以做到非常精准的识别。
- “情有可原”的失败
- 例子:“leopard”(豹)和“Madagascar cat”(马达加斯加猫,即狐猴)。
- 分析:
- 对于豹子的图片,模型虽然将“leopard”列为第一答案,但其后的四个答案分别是 jaguar(美洲豹), cheetah(猎豹), snow leopard(雪豹) 等。这些都是带斑点的大型猫科动物,外形极其相似。这种“错误”非常有逻辑性,完全可以理解。在Top-5标准下,这被记为一次完美的成功。
- 对于狐猴的图片,模型的猜测是松鼠猴、蜘蛛猴等。虽然没有猜中确切的“狐猴”,但模型准确地捕捉到了“生活在树上的灵长类动物”这一核心概念。
- 任务本身的模糊性
- 例子:“cherry”(樱桃)和“grille”(格栅)。
- 分析:
- 对于标有“cherry”的图片,画面中最醒目的物体其实是一只斑点狗(Dalmatian)。模型的第一反应也是“dalmatian”。这引发了一个问题:当一张图片包含多个物体时,哪个才是“正确”的标签?模型的识别其实非常准确,但与数据集给出的“标准答案”不符。
- 对于标有“grille”的图片,它实际上是一辆红色敞篷古董车的前脸。模型给出的第一答案是“convertible”(敞篷车)。相比于“格栅”这个局部特征,模型的回答显然更好地描述了图片的主体。
因此:
- ImageNet分类任务极其困难,其中大量的细粒度分类对人类专家都是一个挑战。
- 早期的深度学习模型(如AlexNet)已经展现出惊人的能力,它们不仅能准确识别物体,其犯下的“错误”也常常是符合逻辑和语义的,表现出类似人类的思维方式。
- 分类任务本身存在模糊性,有时“标准答案”也未必是最好的描述。这也促使后来的研究向多标签分类、目标检测等更复杂的任务发展。
1.3.2. 比赛中的历史时刻
![[Pasted image 20251002160726.png]]
在竞赛中,他们团队的名称是SuperVision,来自多伦多大学(U of Toronto)。后来,这个模型因为其第一作者是Alex Krizhevsky,而被学界广泛称为 AlexNet。
这个模型是由Alex Krizhevsky、Ilya Sutskever以及他们的导师,深度学习领域的传奇人物——杰弗里·辛顿(Geoffrey Hinton) 共同开发的。辛顿教授因为其在神经网络领域的开创性工作,被誉为“AI教父”之一,并荣获了诺贝尔奖和计算机领域的最高奖项——图灵奖。
SuperVision团队(即AlexNet)的成绩,它的Top-5错误率达到了 16.4%。第二名(来自东京大学的ISI团队)以及之后所有团队的成绩,它们的错误率都在26%以上。在2012年之前,计算机视觉领域的主流方法是“传统方法”。研究者们需要手动设计复杂的特征提取器(比如SIFT, HOG算法),然后将这些提取出的特征送入一个机器学习分类器(比如SVM)。这个过程繁琐且效果有限。
而AlexNet是第一个在大赛中证明深度卷积神经网络(Deep Convolutional Neural Networks) 压倒性优势的模型。它采用的是一种端到端(end-to-end)的学习方式,不需要人为设计特征,而是让网络自己从海量的原始图片数据中学习如何提取最有用的特征。
而AlexNet后历年ImageNet挑战赛(ILSVRC)冠军模型的Top-5错误率如下:
![[Pasted image 20251002160952.png]]
在2010年和2011年,比赛冠军的Top-5错误率分别高达 28.2% 和 25.8%。因为当时的主流方法还依赖于人为设计的特征提取器,模型的深度和复杂度都有限,性能提升缓慢。
AlexNet以一个拥有 8个层 的深度卷积网络开启了新时代,错误率骤降至 16.4%。ZFNet 在AlexNet的基础上进行优化,将错误率进一步降低到 11.7%,网络深度仍然是 8层。这表明在现有架构上精调也能带来进步。
2014年出现了两个标志性的模型:
- VGGNet:将网络深度猛增到了 19层,错误率也随之大幅下降至 7.3%。
- GoogLeNet:以 22层 的更深结构和创新的“Inception模块”,赢得了当年的冠军,错误率降至 6.7%。
虽然GoogLeNet是2014年的官方冠军,但VGGNet因为其结构极其简单、规整(全部由3x3卷积和2x2池化组成),在学术界和工业界产生了同样深远的影响。从这一年开始,“网络越深,性能越好”的观点成为了主流。
2015年ResNet (残差网络) 带着一个当时看来匪夷所思的 152层 深度登场。人类专家的错误率为5.1%,而ResNet的Top-5错误率仅为 3.57%。
同时可以看出,网络层数的增加(深度)与错误率的降低呈现出强烈的正相关关系。在ResNet出现之前,简单地堆叠网络层数会导致性能下降(即“网络退化”问题)。ResNet通过引入“残差连接”(或称“跳跃连接”)结构,解决了深度网络的训练难题,才使得构建像152层甚至上千层的超深度网络成为可能。
![[Pasted image 20251002161258.png]]
2. 各个CNN架构
2.1. AlexNet
2.1.1. 基本架构
AlexNet基本架构:
- 7个隐藏层 (7 hidden layers) (补充:通常我们说AlexNet是8层可训练网络,包括5个卷积层和3个全连接层。这里的7个隐藏层可能是指不包含最后的输出层)。
- 65万个神经元 (650K neurons)。
- 6000万个参数 (60M parameters)。
- 6.3亿个连接 (630M connections)。
- ReLU激活函数 (Rectified Linear Units)
- 它比当时流行的tanh和sigmoid等激活函数计算速度更快。
- ReLU的优势有两点:第一是快,它的计算公式是
max(0, x),非常简单;第二是它有效地缓解了“梯度消失”问题。这使得梯度能够在更深的网络中有效传播,从而让训练深度网络变得更加容易。
- Dropout正则化
- 在全连接层上使用了“Dropout”技巧。
- 这是为了解决前面提到的“过拟合”问题而引入的。在训练过程的每一步,都随机地“丢弃”一部分神经元。这会强迫网络学习到更加鲁棒的特征,因为模型不能过度依赖任何一个神经元。这极大地提升了模型的泛化能力。
- 数据增强 (Data augmentation)
- 通过引入变化来扩充数据,例如从原始图片中随机裁剪出 227×227 的图像块。
- 这是另一种对抗过拟合的强大技术。通过对原始训练图片进行随机裁剪、水平翻转、调整颜色等操作,可以无中生有地创造出大量新的训练样本。这等于免费地扩大了训练数据集,让模型学习到对位置、光照等变化不敏感的特征。
- 重叠最大池化 (Overlapping Max Pooling)
- 使用了 3×3 大小的窗口,但步长(stride)为2。
- 传统的池化操作,步长和窗口大小是一样的(比如 2×2 窗口,步长2),窗口之间没有重叠。AlexNet发现,让窗口之间有重叠(步长小于窗口大小),可以提升一点点性能,因为它能保留更丰富的特征信息。
模型在两块GPU上进行训练,耗时5-6天。由于整个模型太大,无法装入当时单块GPU的显存中(当时顶级的NVIDIA GTX 580只有3GB显存)。作者们巧妙地将模型的不同部分(神经元通道)分别放在两块GPU上,并让它们在特定层进行数据交换。这种模型并行的思路,为后来训练更大、更复杂的模型铺平了道路,开启了利用GPU集群进行大规模并行计算的时代。
2.1.2. 架构
![[Pasted image 20251002162624.png]]
特征图尺寸变化公式: $$M=\lfloor\frac{(N+2P-F)}{S}\rfloor+1$$ 其中:
- $M$ 是输出尺寸(高度或宽度)
- $N$ 是输入尺寸
- $P$ 是填充(Padding)的大小
- $F$ 是滤波器(Filter)或池化核的大小
- $S$ 是步长(Stride)
整个网络可以看作是一个处理流水线,我们从左到右一步步来看:
输入 (Input):
- 一张 $227×227×3$ 的彩色图片。(3代表RGB三个颜色通道)
第1层:卷积 (Convolution)
- 操作: 使用96个大小为 $11×11$ 的超大滤波器,以4个像素为步长($S=4$)进行卷积。
- 尺寸计算: 输入 $N=227$ , 滤波器 $F=11$ , 步长 $S=4$ , 填充 $P=0$ 。$M=\frac{(227-11)}{4}+1=\frac{216}{4}+1=54+1=55$
- 输出: 得到一个 $55×55×96$ 的特征图。尺寸变小了,但深度(特征数量)从3增加到了96。
第2层:最大池化 (Max Pooling)
- 操作: 使用一个 3×3 的窗口,以2为步长进行池化。
- 尺寸计算: 输入$N=55$, 池化核F=3, 步长S=2, 填充P=0。$M=\frac{(55-3)}{2}+1=\frac{52}{2}+1=26+1=27$
- 输出: 得到一个 $27×27×96$ 的特征图。深度不变,但长宽被压缩了。
第3层:卷积 (Convolution)
- 操作: 使用256个 $5×5$ 的滤波器,步长 $S=1$,并使用了2个像素的填充($P=2$)。
- 尺寸计算: 输入$N=27$, 滤波器 $F=5$, 步长 $S=1$, 填充 $P=2$。$M=\frac{(27+2\times2-5)}{1}+1=26+1=27$
- 输出: 得到一个 27×27×256 的特征图。这里使用填充的目的是为了在卷积后保持输入和输出的长宽尺寸不变,这是一种非常常见的设计技巧。
第4层:最大池化 (Max Pooling)
- 操作: 同样是 3×3 窗口,步长为2。
- 尺寸计算: 输入$N=27$, 池化核$F=3$, 步长$S=2$, 填充$P=0$。$M=\frac{(27-3)}{2}+1=\frac{24}{2}+1=12+1=13$
- 输出: 得到一个 $13×13×256$ 的特征图。
第5、6、7层:连续卷积
- 接下来是三个连续的卷积层,都使用了 $3×3$ 的小尺寸滤波器和 $P=1$ 的填充来保持尺寸不变。
- 第5层: $13×13×256→13×13×384$
- 第6层: $13×13×384→13×13×384$
- 第7层: $13×13×384→13×13×256$
第8层:最大池化 (Max Pooling)
- 操作: 再次使用 $3×3$ 窗口,步长为2。
- 尺寸计算: 输入$N=13$, 池化核$F=3$, 步长$S=2$, 填充$P=0$。$M=\frac{(13-3)}{2}+1=\frac{10}{2}+1=5+1=6$
- 输出: 得到一个 $6×6×256$ 的特征图。至此,所有的卷积和池化操作完成。
展平 (Flattening):
- 操作: 将 $6×6×256$ 的三维特征图“压扁”,变成一个一维的长向量。
- 尺寸计算: $6×6×256=9216$。
- 补充知识: 这一步是从特征提取到分类决策的桥梁。这个包含9216个元素的长向量,可以被看作是整个网络从原始图片中提取出的最精华、最浓缩的特征表示。
全连接层 (Fully Connected, FC):
- 操作: 接下来是三个全连接层,它们的作用就是根据这个9216维的特征向量,进行最终的分类决策。
- FC1: 9216个神经元连接到4096个神经元。
- FC2: 4096个神经元连接到4096个神经元。
- FC3 (输出层): 4096个神经元连接到1000个神经元,每个神经元对应ImageNet中的一个类别。
Softmax:
- 操作: 在最后一层之后,使用Softmax函数,将1000个神经元的输出值转换成1000个概率值,每个值代表图片属于对应类别的可能性。概率值最高的那个类别,就是模型的最终预测结果。
AlexNet乃至后续大多数CNN架构的核心设计哲学:
- 两段式结构: 整个网络可以清晰地分为两部分:前半部分由卷积层和池化层组成,负责提取特征;后半部分由全连接层组成,负责进行分类。
- 尺寸变化趋势: 在特征提取阶段,数据体的空间尺寸(长x宽)不断减小,而深度(通道/特征数)不断增加。这就像一个信息提纯的过程,不断压缩空间信息,同时提炼出更高级、更抽象的语义特征。
2.1.3. 实际架构
在2012年,一块顶级的消费级GPU(如NVIDIA GTX 580)只有大约3GB的显存。而AlexNet模型本身拥有6000万个参数,在训练过程中还会产生大量的中间计算结果(即特征图),这些数据加起来远远超过了单块GPU的内存上限。因此,作者们唯一的选择就是把一个巨大的网络拆分成两半,分别放在两块GPU上并行运行。
- 两条并行的处理流水线:从输入开始,整个网络就被分成了上下两条独立的线路,每一条线路都在一块GPU上运行。
- 分摊计算任务:网络中每一层的滤波器(filters/kernels)都被平分到了两块GPU上。
- 第一层卷积:总共有96个滤波器,被分为上下两组,每块GPU负责计算48个滤波器。
- 第二层卷积:总共有256个滤波器,每块GPU负责128个。这时,PPT上方的图有一条注释
Filter size = 5x5x48,它的意思是,在这一层,每块GPU上的128个滤波器,其输入的深度是上一层单个GPU输出的特征图深度,即48。 - 第三、四、五层卷积:同样,总滤波器数被平分。例如第四层,总共有384个滤波器,每块GPU负责192个。因此,PPT上方的注释
Filter size = 3x3x192指的是在这一层,单个GPU上的滤波器输入的深度是192。
![[Pasted image 20251002164620.png]]
原始架构图的第三层卷积(输出为192通道的那一层)。上下两条流之间有交叉的连线。这代表在这一层,一块GPU上的滤波器不仅可以访问自己GPU上的数据,还可以访问另一块GPU上的数据。这种“信息交流”至关重要,它保证了整个网络能学习到整合全部信息的特征。而在其他一些层(如第四、五层),连线是平行的,代表GPU之间没有通信,这可能是为了降低通信开销。
2.1.4. 两段式架构
第一部分 (红色虚线框内): 特征/表示学习 (Feature/representation learning)
- 组成: 这部分由所有的卷积层和池化层(Conv1 到 Conv5)构成。你可以把它想象成是模型的“眼睛”和“视觉皮层”。
- 功能: 它的核心任务是接收最原始、最无结构的输入数据(一张 227×227×3 的像素矩阵),并通过层层抽象,自动地学习和提取出对理解图像内容至关重要的特征。
- 数据流: 正如PPT所示,数据在这个模块中流动时,其形态不断变化:从 227×227×3 的原始输入,被逐步转换和提炼成 55×55×96,再到 27×27×256,最终形成一个高度浓缩的特征集合。
第二部分 (右侧): 分类器
- 组成: 这部分由几个全连接层(FC6, FC7, FC8)构成。你可以把它看作是模型的“大脑”。
- 功能: 它的任务相对简单直接:接收前半部分“眼睛”提取出的高级特征,然后基于这些特征做出最终的分类判断,输出这张图片属于1000个类别中每一个的概率。
![[Pasted image 20251002164904.png]]
嵌入(Embedding)。
- 定义: 将庞大、稀疏的向量,转换到一个能够保持语义关系的低维空间(向量)中。
- 详细解读:
- “庞大、稀疏的向量”: 指的就是原始的输入图片。一张 227×227×3 的图片,如果展平成一个向量,其维度高达154,587维。说它“稀疏”是因为图片的语义信息(比如“这是一只猫”)是零散地分布在这些海量像素中的,像素本身的关系并不能很好地反映语义。
- “低维空间(向量)”: 指的就是特征学习模块的最终输出。在AlexNet中,这个输出是一个包含9216个元素的一维向量。虽然维度依然不低,但相比原始的15万维,它已经是一个高度浓缩和精炼的“特征向量”或“嵌入向量”。
- “保持语义关系”: 这个转换过程(即特征提取)最神奇的地方在于,它学会了一种映射,能让在语义上相似的图片,其转换后的嵌入向量在数学空间中的距离也更近。例如,两张不同姿态的猫的图片,它们的嵌入向量会很接近;而一张猫和一张汽车的图片,它们的嵌入向量则会相距很远。
2.1.5. 可扩展性
![[Pasted image 20251002165122.png]]
整个流程抽象为三个部分:
- 输入 (Image):任意一张图片。
- 表示学习网络 (NEURAL NETWORK FOR REPRESENTATION LEARNING):这就是我们之前详细解析的网络的卷积部分(比如AlexNet的Conv1到Conv5)。你可以把它理解成一个强大而通用的“视觉理解引擎”。它经过ImageNet海量数据的训练,已经学会了如何将任何输入的图片转换成一个包含丰富语义信息的“图像表示”,也就是我们所说的嵌入向量(Embedding)。
- 任务模块 (红色方框内):这就是网络的“头”,在最基础的AlexNet里,它是由几个全连接层组成的分类器(FC6, FC7, FC8)。
那个红框里的“任务模块”是可插拔、可替换的。我们完全可以保留前面那个强大通用的“视觉引擎”不变,仅仅通过更换最后这个“任务模块”,来让整个网络去完成各种各样、五花八门的全新任务。
替换这个“任务模块”:
- 用于不同的图像分类领域
- 场景: 我们不再想识别ImageNet的1000个类别,而是想做一个只能识别10种不同花卉的分类器。
- 新模块: 我们只需要把原来输出1000个类别的FC8层,换成一个输出10个类别的新层,然后用我们的花卉数据进行简单的重新训练即可。这就是最经典的迁移学习。
- 用于图像描述
- 场景: 我们希望模型不再是输出一个单词标签,而是生成一整句话来描述图片内容(例如:“一只狗在草地上接飞盘”)。
- 新模块: 这时,我们需要把分类器换成一个完全不同类型的网络,循环神经网络。RNN擅长处理序列数据,它会接收“视觉引擎”给出的图像表示,然后一个词一个词地生成描述性的句子。
- 用于目标定位
- 场景: 我们不仅想知道图里有只猫,还想用一个边界框 (bounding box) 把它精确地圈出来。
- 新模块: 我们需要在原来的分类输出旁边,额外增加一个“回归”输出头。这个头通常也是一个全连接层,但它输出的是4个数字,分别代表边界框的中心点坐标 $(x,y)$、宽度和高度。
- 用于图像分割
- 场景: 这是个更精细的任务,我们想给图片里的每一个像素进行分类,比如把所有属于“猫”的像素涂成红色,属于“草地”的像素涂成绿色。
- 新模块: 这需要一个更复杂的“解码器”模块。它通常会用全卷积网络替换掉原来的全连接层,并使用反卷积层 等上采样技术,将浓缩的特征图逐步放大,直到恢复到和原图一样的大小,从而实现像素级别的预测。
现代计算机视觉的核心工作范式: 先在一个超大规模的数据集(如ImageNet)上,花费巨大资源预训练(Pre-training)一个强大的通用视觉特征提取器(也叫“骨干网络”,Backbone)。然后,在面对具体下游任务时,研究者们就可以像搭乐高一样,在这个通用的“主干”上,灵活地接上各种各樣的“任务头”,并用少量特定领域的数据进行微调(Fine-tuning),就能快速、高效地解决新问题。
2.2. ZFNet
在2013年,AlexNet的成功让人们对CNN的强大能力感到兴奋,但没有人能说清它内部到底发生了什么,为什么它会有效。ZFNet的作者(Matthew Zeiler 和 Rob Fergus)开创性地提出,我们必须找到一种方法去“看见”网络在每一层到底学到了什么。
ZFNet的主要贡献并非提出一个全新的网络架构,它的核心工作是打开CNN这个“黑箱”。为此,他们设计了一种名为“反卷积网络”(Deconvolutional Network, DeConvNet)的技术。这是一个“逆向工程”的工具:它能将网络在高层学习到的抽象特征(比如一个激活的神经元),一层层地反向映射回最初的像素空间。这样一来,研究者就能直观地看到,到底是输入图片中的哪个具体图案(比如一只猫的耳朵,或一个特定的纹理) 激活了网络中的某个特定神经元。
通过使用DeConvNet这个强大的诊断工具,ZFNet团队发现了AlexNet在第一层卷积层上的设计缺陷。主要有两个关键问题:
- 混叠/走样 和 中频信息丢失。
- 根本原因是采样率过低。
AlexNet的第一层卷积使用了非常大的 11×11 滤波器和非常大的步长(stride=4)。这就好比一个近视眼的人,一上来就想用一个超大号的、网格稀疏的放大镜去看东西。这样做的后果是,他看到的世界要么是模糊的色块(低频信息),要么是锐利的边缘(高频信息),但很多中间层次的、精细的纹理细节(中频信息)都在第一步就被粗暴地略过了。ZFNet的可视化结果证实了这一点,AlexNet第一层学到的特征质量并不理想。
在精确地诊断出问题后,ZFNet对AlexNet的架构进行了精准调整。两个主要改动:
- CONV1(第一层卷积): 将滤波器的尺寸从 11×11、步长4,改为了更小的 7×7、步长2。
- 目的: 减小滤波器和步长,等于让网络在第一步看得更仔细,保留更多原始图像的细节信息,从而解决了之前丢失中频信息和混叠的问题。
- CONV3,4,5(后续卷积层): 增加了滤波器的数量,从AlexNet的384, 384, 256个,增加到了512, 1024, 512个。
- 目的: 既然第一层现在能提供更丰富、更高质量的特征信息了,那么后续的层也应该有更大的“容量”(更多的滤波器)来处理和学习这些更复杂的特征。
通过这些看似微小但至关重要的调整,ZFNet在2013年的ImageNet挑战赛上,将Top-5错误率从AlexNet的约16.4%成功降低到了 11.7%,并赢得了当年的冠军。
2.3. VGGNet
2.3.1. 设计架构
VGGNet的设计美学可以概括为两个词:简洁和一致。它的核心设计准则:
- 只使用 3×3 的小尺寸滤波器:与AlexNet等前辈使用 11×11 或 5×5 等大尺寸滤波器不同,VGG的卷积层全部采用 3×3 这种最小的、能够捕捉上下文信息(上下左右中)的滤波器尺寸。
- 重复的“减半尺寸,加倍通道”模块:整个网络由一系列高度标准化的模块堆叠而成。每个模块包含若干个 3×3 卷积层,最后跟一个 2×2 的最大池化层。池化层的作用是将特征图的尺寸减半(例如从 112×112 降到 56×56),而紧接着的卷积层通常会将通道数加倍(例如从128增加到256),从而在压缩空间信息的同时,提炼出更丰富的特征信息。
这种极度规整的设计,使得VGGNet的结构非常容易理解和扩展,催生了VGG16(16层)和VGG19(19层)等不同深度的版本。
VGGNet最重要的洞见在于,使用多个堆叠的小尺寸滤波器,其效果要优于使用一个大尺寸滤波器。
- 洞见一:用更少的参数获得相同的感受野
- 感受野 (Receptive Field):指的是网络中一个神经元能够“看到”的输入图像区域的大小。
- 三个 3×3 的卷积层堆叠,其有效感受野等同于一个 7×7 的卷积层。
- 然而,在参数数量上,两者却有天壤之别。假设输入和输出的通道数都为C,那么:
- 一个 7×7 卷积层的参数量为:$(7\times7\times C)\times C=49C^2$
- 三个 3×3 卷积层的参数量为:$3\times(3\times3\times C)\times C=27C^2$
- 堆叠小滤波器的参数量远少于使用大滤波器,这使得网络在拥有相同“视野”的情况下更加轻量。
- 洞见二:引入更多的非线性
- 每一次卷积操作后,通常都会跟一个非线性激活函数(如ReLU)。
- 使用三个 3×3 卷积层,意味着我们可以在模型中插入三次非线性激活,而使用一个 7×7 卷积层只有一次。更多的非线性变换,意味着网络的学习和表达能力更强。
- 成绩:VGGNet在2014年的ImageNet挑战赛中,获得了分类任务的第二名和定位任务的第一名。
- 代价:它的主要缺点是参数量巨大。VGG16拥有约1.38亿个参数,且PPT明确指出,绝大多数参数都集中在最后的全连接层(FC layers)中。
- 补充知识:巨大的参数量使得VGGNet的训练和推理成本都非常高,模型文件也很大(超过500MB)。这正是当年击败它的GoogLeNet所要解决的核心问题。但即便如此,由于其简洁优雅的结构,VGGNet在很长一段时间里都是学术界进行各种研究(如迁移学习)时最受欢迎的基础模型之一。
- VGG-16的“标准建材”
- 卷积层 (CONV): 一律使用
3x3的小尺寸滤波器,步长为1,并采用“same”填充策略。- 补充知识:“same”填充通过在输入特征图的边缘补零,来确保卷积操作后的输出特征图在长和宽上与输入保持完全一致。
- 最大池化层 (MAX-POOL): 一律使用
2x2的窗口,步长为2。- 这会导致输出特征图的长和宽都精确地减半。
- VGG-16的细节
整个网络可以分为5个大的卷积区和一个最终的分类区。
- 输入: $224×224×3$ 的图像。
- Block 1
- 包含 2个 卷积层,每个层有 64个 滤波器。
- 数据流: $224×224×3→224×224×64$。
- 末尾接一个池化层,尺寸变为 $112×112×64$。
- Block 2
- 包含 2个 卷积层,每个层有 128个 滤波器。
- 数据流: $112×112×64→112×112×128$。
- 末尾接一个池化层,尺寸变为 $56×56×128$。
- Block 3
- 包含 3个 卷积层,每个层有 256个 滤波器。
- 数据流: $56×56×128→56×56×256$。
- 末尾接一个池化层,尺寸变为 28×28×256。
- Block 4
- 包含 3个 卷积层,每个层有 512个 滤波器。
- 数据流: $28×28×256→28×28×512$。
- 末尾接一个池化层,尺寸变为 $14×14×512$。
- Block 5
- 包含 3个 卷积层,每个层有 512个 滤波器。
- 数据流: $14×14×512→14×14×512$。
- 末尾接一个池化层,尺寸变为最终的 $7×7×512$。
- 分类
- 在经过5个区的特征提取后,我们得到了一个 $7×7×512$ 的浓缩特征图。
- 首先,将这个三维的特征图展平成一个一维向量,其维度为 $7×7×512=25,088$。
- 然后,这个向量被送入三层全连接网络(Fully Connected):
- 第一层 (FC6): 4096个神经元
- 第二层 (FC7): 4096个神经元
- 第三层 (FC8): 1000个神经元,正好对应ImageNet的1000个类别。
- 最后通过Softmax函数,得到这张图片属于1000个类别的最终概率。
VGG-16中16指的是网络中包含可学习参数的层的数量。
- 5个卷积区总共有 2+2+3+3+3=13 个卷积层。
- 分类总部有 3 个全连接层。
- 13(卷积)+3(全连接)=16 层。
- (注意:池化层没有可学习的参数,因此不计入总层数内)。
2.3.2. 可视化滤波器
我们使用一种名叫梯度提升的技术:
- 我们从一张充满随机噪声的空白图片开始。
- 我们选定VGG-16网络中某一层、某一个特定的滤波器。
- 我们将噪声图片输入网络,计算这个特定滤波器的激活值。
- 然后,我们以“最大化这个激活值”为目标,利用反向传播计算出梯度,并用这个梯度来微调输入图片上的像素。
- 不断重复第3、4步,这张噪声图片就会逐渐演变成最能“取悦”或“激活”我们选定的那个滤波器的样子。
![[Pasted image 20251002173145.png]] ![[Pasted image 20251002173159.png]]
- 第一层 (conv1_1): 基础的“视觉元素”
- 我们看到的是非常简单的颜色块、渐变色和基础的纹理,比如斜向的条纹。
- 这是网络学习的最底层、最基础的特征。它就像人类视觉系统的起点,首先学会识别构成世界的基本元素:边缘、颜色和方向。
- 第二、三层 (conv2_1, conv3_1): “视觉元素”的组合
- 图案开始变得复杂,出现了由简单线条组合而成的网格、圆点、更复杂的波浪纹等。
- 网络开始将第一层学到的基础元素进行组合,形成更有意义的“视觉基元”,比如角点、重复的纹理、简单的几何形状。
- 第四层 (conv4_1): 复杂的“材质纹理”
- 这里的图案已经非常像现实世界中的材质了,比如蜂巢、爬行动物的鳞片、编织物的纹理等。
- 网络已经学会了识别更高级的、由多种视觉基元构成的复杂纹理。这些特征对于区分物体类别非常有帮助。
- 第五层 (conv5_1): “物体部件”的雏形
- 在最深的卷积层,这些图案不再仅仅是纹理,而是开始呈现出具体物体的部件。最高层捕获了用于分类的物体纹理,例如羽毛、眼睛等等。
- 到了这一层,网络学习到的特征已经非常抽象和高级。它不再关心简单的线条和颜色,而是学会了识别那些对于最终分类至关重要的、具有高度语义信息的“概念”和“部件”。一个能被“眼睛”图案激活的滤波器,对于识别各种动物显然至关重要。
关键结论:
- 高层滤波器整合了更大感受野的复杂图案。随着网络层数的加深,每个滤波器能“看到”的原始图像区域(即感受野)也越大,这使得它能够学习到更宏观、更复杂的特征。
- 许多滤波器是相同图案的旋转版本。这表明网络为了识别不同方向的同一个特征(比如横着的边和竖着的边),会独立地学习出多个滤波器,这在某种程度上是一种冗余。
- 最高层捕捉的是分类所需的关键部件。
2.4. GoogLeNet
2.4.1. 设计架构
GoogLeNet在三个维度上都实现了突破:
- 性能更强: 它是 ILSVRC'14的冠军,Top-5错误率仅为 6.7%。
- 网络更深: 它拥有 22层 网络结构,比AlexNet(8层)和VGG16(16层)都要深,延续了“深度革命”的趋势。
- 模型更轻: 它的参数量仅有约 400万(4M),与AlexNet的6000万和VGGNet的1.38亿相比,显得极其轻巧高效。它实现这一点的关键在于几乎没有使用参数量巨大的全连接层。
GoogLeNet的创新在于Inception模块,核心主旨是让网络自己决定最佳的滤波器尺寸。在一张图片中,需要识别的信息尺度不一。识别一只狗的整个轮廓(大特征)可能需要一个较大的感受野(比如 5×5 的滤波器),而识别它的眼睛(小特征)则可能用一个 3×3 的滤波器更合适,识别最核心的瞳孔甚至用 1×1 就够了。
- nception模块的解决方案是“并行处理,丰俭由人”。在一个网络层中,它不再是只做一种操作,而是同时并行地进行多种操作:
- 进行一次 1×1 的卷积
- 进行一次 3×3 的卷积
- 进行一次 5×5 的卷积
- 进行一次 3×3 的最大池化
- 然后,它将这四条“支路”得到的结果在深度(通道)维度上拼接起来,形成最终的输出。
- 这样做的好处是,网络可以根据数据和任务的需求,在训练中自动学习给哪条支路分配更多的“权重”。如果 5×5 的大尺度特征很重要,网络就会加强这条通路;如果 1×1 的特征更关键,这条通路就会得到强化。
直接并行多个大卷积核的计算成本非常高。Inception模块巧妙地使用了大量的 1×1 卷积来作为“瓶颈层”,进行降维。
在进行计算成本高昂的 3×3 和 5×5 卷积之前,Inception模块会先用一个廉价的 1×1 卷积,将输入特征图的通道数(深度)大幅减少(例如从256维降到64维)。然后,再对这个“变薄”了的特征图进行卷积,计算量就大大降低了。最后再通过后续的卷积将维度升回去。这种“先压缩,再卷积,后扩张”的瓶颈设计,是GoogLeNet能保持极高效率的核心。
2.4.2. Inception模块
Inception模块的核心思想是“让网络自己决定用哪种滤波器”,所以它在一个层里并行地放置了多种尺寸的滤波器(比如 1×1,3×3,5×5)。想法虽好,但直接实现的计算成本极其高昂。
假设输入特征图的尺寸为 $28×28×192$(即长宽为28,有192个通道/深度)。我们希望通过 $5×5$ 卷积,得到一个 $28×28×32$ 的输出特征图。
- 所需的计算量(乘法操作次数)为:(滤波器尺寸×输入深度)×(输出特征图尺寸)$(5×5×192)×(28×28×32)$=4,800×25,088≈1.2亿次运算
- 仅仅是Inception模块中的一个分支就需要1.2亿次运算,这使得整个网络变得异常笨重和缓慢,完全违背了“高效”的初衷。
为了解决这个成本问题,在进行昂贵的 3×3 和 5×5 卷积之前,我们先用一个非常廉价的 1×1 卷积来进行降维。
还是以 5×5 卷积分支为例,新的流程分两步:
- 降维 (Squeeze): 先用16个 $1×1$ 的滤波器,将 $28×28×192$ 的输入特征图“压缩”成一个 $28×28×16$ 的“薄”特征图。
- 卷积 (Convolve): 然后再对这个“薄”得多的特征图进行 $5×5$ 的卷积,得到最终 $28×28×32$ 的输出。
第一步 (1x1卷积) 的成本: $$(1\times1\times192)\times(28\times28\times16)\approx240\text{万次运算}$$ 第二步 (5x5卷积) 的成本: $$(5\times5\times16)\times(28\times28\times32)\approx1000\text{万次运算}$$ 总成本: 两步相加,总共约为 1250万次运算。
这个 $1×1$ 的层常被称为“瓶颈”。它虽然尺寸是 $1×1$,但它的深度和输入通道数是一样的(即 $1×1×192$)。它的作用并非在空间上卷积,而是在通道维度上进行信息的融合与压缩。可以把它理解成一个微型的全连接网络,它对输入特征图的每个像素位置上的192个通道值进行加权求和,从而将192个特征通道浓缩成16个信息量更足的新特征通道。
2.4.3. 高效Inception模型
![[Pasted image 20251002174323.png]]
Inception模块的两个基本设计原则:
- 并行处理多尺度特征: 在一个层级里,同时进行 $1×1$、$3×3$、$5×5$ 的卷积以及池化操作,以捕捉不同尺度的信息。
- 保持空间尺寸不变: 所有的卷积操作都使用“same”填充,以确保输出的特征图在长和宽上与输入(例如 $28×28$)保持一致。
上方的图展示了一个朴素的实现方式:直接将输入(一个 $28×28×256$ 的特征图)并行送入四个分支,然后将结果拼接。这种方法的计算成本极其高昂。
下方的图,才是GoogLeNet实际采用的高效方案。它的核心就在于我们之前讨论过的 1×1 卷积瓶颈层。我们来逐一分析它的四个并行分支:
- 分支一: 1×1 卷积
- 这是最直接的分支。输入($28×28×256$)经过一个拥有128个滤波器的 $1×1$ 卷积,直接输出一个 $28×28×128$ 的特征图。
- 分支二: 3×3 卷积 (带瓶颈)
- 第一步 (降维): 输入($28×28×256$)先经过一个拥有64个滤波器的 $1×1$ 卷积,将通道数从256“压缩”到64,得到一个 $28×28×64$ 的中间层。
- 第二步 (卷积): 然后再对这个“变薄”了的中间层进行拥有192个滤波器的 $3×3$ 卷积,最终输出一个 $28×28×192$ 的特征图。
- 分支三: 5×5 卷积 (带瓶颈)
- 第一步 (降维): 同样,输入先经过一个拥有64个滤波器的 $1×1$ 卷积,得到一个 $28×28×64$ 的中间层。
- 第二步 (卷积): 再对这个中间层进行拥有96个滤波器的 $5×5$ 卷积,最终输出一个 $28×28×96$ 的特征图。
- 分支四: 池化 (带瓶颈)
- 第一步 (池化): 输入先经过一个 $3×3$ 的最大池化。池化操作本身不改变通道数,所以这一步的输出仍然是 $28×28×256$。如果直接拼接,这$256$个通道会带来巨大的计算负担。
- 第二步 (降维): 因此,在池化之后,再跟上一个拥有64个滤波器的 1×1 卷积,将通道数从256降到64,最终输出一个 28×28×64 的特征图。
最后,将这四个分支的输出特征图在深度(通道)维度上拼接在一起。最终的输出深度:
$$128(来自分支一)+192(来自分支二)+96(来自分支三)+64(来自分支四)=480$$
因此,这个Inception模块接收一个256通道的输入,最终输出一个包含480个通道的、融合了多尺度信息的特征图,尺寸为 $28×28×480$。
GoogLeNet的核心就是将我们之前详细分析过的Inception模块(图中的绿色方块)像积木一样大量地堆叠起来,形成一个非常深的网络。
![[Pasted image 20251002180020.png]]
但是,如果只是简单地无脑堆叠,网络是无法有效学习的。因此,GoogLeNet引入了两个重要的结构化设计:
设计一:通过池化层进行降采样
- Inception模块之间有时会穿插最大池化层。
- 我们知道,Inception模块内部通过“same”填充来保持特征图的长宽不变。为了让网络能够学习到不同层次的特征(从关注细节到关注全局),就必须逐步地减小特征图的空间尺寸。GoogLeNet采用的方法非常经典,就是在堆叠了几个Inception模块之后,插入一个标准的最大池化层 (Max Pooling)(图中的红色方块),将特征图的长宽减半。这个过程重复数次,就构成了“特征提取 → 降采样 → 特征提取 → 降采样...”的经典CNN结构。
设计二:用于保证训练效果的“辅助分类器”
- 为了保证良好的反向传播,一些分类器被注入到网络的中间部分。
- 这是GoogLeNet一个非常聪明的设计,目的是为了解决梯度消失的问题。
- 在一个像GoogLeNet这样深达22层的网络中,误差信号在从最后一层反向传播到最开始几层时,需要经过漫长的路径。在这个过程中,梯度信号可能会变得越来越微弱,甚至消失为零。这会导致网络的浅层部分得不到有效的训练。
- GoogLeNet的作者们在网络的中间位置,额外引出了两个“分支”,并在这两个分支上各自建立了一个小型的辅助分类器。可以把它们看作是两个“助推器”。
- 在训练阶段,网络的总损失函数(Loss)不仅包含最终主分类器的损失,还包含了这两个辅助分类器的损失(通常会乘以一个较小的权重)。这样一来,梯度信号就可以从网络的“中部”直接传递给前面的层,相当于给浅层和中层网络增加了额外的、强有力的“监督信号”,确保整个网络都能被充分训练。
- 重要提示: 这两个辅助分类器只在训练时使用。在模型训练完毕进行预测(推理)时,它们会被丢弃,我们只使用网络末端那个最终的、性能最好的主分类器。
2.5. ResNet
2.5.1. 深度网络的困难
从理论上讲,更深的网络应该表现得更好。
- 论点一:更强的表达能力
- 一个更深的网络拥有更多的层次和非线性变换,因此它是一个更强大的函数逼近器。理论上,它能够学习到比浅层网络更复杂、更精确的从输入到输出的映射关系。
- 论点二:恒等映射的“底线”
- 假设我们已经有了一个训练得很好的 $N$ 层浅层网络,其功能为
y = F(x)。 - 现在,我们通过在它上面堆叠几个“额外层”来构建一个更深的网络,其功能变为
y = G(F(x))。 - 从理论上讲,一个最坏的情况是,这个浅层网络
F(x)可能已经达到了最优。此时,新增的G层只需要学会成为一个恒等函数,即它的输出完全等于它的输入(G(z) = z)。这样一来,深层网络的最终输出G(F(x))将完全等同于浅层网络的输出F(x)。 - 因此,理论上的结论是:一个更深的网络,其性能最差也应该和它对应的浅层网络持平,而不应该变得更糟。
- 假设我们已经有了一个训练得很好的 $N$ 层浅层网络,其功能为
但是,在实践中,实验表明,当简单地把网络堆得更深时,模型的性能并不会持续提升。深度超过某个阈值后,继续增加网络的层数,反而会导致模型的性能急剧下降。
这个现象最令人困惑的地方在于,它不是我们通常所说的“过拟合”。模型无论是在训练集上还是在测试集上,表现都变得更差了。一个56层的网络,其训练误差可能比一个20层的网络还要高。
这说明问题不出在模型的泛化能力上,而是出在优化上。由于某些未知的原因,一个更深的网络变得更难训练了。优化器(如SGD)无法为这个更深的模型找到一个好的解。那些我们期望能轻松学会“恒等函数”的额外层,实际上却成了“累赘”,扰乱了整个训练过程。
2.5.2. 网络退化
理论上,一个足够宽的单层神经网络就足以拟合任何函数(这源于“全局近似定理”)。尽管有上述理论,但实践中的趋势却是将网络架构做得越来越深。这是因为实践证明,深度网络在学习层次化特征方面具有巨大优势,并且通常比同等性能的浅层宽网络需要更少的参数,即“参数效率”更高。
深度网络非常难以训练,一个主要原因是梯度消失问题。即在反向传播过程中,梯度信号在穿过多层后会变得极其微弱,导致网络的前几层几乎无法得到更新和学习。像GoogLeNet这样的模型,已经尝试通过在网络中部添加辅助损失函数的方式,来缓解深度网络的训练困难。但这更像是一个“补丁”,而非根本性的解决方案。
![[Pasted image 20251002181335.png]]
- 黄色线代表20层网络,红色线代表56层网络。
- 我们可以清晰地看到,随着训练的进行,更浅的20层网络(黄线)最终达到了比更深的56层网络(红线)更低的训练误差。
- 这证明了56层的网络性能更差,并非因为它发生了“过拟合”(如果过拟合,它的训练误差应该更低),而是因为它根本没有被很好地训练。这个更深的模型,其优化过程变得异常困难。
- 我们知道“深度”是提升性能的关键方向。
- 但简单粗暴地堆叠网络层数,会导致“网络退化”,即网络越深,训练越困难,效果反而越差。
- 这个问题不是过拟合,而是优化难题。
2.5.3. 残差模块
首先回顾一下问题的根源:在一个普通的深度网络中,我们期望那些“多余”的层能够学会恒等映射,即 输出 = 输入,从而不拖累整个网络的性能。但实践证明,让一堆非线性的卷积层去精确地拟合一个 H(x) = x 的恒等函数,是极其困难的。
ResNet的作者们提出了假设:
- 原始问题: 我们想让网络层(我们称之为
F)直接学习目标函数H(x)。 - 新思路: 我我们不再让网络层去学习完整的
H(x),而是让它去学习一个所谓的残差函数,即F(x) = H(x) - x。
如果在某个阶段,恒等映射 H(x) = x 已经是最佳选择了,那么在新的学习框架下,网络层需要学习的目标 F(x) 就变成了 x - x = 0。对于一个由卷积、权重和偏置项组成的复杂网络层来说,通过将所有权重参数推向0来让最终输出为0,远比精确地拟合出 y=x 这种恒等关系要容易得多。
为了实现上述思想,ResNet设计了如图所示的“残差模块”结构:
- 主路径: 输入
X照常通过两层或多层卷积网络。这个路径负责学习我们刚才定义的那个残差函数F(x)。 - 旁路/捷径 (Shortcut): 输入
X同时通过一条“捷径”,完全绕过了这些卷积层,不做任何改变,直接到达模块的末端。这条捷径也被称为残差连接。它提供的就是原始的x。 - 合并: 在模块的末端,将主路径的输出
F(x)和旁路的输出x按元素直接相加,得到F(x) + x。
这个最终的输出 F(x) + x 其实就等于 (H(x) - x) + x,也就是我们真正想学习的目标 H(x)。通过这种方式,网络依然在学习目标函数 H(x),但其内部的学习任务被“重构”和简化了。
![[Pasted image 20251002182907.png]]
这种设计的优势是立竿见影的:
- 解决了网络退化问题: 当增加新的残差模块时,如果这些模块对性能没有提升,网络只需要将这些模块主路径上的权重学习为0,让
F(x)=0即可。此时,输入信号x将通过跳跃连接“无损”地流过这个模块,网络性能不会下降。 - 使得训练超深度网络成为可能: 正是因为解决了退化问题,研究者们才能够成功地训练152层、200层甚至上千层的超深度网络。
- 计算成本低: 这个基础的残差模块本身只比两个普通的卷积层增加了一个几乎可以忽略不计的“加法”操作,非常高效。
- 在更深的ResNet(如ResNet-50及以上)中,作者还借鉴了GoogLeNet的思想,设计了更高效的“瓶颈(Bottleneck)”残差模块,使用 1×1 卷积来进行升维和降维,进一步降低了计算成本。
2.5.4. 架构
- 核心思想: 整个网络就是通过将“残差模块”一个接一个地堆叠起来而形成的。整个网络就是由许多个带有“跳跃连接”的模块组成的。
- 基本模块: 在较浅的ResNet(如ResNet-34)中,每个残差模块由两个 3×3 的卷积层构成 。
- 降采样策略: 网络会**周期性地将滤波器数量加倍,然后通过步长为2的池化(或卷积)来进行降采样。
- 这完全沿袭了VGGNet“尺寸减半,通道加倍”的经典设计,目的是为了在逐步压缩空间信息的同时,提取出更丰富、更抽象的特征。一个值得注意的细节是,ResNet通常不是用一个独立的池化层来降采样,而是巧妙地将某个残差模块中第一个卷积层的步长设置为2,从而在卷积的同时完成降采样,效率更高。
当网络变得非常深时(例如超过50层),两个 3×3 的卷积层计算成本依然很高。因此,ResNet的作者借鉴了GoogLeNet的成功经验,设计了一种更高效的“瓶颈”残差模块。
- 设计思路: 在效率上与GoogLeNet类似 (Similar to GoogleNet for efficiency)。
- 压缩 (Squeeze): 首先使用一个 1×1 卷积将输入的通道数大幅减少。例如,将一个 $28×28×256$ 的输入压缩成 $28×28×64$。
- 卷积 (Convolve): 然后,在一个通道数很少(64维)的“薄”特征图上进行计算成本高昂的 3×3 卷积。这远比在原始的256维特征图上进行卷积要便宜得多。
- 扩张 (Expand): 最后,再用另一个 1×1 卷积将通道数恢复到原来的维度,例如256维。
这个“两头小,中间大”的瓶颈结构,用更少的参数和计算量,实现了比两个 3×3 卷积更强大的特征学习能力,因此成为了深度ResNet(如ResNet-50, 101, 152)的标准配置。
![[Pasted image 20251002183820.png]]
正是凭借着残差模块(特别是瓶颈模块)的强大威力,ResNet成功解决了网络退化问题,使得训练前所未有的深度网络成为现实。ResNet能够在ImageNet上成功训练152层的超深度网络,并一举夺冠。
2.6. ReduNet
2.6.1. 黑箱问题
传统深度神经网络(Conventional Deep NN)的本质问题:
- 它是一个“黑箱”,意味着它的内部工作原理难以解释。
- 从数学上看,它通过将许多个未知的、复杂的函数
f_1, f_2, ...嵌套在一起(f(x) = g ° f_L ° ... ° f_2 ° f_1(x)),来学习一个从输入x到输出y的映射。 - 虽然我们知道这个模型很有效,但我们很难回答“为什么模型认为这张图片是猫而不是狗?”这类问题。这种不可解释性,在医疗、金融、自动驾驶等高风险领域是一个巨大的障碍。
ReduNet采用了一种“白箱”的方法,它的目标是构建一个可解释的深度网络。
- 核心区别: ReduNet不是去学习一个任意的、能解决问题的复杂函数。它的目标是学习一个特定的的函数
f(x, θ)。 - 优化目标: 这个特定函数的目标是最大化一个叫做“**率失真”的量,用
ΔR表示。 - “率失真”源自信息论,可以把它通俗地理解为“信息的压缩程度”。最大化率失真,就意味着我们要找到一种新的数据表示方式
z,使得数据在这个新的表示空间里变得尽可能地简洁、规整和有结构。
那么,这种“简洁、规整”的理想特征空间应该长什么样呢?ReduNet给出两个非常清晰的理想特性,并通过下面的示意图进行了可视化:
![[Pasted image 20251002184339.png]]
- 特性一:类内可压缩
- 定义: 属于同一个类别的所有数据(比如所有猫的图片),在经过ReduNet映射后,它们的特征应该被高度地“压缩”到一个低维的线性子空间。
- 在图的左边(输入空间),属于类别
M¹的红点原本杂乱地分布在一个弯曲的流形上;经过f(x, θ)映射后,在图的右边(特征空间),所有红点都整齐地排列在了一条直线S¹上。
- 特性二:类间可区分
- 定义: 用于表示不同类别的那些线性子空间之间,应该是“高度不相关的”,理想情况下应该是相互正交(垂直)的。
- 在图的右边,代表类别1的直线
S¹、代表类别2的直线S²和代表其他类别的直线Sʲ,它们之间都近似相互垂直。
ReduNet的可解释性就来源于这个清晰的几何结构。当一个新的图片输入时,我们先用 f(x, θ) 将它映射成特征空间里的一个点 z。接下来,分类过程就变得非常简单和透明:我们只需要计算 z 这个点离哪条代表类别的直线(子空间)最近,就判断它属于哪个类别。这个决策过程不再是一个黑箱,而是一个清晰的、可度量的几何问题。我们可以通过分析这些子空间的形态,来理解模型到底是如何区分不同类别的。
2.6.2. 网络设计
ReduNet的优化目标: $$\max_\theta\Delta R(Z)=\max_\theta(R-R^c)$$ 这个公式源自信息论:
- $R$ 代表描述整个数据集 $Z$ 所需要的信息量(或可以理解为数据所占的总体积)。
- $R^c$ 代表描述每个类别内部的数据所需要的信息量之和(即每个类内数据所占的体积之和)。
- $ΔR$ 就是“率失真”,即总体积减去类内体积之和。
最大化 $ΔR$ 需要做到两件事:
- 最大化 $R$: 让整个数据集的总体积尽可能大,这意味着要把不同类别的数据推得越远越好。
- 最小化 $R^c$: 让每个类别内部的数据体积尽可能小,这意味着要把同类别的数据压缩得越紧密越好。
为了实现这个目标,ReduNet使用了梯度上升法。目标函数 $ΔR$ 对特征 $Z$ 的梯度公式: $$\mathrm{Gradient~}\frac{\partial\Delta R}{\partial Z}=\underbrace{E_lz_l}{\mathrm{expansion}}-\underbrace{\sum C_l^jz_l}{\text{compression}}$$ 这个梯度可以被理解为作用在每个数据点 $z$ 上的两种相反的“力”:
- 扩张力: $E_l z_l$
- 它的作用是“将不同类别推开” 。
- 这个力使得不同类别的数据团块相互排斥,从而增大了整体的数据体积 $R$。
- 压缩力: $- Σ C_l^j z_l$
- 它的作用是“将每个类别的数据压平成一个子空间”。
- 这个力使得同一个类别的数据点向其内部的中心(或一个线性子空间,如一条直线)聚集、靠拢,从而减小了类内的体积 $R^c$。
![[Pasted image 20251002185105.png]]
- 初始状态 ($Z_l$): 在第 $l$ 步,数据点的分布还是比较混乱的,不同类别(红点和蓝点)交织在一起,分布在弯曲的流形上。
- 更新规则: 每一个数据点 $z$ 的位置,都会根据下面的标准梯度上升公式进行更新:$$Z_{l+1}=Z_l+\eta\cdot\left.\frac{\partial\Delta R}{\partial Z}\right|_{Z_l}$$ 这里的 $η$ 是学习率,代表每一步更新的幅度。这个公式的含义就是:让每个数据点 $z$ 沿着能最大化 $ΔR$ 的方向(即梯度方向)移动一小步。
- 更新后的状态 ($Z_{l+1}$): 经过一步更新后,我们可以看到数据分布变得更有序了。红点和蓝点各自被“压缩”得更紧密,同时两个类别之间被“扩张”得更分明。
ReduNet整个深度网络的设计,其每一层或每一个模块,都可以被看作是在执行一次或多次这样的梯度上升迭代。数据在网络中向前传播的过程,就等同于特征 Z 在这个优化过程中被不断迭代、逐步变得更有序的过程。这正是ReduNet被称为“白箱”的原因:它的网络结构直接对应了一个清晰、可解释的数学优化步骤,我们清楚地知道每一层到底在做什么。
3. 计算机视觉领域核心任务
3.1. 可视化并理解CNN
3.1.1. 遮挡敏感度分析
我们选取一张图片,并用一个色块(通常是灰色或黑色)遮住图像中的某一部分。一个例子是,将一张小狗图片中我们主观认为最重要的部分,即它的脸给完全盖住。
我们将这张被部分遮挡的图片,输入到已经训练好的CNN模型中,然后观察模型的预测结果或置信度发生了什么变化。
通过对比遮挡前后的结果,我们就能推断出模型到底有多“关注”被遮挡的那个区域。
- 理想情况:
- 如果我们遮住了狗的脸,模型的预测结果从“狗”变成了其他类别,或者虽然仍然预测是“狗”,但给出的置信度大幅下降。
- 这说明模型之前确实是依赖于脸部的特征(比如眼睛、鼻子、耳朵的形状)来识别出“狗”的。这证明模型学到的是物体的内在、关键特征。
- 糟糕情况:
- 如果预测准确率没有下降,那么这个神经网络并没有在学习这个物体的特定特征。
- 如果我们把狗的脸都盖住了,模型依然能毫无压力、高枕无忧地以极高的置信度输出“狗”,这就亮起了红灯。这强烈暗示,模型做出“狗”的判断,依据的可能根本不是狗本身,而是图片中的其他线索,比如背景里的草地、狗的爪子形状、甚至是照片的整体色调等它在训练集中学到的某种虚假关联。
一个更严谨的流程是,生成一张能够直观显示模型“注意力”所在的“概率热力图”或“显著性图”。
生成热力图的步骤:
- 第一步:滑动遮挡 (Sliding Mask)
- 我们不再像之前那样只遮挡一个主观认为重要的区域,而是用一个灰色的小方块,系统性地、一步步地滑过整张输入图像。每移动到一个新位置,就生成一张新的、被部分遮挡的图片。
- 第二步:计算并记录概率 (Compute Probability)
- 对于每一个被遮挡的图片版本,我们都将它输入到训练好的CNN模型中。
- 然后,我们记录下模型对正确类别预测的概率值。例如,对于一张大象的图片,我们记录模型预测其为“大象”的概率是多少。
在对所有可能的位置都进行了一遍遮挡和预测后,我们就可以生成最终的热力图了。
- 生成过程: 我们创建一个与原图大小相同的空白图像,然后根据上一步记录的概率值,为每个像素(或区域)上色。
- 上色后的热力图中,区域越暗,代表(遮挡后)正确分类的概率越低,也代表这个像素越重要。
![[Pasted image 20251002200334.png]]
优点:
- 模型调试: 这种方法是检测“作弊”模型的利器。如果一个区分“哈士奇”和“狼”的模型,其热力图在雪地背景上是红色的,而在动物身上是黄色的,我们就能立刻发现这个模型学错了东西。
- 建立信任: 在医疗诊断等高风险领域,医生可以通过热力图来确认AI模型是否在关注病灶区域,从而决定是否采信其诊断结果。
- 弱监督定位: 即使模型没有经过专门的目标定位训练,这张热力图也粗略地框出了物体的位置,实现了“免费”的定位效果。
缺点:
- 计算量巨大: 对一张图片生成热力图,需要进行成千上万次模型预测,速度非常慢。
- 遮挡块的干扰: 灰色方块本身也是一种输入模式,有时模型可能会对这个方块产生“反应”,从而干扰热力图的准确性。
- 更先进的方法: 正因为有这些局限,后来研究者们提出了更高效、更精确的热力图生成方法,比如基于梯度的Grad-CAM等。这些方法通常只需要一次前向和一次反向传播就能生成热力图,但其核心思想,找到对模型决策贡献最大的区域与遮挡法是一脉相承的。
3.1.2. 梯度提升
我们先将一个训练好的CNN模型的所有权重都固定住。然后,我们的目标不再是分析一张已有的图片,而是要从零开始生成一张全新的、合成的图片。这张图片的要求只有一个:它必须能让网络中某个特定神经元(比如代表“狐狸”的那个输出神经元)的激活值达到最大。
- 从一张白纸开始 (Initialize): 我们从一张纯黑或充满随机噪声的图片 $I$ 开始。
- 前向传播: 将这张图片输入网络,看看代表“狐狸”的神经元此刻的得分 $S_c(I)$ 是多少。可想而知,一开始得分会很低。
- 反向传播: 我们利用反向传播,但这次我们计算的不是损失函数对权重的梯度(那是训练网络),而是“狐狸”神经元的得分对输入图片的每一个像素的梯度。
- 这个梯度 $∂S_c/∂I$ 的直观含义是:“要想让‘狐狸’的得分更高,这张图片的每个像素应该朝哪个颜色方向变化一点点?”
- 图像更新: 我们根据算出的梯度,对原始图片的每个像素值进行一次微小的更新。
- 重复: 我们不断地重复2-4步。每一次迭代,这张图片都会被修改得更“像”网络心目中的“狐狸”一点点。成百上千次迭代后,图片上就会浮现出网络对“狐狸”这个概念的“理解”。
这个迭代过程所遵循的数学目标的公式: $$\arg\max_IS_c(I)-\lambda||I||_2^2$$
- $arg max_I S_c(I)$ : 这是我们的主要目标,即寻找一张图片 $I$,使得我们关心的类别 $c$ 的得分 $S_c(I)$ 最大化。
- $- λ||I||_2^2$ : 这是一个正则化项。
- 这个正则项至关重要。如果没有它,算法会发现提升得分最快的方法是生成一些包含极端像素值的高频噪声“攻击”图片,因为这些图片最能“欺骗”网络。这个正则项通过惩罚过大的像素值,鼓励算法生成更平滑、更自然的图像。
用这种方法生成的图片有这些特点:
- 非真实感: 这些图片并不像真实的照片,而更像是光怪陆离、充满迷幻色彩的“梦境”。
- 重复的模式: 最显著的特征是模式的重复。例如,为“狐狸”生成的图片上布满了狐狸的脸和耳朵;为“哑铃”生成的图片上则满是哑铃的形状和肌肉的纹理。
- 因为一旦算法发现某个图案(比如一个狐狸头)能有效提升“狐狸”神经元的得分,它就会认为“越多这样的图案越好”,于是就在图片上反复绘制这个图案。这揭示了传统CNN的一个特性:它擅长识别特征的存在,但对物体的“整体性”和“唯一性”没有很强的概念。
- 概念的可视化: 这些图片让我们得以直观地看到网络是如何“定义”一个概念的。例如,为“豪华轿车”生成的图片布满了拉长的车身和重复的车轮,这说明网络学到的关键特征就是“长”和“轮子多”。
![[Pasted image 20251002201002.png]]
3.1.3. 最大激活块
这种方法的三个步骤:
- 选择并记录: 首先,我们从训练好的网络中挑选一个特定的神经元(或滤波器)。然后,我们将一个巨大的图像数据集(比如数万张真实的验证图片)输入网络,并记录下我们挑选的这个神经元在看到每一张图片(或图片中的某个区域)时的激活值(即它的“兴奋”程度)。
- 排序并筛: 在记录了所有激活值之后,我们进行排序,找出最能让这个神经元“兴奋”的前
k张图片(比如k=9或10)。 - 展示: 最后,我们将这
k张图片中对应的区域展示出来。这些区域就是这个神经元的激活域,是它在真实世界中最想看到的图案。
这种方法的可视化为我们揭示了网络内部的特征层级。
![[Pasted image 20251002201247.png]]
- 浅层神经元(左图):
- 左侧的图展示了网络浅层的一些神经元所“喜欢”的图案。每一行对应一个神经元。
- 观察: 我们可以清晰地看到,这些神经元是简单模式的检测器。
- 神经元1 显然是一个“眼睛检测器”。
- 神经元2 似乎喜欢检测尖角或特定角度的线条。
- 下面还有的神经元是“文字检测器”或“圆形纹理检测器”。
- 高层神经元(右图):
- 右侧的图展示了网络高层神经元所对应的图片块。高层神经元拥有更大的感受野(LRFs),因此它们看到的图片区域也更大。
- 观察: 这些神经元检测的是更复杂、更具语义的物体或部件。
- 比如,我们能看到“人脸检测器”、“狗头检测器”、“车轮检测器”等。
将左右两图对比,就完美地印证了CNN的分层学习理论:网络首先在浅层学习到简单的边缘、颜色和纹理(如左图),然后在高层将这些简单的“零件”组合起来,形成了能够识别复杂物体部件(如右图)的、更高级的“概念”。
3.1.4. 卷积的本质
卷积操作,在计算上等同于计算滤波器和它所覆盖的图像局部感受野之间的点积。
点积的两种表达方式。我们先看代数定义,因为它描述了计算机的实际运算过程: $$w^Tx=\sum_{ij}x_{ij}w_{ij}$$ 这里的 w 代表滤波器的权重,x 代表图片上对应的像素块。这个公式的意思就是,将滤波器和图片块的对应元素相乘,然后将所有乘积加起来,得到一个最终的数值(即该位置的激活值)。
那么,这个计算过程的意义是什么呢?这就需要看点积的几何定义: $$u∘v=∣u∣∣v∣cos(θ)$$
- 这里的
u和v可以看作是两个向量(即滤波器和图片块),θ是它们之间的夹角。 - 这个公式告诉我们,点积衡量的是两个向量的相似度或对齐程度。
- 当两个向量方向完全一致时(
θ = 0),cos(θ)取得最大值1,点积也最大。
将这个数学意义带回到卷积的场景中,我们就得出了一个至关重要的结论:卷积操作的输出值,在当局部感受野的图案与滤波器的图案完全匹配时,会取得最大值。
基于以上的数学原理,我们可以得出一个非常直观的理解:每一个卷积滤波器,本质上都是一个“模式检测器”。
- 一个滤波器的权重被设计(或学习)成什么样,它就在寻找什么样的模式。
- 例如,一个权重形似“垂直线”的滤波器,当它滑过图像中的垂直边缘时,点积结果就会很大,从而产生一个强烈的激活信号。
- 一个权重形似“左绿右红”的颜色渐变滤波器,当它看到对应的颜色渐变时,就会被强烈激活。
![[Pasted image 20251002202120.png]]
图为四个著名网络在ImageNet上训练完成后,其第一层卷积滤波器权重的可视化结果。它们代表了这些网络学会的最基础的“视觉元素”。
- AlexNet:
- 拥有64个 11×11×3 的滤波器。
- 我们可以看到,AlexNet的滤波器已经学习到了对不同方向的边缘和不同颜色的反应。但由于其 11×11 的滤波器尺寸过大,导致一些滤波器模式看起来比较“粗糙”和“混杂”。
- ResNet-18, ResNet-101, DenseNet-121:
- 这三个更现代的网络都使用了64个 7×7×3 的滤波器。
- 与AlexNet相比,这些现代网络学习到的第一层滤波器明显更加平滑、清晰和多样化。它们看起来就像一个教科书般的“基底”集合,包含了大量不同方向、不同频率的边缘检测器(也叫“Gabor滤波器”)和颜色检测器。
- 这通常被认为是这些高级网络(特别是ResNet)的训练过程更稳定、更有效的证据。它们能够自发地学习到一套对于视觉任务而言更优、更“正交”的基础特征,为后续网络层学习更复杂的模式打下了坚实的基础。
- 这三个更现代的网络都使用了64个 7×7×3 的滤波器。
下面我们纵向来看,每一层的卷积滤波器的可视化结果:
![[Pasted image 20251002202408.png]]
第一层是用于边缘检测的模板。这96个方格不是真实的图片,而是将每个滤波器内部的权重数值直接可视化成的图像。我们可以清晰地看到,这些滤波器自发地学习成为了两类最基础的“模式检测器”:
- 边缘和方向检测器: 大量黑白的滤波器呈现出不同方向的亮暗条纹,它们分别对水平、垂直、45度、135度等方向的边缘最为敏感。
- 颜色检测器: 另一些彩色的滤波器则学习检测特定的颜色组合或颜色渐变,例如从绿色到紫色,或从橙色到蓝色的对立色模式。
![[Pasted image 20251002202458.png]]
- 左侧(真实图片块): 这是“最大激活块”技术。研究者们从海量真实图片中,找到了最能激活该层某个特定滤波器的9个图片块(top-9 patches)。
- 右侧(重建图案): 这是“反卷积重建”技术。它将那个被高度激活的特征,通过网络反向传播映射回像素空间,从而“画”出这个滤波器“心目中”最理想的图案是什么样的。
图案看起来更模糊,因为ReLU激活函数和池化操作导致了信息损失。
- 第二层 (Layer 2):
- 一个被选中的滤波器,其最喜欢的9张图块无一例外都是眼睛。
- 网络已经开始将第一层的“字母”(边缘、颜色)组合成“单词”——即有意义的物体部件。这个滤波器已经成为了一个“眼睛检测器”。
- 第三层 (Layer 3):
- 滤波器被人脸和蜂巢等更复杂的模式激活。
- 网络正在将第二层的“单词”(如眼睛、鼻子)组合成“短语”。它学会了识别由多个部件构成的、更复杂的概念。
- 第四层 (Layer 4):
- 滤波器被各种各样的狗脸激活。
- 网络的识别能力变得更加具体和精细。它不再只是识别人脸的通用概念,而是学习到了专门用于识别“狗脸”的、更具针对性的特征。
- 第五层 (Layer 5):
- 滤波器被花朵、相机镜头等具有相似放射状结构的物体激活。
- 到了最高层的卷积层,网络学习到的特征变得非常抽象。这个滤波器已经超越了具体物体的范畴,成为了一个“中心-放射状图案”的检测器,这个抽象概念可以被用来识别很多不同的物体类别。
3.1.5. 相似性
对寻找相似的图片,一种最符合数学直觉的方案是:
- 方法: 在“像素空间”中寻找最近邻。
- 度量: 使用欧几里得距离,也就是计算两张图片每个对应像素值之差的平方和。
这个方法将每张图片看作一个由所有像素值组成的高维向量。两张图片A和B之间的距离可以表示为:
$$\mathrm{Distance}(A,B)=\sum_{i=1}^n(A_i-B_i)^2.$$
其中,$A_i$ 和 $B_i$ 分别是图片A和B第 $i$ 个像素的数值,$n$ 是总像素数。距离值越小,代表两张图片在像素层面上越“相似”。这就是K-NN分类器时所用的L2距离。
但是这么做是有问题的,结果上也很差。因为在算法(像素距离)的眼中,这些图片是“相似的”,所以才会被检索出来。但在人类的眼中,它们在语义上是完全不同的物体。像素空间的相似性 ≠ 语义空间的相似性。
所以我们要寻找语义空间内相似的向量,CNN提供了机会。
- 我们先用一个强大的、在ImageNet上预训练好的CNN模型(比如VGG或ResNet)。
- 我们将我们所有的图片(比如一个巨大的图库)一张张地输入这个模型,并为每一张图片提取出它对应的特征向量(例如一个4096维的向量)。
- 当用户提供一张“查询图片”时,我们也用同样的方法将它转换成一个“查询向量”。
- 接下来,我们在这个高维的特征空间中,使用欧几里得距离等度量方法,计算“查询向量”与图库中所有其他向量的距离。
- 最后,我们找出距离最小的几个向量,并将它们所对应的原始图片返回给用户。
![[Pasted image 20251002204256.png]]
算法找到了像素不同但语义相似的图片,CNN通过其层次化的结构,学习到了对平移、旋转、缩放、光照等变化具有不变性的特征表示。它能够“看透”这些表面的、像素层级的差异,直达物体内在的、最本质的语义核心。它将这种语义上的相似性,转化为了特征空间中向量之间的“距离相近”。
这项技术正是所有现代“以图搜图”或“反向图片搜索”引擎(如Google Images的搜图功能)的基石。它也被广泛应用于电子商务中的“相似商品推荐”、安防领域的“行人重识别”(Re-ID)以及数字资产管理中的“重复图片检测”等场景。
经过深度神经网络学习到的特征空间,才是一个真正有意义的、能够用来衡量图片之间语义相似度的空间。CNN最伟大的能力之一,就是将杂乱无章的像素世界,重新组织成一个结构清晰、语义明确的特征世界。
3.1.6. 可视化地图
![[Pasted image 20251002203756.png]]
我们的目标是为ILSVRC 2012的5万张验证集图片绘制一张尽可能把相似的物体放在一起的地图。
- 第一步:特征提取
- 首先,将这5万张图片中的每一张,都输入到一个预训练好的CNN模型中(比如AlexNet)。
- 然后,为每一张图片提取出其4096维的特征向量。经过这一步,我们就把5万张图片,转换成了5万个在4096维高维空间中的数据点。
- 第二步:降维
- 人类无法想象和观察一个4096维的空间。为了能将这些数据点画在一张平面图上,我们需要使用降维算法,将这5万个4096维的向量,一一映射成2维的坐标点(即每个图片都有一个唯一的x, y坐标)。
- 补充知识: 完成这种可视化任务最著名、效果最好的算法叫做 t-SNE。t-SNE算法的目标是,在降维的过程中,尽可能地保持数据点之间的“邻里关系”。简单来说,就是在原来4096维空间中彼此靠近的点,在降维到2维平面后,它们依然会聚集在一起;而在高维空间中相距遥远的点,在2维平面上也会被分开。
经过上述步骤,我们就得到了由5万张小图片拼接而成的“语义地图”。地图上每一个点的位置,就是t-SNE算法为它计算出的(x, y)坐标。
- 宏观观察: 我们第一眼就能看到,这张地图并非杂乱无章的像素噪音。它呈现出了清晰的结构,仿佛一张世界地图,有“大陆”、“海洋”和“岛屿”。这本身就证明了CNN的特征空间是高度结构化的。
这张地图的两个“区域”:
- 左下角的“自然大陆”: 蓝色箭头指向的区域(由黄色方框标出),放大后我们看到,这里聚集了各种各样的蝴蝶、昆虫和花朵。这说明,在CNN的“认知”里,这些东西在视觉上是相似的,因此它们的特征向量在空间中的位置也彼此靠近。
- 右上角的“交通工具大陆”: 黄色箭头指向的区域(由红色方框标出),放大后我们看到了飞机的“社区”和轮船/帆船的“社区”。
- 这不仅说明模型能把所有的人造交通工具聚类在一起,甚至在这个“交通工具大陆”内部,还形成了更细分的“街区”。所有飞机的特征向量彼此靠近,所有船的特征向量也彼此靠近。同时,“飞机街区”和“轮船街区”又同属于一个更大的“交通工具大陆”,因为它们在语义上都比“蝴蝶”更相似。
- CNN学习到的特征空间是一个“语义空间”: 空间中的距离直接反映了图片内容在语义上的相似度。
- 网络具备自动聚类的能力: 在没有任何特定指令的情况下,CNN仅通过学习分类任务,就自发地将具有相似视觉概念的图片在特征空间中组织到了一起。
3.2. 目标定位
3.2.1. 回顾ResNet
前向传播 (Forward feeding): 数据从第 i 层传到第 i+1 层,公式为: $$x_{i+1}=\sigma(s_i)\quad\text{其中}\quad s_i=W_ix_i+b_i$$ 这里的 σ 是激活函数,以Sigmoid为例。
反向传播 (BP): 梯度(误差信号)从第 i+1 层传回第 i 层。根据链式法则,梯度的关系为: $$\delta_i=\frac{\partial J}{\partial x_i}=\delta_{i+1}\cdot\sigma(s_i)(1-\sigma(s_i))\cdot W_i$$ Sigmoid函数的导数的最大值不会超过0.25,梯度每反向传播一层,它的大小至少会被乘以一个小于0.25的数(通常还会乘以一个小于1的权重 W)。当网络非常深时,会出现梯度消失问题。
ResNet引入了跳跃连接,前向传播的公式变为(简化后): $$x_{i+1}=x_i+\sigma(s_i)$$ 反向传播 (BP): 此时,我们再来计算梯度: $$\delta_i=\frac{\partial J}{\partial x_i}=\frac{\partial J}{\partial x_{i+1}}\cdot\frac{\partial x_{i+1}}{\partial x_i}=\delta_{i+1}\cdot\frac{\partial}{\partial x_i}(x_i+\sigma(s_i))$$ 得到: $$\delta_i=\delta_{i+1}\cdot(1+\sigma(s_i)(1-\sigma(s_i))\cdot W_i)$$ 公式与普通网络公式的唯一、也是最关键的区别——括号里多了一个“1 +”。
- 这个“1”来自于跳跃连接 $x_i$ 对自身的求导。它构建了一条梯度的“高速公路”。
- 这意味着,即使后面那一项 $σ(s_i)(1 - σ(s_i)) * W_i$ 因为很小而趋近于0,梯度 $δ_{i+1}$ 依然可以畅通无阻地通过这个“1”直接传递给 $δ_i$。梯度消失问题就解决了。
同时:
- 堆叠2个 3×3 卷积,其感受野等效于一个 5×5 卷积;堆叠3个 3×3 卷积,其感受野等效于一个 7×7 卷积。
- ResNet的结构是由许多个残差模块堆叠而成。由于跳跃连接的存在,信息流在网络中形成了多种路径。信号可以选择穿过一个残差模块的卷积层,也可以选择“跳过”它。
- 在一个很深的ResNet里,信号可以通过一条很短的路径(比如只经过一个残差模块),从而获得一个较小的感受野(如 3×3);也可以通过一条很长的路径(比如连续穿过两三个残差模块的卷积层),从而获得一个更大的感受野(如 5×5 或 7×7)。
- 因此,ResNet的结构在某种意义上隐式地实现了一个“网络集合”,其中包含了不同深度、不同感受野的子网络。这使得它能够像GoogLeNet的Inception模块那样,自适应地学习和融合多尺度的特征,但实现方式更为简洁和隐式。
ResNet成功的两大支柱:
- 优化上的优越性: 通过加性的跳跃连接,彻底解决了深度网络的梯度消失问题,使得网络“想搭多深就能搭多深”。
- 表征上的强大性: 这种结构隐式地创建了多条不同长度的路径,使得网络能够自然地学习到多尺度的特征,实现了与GoogLeNet异曲同工之妙。
3.2.2. 图像分类、目标定位和目标检测
- 图像分类
- 定义: 识别出一张图片中的物体是什么。
- 这是最基础的计算机视觉任务。它的核心假设是:一张图片里只有一个主要物体。模型的唯一职责就是回答“这里面有什么?”这个问题。
- 输入:一张包含一辆汽车的图片。
- 输出:一个单一的标签——“Car”。
- 大部分模型,如AlexNet、VGGNet、GoogLeNet和ResNet,在ImageNet上解决的核心问题就是图像分类。
- 分类与定位
- 定义: 识别出物体是什么,并用一个边界框标出它的位置 。
- 这个任务在分类的基础上增加了一个要求。它不仅要回答“是什么?”,还要回答“它在哪?”。它通常也假设图片中只有一个主要待办识物体。
- 输入:同样是那张包含汽车的图片。
- 输出:两部分信息——标签“Car”以及一个框住汽车的红色方框。
- 要完成这个任务,神经网络通常需要有两个输出“头”:一个分类头(用于输出类别概率)和一个回归头(用于输出4个代表边界框位置和大小的坐标值)。
- 目标检测
- 定义: 检测并定位出图片中所有的(通常是多个)物体。
- 这是前两个任务的泛化和升级,更贴近真实世界的复杂场景。它需要回答的问题是:“图里都有什么东西?它们分别在哪里?”。它需要处理多个物体和多个类别的情况。
- 输入:一张包含两辆汽车的图片。
- 输出:两个边界框,分别框住两辆不同的汽车。如果图片里还有行人,模型也应该把行人框出来并标记为“pedestrian”。
- 目标检测是计算机视觉领域应用最广泛、也最具挑战性的任务之一,是自动驾驶、视频监控、智能安防等应用的核心技术。要解决这个复杂问题,需要专门设计的网络架构。
3.2.3. 从分类模型升级为定位模型
首先,我们假设有一个神经网络,它的任务是识别图片中的物体。除了具体的物体类别(如行人、汽车、摩托车),我们还增加了一个特殊的类别——“背景”(background),用来表示图片中没有我们感兴趣的物体。
为了完成定位任务,我们必须重新设计网络的输出层,让它能提供更丰富的信息。我们定义一个全新的输出向量格式: $$\mathrm{Output}=(p_c,b_x,b_y,b_h,b_w,c_1,c_2,c_3)$$
- $p_c$: 这是一个“物体置信度”分数,代表图片中是否存在一个我们感兴趣的物体。如果 $p_c=0$,表示这是背景;如果 $p_c=1$,表示存在一个物体。
- $(b_x,b_y,b_h,b_w)$: 这是4个用来描述边界框的数字,它们是回归任务的输出。
- 这4个值通常是归一化的。即把图片的左上角看作坐标
(0,0),右下角看作(1,1)。 - $(b_x,b_y)$: 边界框的中心点坐标。
- $(b_h,b_w)$: 边界框的高度和宽度,它们是相对于整张图片尺寸的比例。
- 例如 $b_x=0.5, b_y=0.7, b_h=0.3, b_w=0.4$ 描述了一个中心点在图片水平中线、垂直70%靠下的位置,其高度是图片总高度的30%,宽度是图片总宽度的40%的框。
- 这4个值通常是归一化的。即把图片的左上角看作坐标
- $(c_1,c_2,c_3)$: 这是分类任务的输出,代表在 $p_c=1$ 的前提下,这个物体分别是“行人”、“汽车”、“摩托车”的概率。
要让模型学会输出这样一个复杂的向量,我们需要两样东西:特殊的训练数据和特殊的损失函数。
- 训练数据:
- **训练集需要包含边界框信息和标签。
- 这意味着我们的数据标注工作变得更复杂了。对于每一张训练图片,标注员不仅要告诉模型“这是一辆车”,还必须手动框出这辆车的位置,并提供这个框的4个坐标值。
- 损失函数 (Loss Function):
- 由于模型需要同时完成两个任务(回归和分类),我们需要一个“多任务损失函数”来同时衡量两个任务的完成情况。其基本形式:$$\mathrm{Loss}=\lambda L_1+L_2$$
- $L_1$ 是分类误差。这部分通常使用交叉熵损失函数来计算。它只在 $p_c=1$ 时才被计算。
- $L_2$ 是边界框误差。这部分是回归损失,通常使用$L_2$损失(均方误差)或Smooth $L_1$损失来计算预测的4个坐标值与真实值的差距。它也只在 $p_c=1$ 时才被计算。
- $λ$: 这是一个超参数,用来平衡分类任务和回归任务的重要性。通过调整 $λ$ 的大小,我们可以控制模型在训练时更侧重于“认得准”还是“框得准”。
将一个标准CNN改造为定位模型的核心技术思想:
- 输出端改造: 将单一的分类输出,扩展为一个包含物体置信度、边界框坐标和具体类别的复合向量。
- 训练端改造: 使用一个多任务损失函数,同时对模型的分类能力和定位(回归)能力进行监督和优化。
3.2.4. 姿态检测
姿态检测的目标不再是找出一个物体的粗略边界框,而是要精确地定位出物体(通常是人体)身上一系列预定义关键点的坐标。
![[Pasted image 20251002210757.png]]
型的输出是一长串的坐标值: $$(l_{1x},l_{1y}),\ldots,(l_{16x},l_{16y})$$ 这代表模型需要预测16个关键点的 $(x, y)$ 坐标,总共需要输出32个数字。这些关键点可以包括头顶、肩膀、手肘、手腕、膝盖、脚踝等。将这些点按人体结构连接起来,就能形成一个描述姿态的“火柴人”或“骨架”。
实现姿态检测的架构依然遵循我们已经熟悉的模式:
- 特征提取: 首先,将输入的图片(例如图中的网球运动员)送入一个强大的CNN主干网络(如图中所示的AlexNet类结构)。这个网络作为通用的特征提取器,将整张图片浓缩成一个包含高级语义信息的特征向量(图中示例为一个4096维的向量)。
- 回归头: 接下来,将这个高维特征向量送入一个专门用于此任务的“任务头”。与分类任务不同,这个头是一个纯粹的回归头。它通常由一个或多个全连接层组成,其最终的输出层有32个神经元,正好对应我们需要预测的16个关键点的
x和y坐标。
要让网络学会如何精确地定位这些关键点,其训练过程也需要进行相应的设计。
- 训练数据 (补充知识): 姿态检测的训练数据标注成本非常高昂。对于每一张训练图片,都需要标注员手动地、精确地在每个关键点(如左脚踝、右肩膀)上打点,记录下它们的像素坐标。
- 损失函数 (Loss Function):
- 如图所示,对于每一个被预测的关键点(如左脚、右脚、头顶),我们都会计算它的预测坐标与真实标签坐标之间的L2损失。
- 总损失: 整个模型的总损失(Total Loss),就是所有单个关键点损失的总和。 $$\mathrm{Total~Loss}=\sum_{k=1}^{16}\mathrm{L2~Loss}_k$$ 神经网络的训练目标,就是通过调整权重,来最小化这个总损失。这会驱使模型同时将所有预测的关键点,都尽可能地移动到它们各自的真实位置上。
姿态检测是许多现代AI应用的核心技术,例如:
- 动作识别: 通过分析视频中人体骨架序列的变化,可以识别出“跑步”、“跳跃”、“挥手”等动作。
- AR特效: 手机App中的AR滤镜(比如给你戴上虚拟帽子或眼镜)就是通过实时检测你面部或身体的关键点来实现精准叠加的。
- 运动健身与康复: AI健身应用可以通过摄像头分析你的运动姿态(如深蹲、瑜伽)是否标准,并给出指导。
- 人机交互: 通过识别手势或身体姿态来控制设备。
3.2.5. 地标点检测
地标点是物体上一些重要特征点的坐标。在人脸识别中,这些点就是眼睛、眉毛、鼻子、嘴巴和脸部轮廓的位置。模型的任务是接收一张人脸图片,并输出一张精细的“面部地图”,即精确预测出脸上所有预定义地标点的 (x, y)坐标。
展示的例子是需要检测64个地标点。因此,模型的最终输出是一个包含 64 * 2 = 128 个数值的长向量: $$(l_{1x},l_{1y}),(l_{2x},l_{2y}),\ldots,(l_{64x},l_{64y})$$ ![[Pasted image 20251002211317.png]]
完成此任务的一种典型的网络结构采用了多任务学习的思路。
- 特征提取: 首先,输入的图片经过一个ConvNet(卷积神经网络)。和之前一样,这个网络的主体部分作为特征提取器,将原始的像素信息转换为高级的语义特征。
- 多任务输出头: 网络的末端不再是单一的输出,而是分叉成了两个(或更多)并行的“任务头”:
- 分类头: 一个小的分支用来做一个简单的二元分类任务,回答“图片里有人脸吗?(face?)”。
- 回归头: 一个大的主分支用来完成主要的回归任务,即输出那128个地标点的坐标值。
这个网络的总输出维度是129,正是 1 (用于“face?”的分类输出) + 128 (用于64个地标点坐标的回归输出)。
与姿态检测一样,地标点检测的训练数据也需要极其精细的人工标注。标注员需要在成千上万张人脸图片上,为每一个地标点(如左眼角、鼻尖、下嘴唇中心等)精确地打上坐标。
训练这样一个多任务模型,需要一个复合的损失函数,通常是各个任务损失的加权和: $$\mathrm{Total~Loss}=\lambda_1\cdot\mathrm{Loss}\text{classification}+\lambda_2\cdot\mathrm{Loss}\text{regression}$$ 人脸地标点检测是当今应用最广泛的计算机视觉技术之一,它是许多上层应用的基石:
- AR特效/滤镜: 手机拍照App(如抖音、Snapchat、Instagram)中给你戴上眼镜、画上妆容、加上动物耳朵的AR滤镜,都依赖于实时、高精度的人脸地标点检测来确定五官的位置。
- 人脸识别与对齐: 在进行人脸比对之前,系统会先用地标点检测来对人脸进行“对齐”,即将人脸旋转、缩放,使得眼睛、鼻子等都处于标准位置,这可以极大地提升后续识别的准确率。
- 情绪识别: 通过分析嘴巴、眉毛等地标点的相对位置和形状变化,可以判断出人物的表情是喜、是怒、还是哀。
- 虚拟试穿/试妆: 让你在线“试戴”眼镜或“试用”口红的应用,也是基于地标点检测技术。
3.3. 目标检测
3.3.1. 概述
目标检测的核心任务是为每一个物体画上边界框,并进行分类。图片中物体的数量是未知的。这正是它与“目标定位”任务最根本的区别。
面对“数量未知”这一挑战,解决的方案是选取不同的感兴趣区域(RoI),然后使用CNN对每个区域内是否存在物体进行分类。
- 赛场: PASCAL VOC,这是在ImageNet之外,另一个衡量目标检测算法水平的权威“考场”。
- 评价指标: mAP (mean Average Precision),即“平均精度均值”。
- 补充知识: mAP是目标检测领域最核心的评价指标。它综合考虑了模型预测的“精确率”(Precision,你预测是苹果的框里,有多少真的是苹果?)和“召回率”(Recall,所有的真苹果里,你找到了多少个?),是一个能够全面衡量模型性能的数值,越高越好。
- 历史的分割线:
- 深度学习之前 (Before deep convnets): 在2012年之前,大约5年的时间里,目标检测的性能提升非常缓慢,mAP值从20%多艰难地爬升到40%左右。这个时代依赖的是HOG、SIFT等手动设计的特征。
- 深度学习之后 (Using deep convnets): 从2013年(AlexNet在分类任务上大获全胜的第二年)开始,以R-CNN为代表的深度学习方法被引入目标检测。性能曲线瞬间“起飞”,在不到2年的时间里,mAP值就从40%飙升到了70%以上。
![[Pasted image 20251002211740.png]]
- 目标检测是一个比分类更复杂、更实用的任务。
- 以R-CNN为代表的“候选区域+CNN分类”方法,是深度学习解决目标检测问题的开创性思路。
- 深度学习的引入,使得目标检测的性能发生了历史性的、断崖式的飞跃,其影响力丝毫不亚于它在图像分类领域掀起的革命。
3.3.2. 滑动窗口检测
这个方法巧妙地将一个复杂的目标检测问题,转化为了一个我们已经非常熟悉的图像分类问题。整个过程分为两步:训练和检测。
- 第一步:训练一个“方块分类器”
- 首先,用裁剪好的图片创建一个带标签的训练集。
- 准备数据: 我们需要收集大量的、尺寸统一的小图片块。
- 打标签: 为每一张小图片打上标签
y。如果图片里是我们想检测的物体(比如汽车),标签就是1;如果不是(比如是花朵、湖水或者单纯的背景),标签就是0。 - 训练模型: 用这个准备好的数据集,训练一个标准的卷积神经网络(ConvNet)。
- 训练结果: 经过这一步,我们就得到了一个专门的“方块分类器”。它的唯一功能就是判断任何一个输入给它的小方块图片“是车”还是“不是车”。
- 第二步:用“滑动窗口”进行检测
在拥有了一个训练好的“方块分类器”之后,我们就可以在一张全新的、大的图片上进行目标检测了。方法就是进行地毯式搜索:
- 具体流程:
- 选择一个窗口尺寸: 首先,我们选定一个窗口的大小,比如 64×64 像素。
- 滑动: 将这个窗口放在大图片的左上角,把窗口内的图像“抠”出来。
- 分类: 将“抠”出来的图像块送入我们第一步训练好的“方块分类器”进行判断。
- 重复: 将窗口向右移动一小段距离(这个距离叫“步长”或“stride”),然后重复“抠图-分类”的过程。当这一行滑到头后,就向下移动一个步长,从左到右继续滑动。
- 多尺度: 为了检测图中不同大小的汽车(近大远小),在用完 64×64 的窗口扫描完整张图片后,我们还需要换一个更大或更小的窗口尺寸(比如 96×96),然后把整个滑动扫描的过程再完整地重复一遍。
这种方法虽然思路简单,但PPT也明确指出了它的两个致命弱点:
- 巨大的计算成本。
- 在一张高清图片上,用多种不同的窗口尺寸、并且以很小的步长(比如每次只移动4个像素)进行扫描,需要进行分类的“方块”数量将达到数十万甚至上百万个。让一个强大的CNN模型重复运行这么多次,其时间成本是无法接受的,完全不能用于视频等实时场景。
- 速度与性能的矛盾
- 过大的步长可以降低计算成本,但会损害性。
- 这是一个无法调和的矛盾。为了加快速度,我们可以增大步长,比如每次让窗口跳32个像素。但如果一辆车恰好就位于两次“跳跃”的中间位置,那么窗口就可能完美地“跨过”了这辆车,导致漏检。
滑动窗口是一种简单粗暴但逻辑清晰的目标检测方法。它的核心思想是将检测问题转化为在大量候选位置上的分类问题。然而,它最大的问题在于候选位置的生成方式过于“盲目”和“浪费”,导致了极高的计算冗余。
根据以上问题,我们有一个优化的技巧:将全连接层转换为卷积层。
一个全连接层和一个特定参数的卷积层在数学上是等价的。
![[Pasted image 20251002212300.png]]
- 转换规则1: 如果一个全连接层的前一层是一个 $H×W×D$ 的特征图,那么这个全连接层就可以等效为一个滤波器尺寸恰好为 $H×W$ 的卷积层。例如,上图中,
MAX POOL之后是一个 $5×5×16$ 的特征图。连接其后的第一个FC层(有400个神经元)就可以被一个拥有400个尺寸为 $5×5×16$ 的滤波器所取代。这个卷积操作的输出尺寸将是 $1×1×400$。 - 转换规则2: 如果一个全连接层的前一层是一个 $1×1×K$ 的特征图(本质上就是一个向量),那么这个全连接层可以等效为一个滤波器尺寸为 $1×1$ 的卷积层。
通过这个转换,原本用于分类单个小图片块的、包含“卷积+全连接”的混合网络,就变成了一个从头到尾只包含卷积层的“全卷积网络”。
假设本来我们要在一个 $16×16$ 的大图上,用一个 $14×14$ 的窗口进行滑动检测(步长为2)。我们需要分别对左上、右上、左下、右下四个位置的 $14×14$ 图像块,独立地运行4次我们的分类网络。这其中有大量的重叠区域被重复计算,非常浪费。
将网络转换为FCN后:
- 我们不再抠图,而是将整个 16×16 的大图,一次性地输入到我们转换好的全卷积网络中。
- 数据在FCN中传播,特征图的尺寸逐层变化:
16x16x3->12x12x16->6x6x16->2x2x400...。 - 最终,我们得到的输出不是一个单一的分类结果,而是一个 2×2×400 的特征图。
- 这个 2×2 的输出图,就是我们的结果。它的每一个“像素”,都精确地对应了传统方法中一个滑动窗口位置的分类结果。
- 输出图左上角的 (1,1) 位置的向量,就是传统方法在输入图左上角进行分类的结果。
- 输出图右下角的 (2,2) 位置的向量,就是传统方法在输入图右下角进行分类的结果。
将输入图像4个子集上的4次传播,合并成了一次卷积计算,可以提升效率。这种效率提升的根本原因在于计算共享。在传统方法中,四个重叠的窗口区域的特征会被重复计算4次。而在全卷积网络的方法中,整张大图的特征只被计算了一次,这些被共享的特征在网络的深层自然地产生了对应不同窗口位置的输出。
这个将全连接层转化为卷积层的思想,是深度学习在目标检测领域的一个根本性突破。它不仅使得滑动窗口方法的效率得到了指数级的提升,也为后来的Faster R-CNN中的区域提议网络(RPN)和用于语义分割的FCN架构奠定了核心基础。
3.3.2.1. 例子
![[Pasted image 20251002213021.png]]
首先在上方定义了一个“玩具版”的全卷积网络(FCN)架构,这个网络是由一个普通的分类器转换而来的。我们来看一下它的数据流:
- 输入: 一张
28x28x3的图片。 - 第一层 (卷积): 经过
5x5卷积,输出一个24x24x16的特征图。 - 第二层 (池化): 经过
2x2的最大池化,输出一个12x12x16的特征图。 - 第三、四、五层 (卷积,原为FC层): 经过三层由全连接层转换而来的卷积(
5x5,1x1,1x1),最终输出一个8x8x4的特征图。
请注意,最终的输出不是一个单一的预测值,而是一个 8x8 的网格,每个网格点上都有一个包含4个值的向量(代表4个类别的得分)。
这等同于在 28x28 的图像上,用 14x14 的窗口、以2为步长进行滑动。
- 感受野等价于窗口尺寸:
- 为什么是
14x14的窗口?它是由网络结构反推出来的。它代表了最终输出的8x8特征图上的任何一个点,其计算所能“看到”的原始输入图像区域的大小。这个“视野范围”就是该点的感受野。这个FCN的结构,恰好使得其输出层单个点的感受野大小为14x14像素。
- 为什么是
- 输出图尺寸等价于窗口滑动次数:
- 为什么步长是2?这通常是由网络中的池化层(或其他带步长的卷积层)决定的。在这个例子中,
2x2的池化层将尺寸减半,使得网络整体的步长为2。
- 为什么步长是2?这通常是由网络中的池化层(或其他带步长的卷积层)决定的。在这个例子中,
- 我们将
28x28的大图一次性输入FCN。 - 我们得到了一个
8x8x4的输出图。 - 这个
8x8的网格,正好对应了传统滑动窗口方法需要滑动的64个位置。 - 输出图中每一个
(x, y)位置上的那个4维向量,就精确地代表了传统方法在对应(x, y)位置的14x14窗口上进行分类后得到的4个类别分数。
它通过一次前向传播,就并行地、共享地完成了传统方法需要64次独立传播才能完成的计算量。这种计算共享的思想,是现代高效目标检测和分割网络能够实现实时性能的基石。
3.3.3. R-CNN
![[Pasted image 20251002215602.png]]
R-CNN的核心思想非常巧妙,它将“大海捞针”式的目标检测问题,分解为了一个更智能、更高效的策略:
- 步骤一:提议候选区域
- 不再像滑动窗口那样盲目地扫描图像的每一个角落,而是先用一个快速的算法,在图像中找出上千个可能包含物体的候选区域。
- 步骤二:分类候选区域
- 然后,再动用强大的CNN模型,对这上千个候选区域逐一进行特征提取和分类,判断每个区域里到底是什么物体,或者是不是背景。
具体执行过程:
- 1. 输入图像:
- 我们从一张待检测的图片开始,比如图中一个骑在马背上的人。
- 2. 提取候选区域:
- R-CNN采用了一个名为“选择性搜索”的传统计算机视觉算法。
- 这个算法与学习无关,它根据图像的颜色、纹理、边缘等底层信息,通过层层合并相似的像素区域,最终能够生成大约2000个高质量的、尺寸各异的候选框(Region Proposals)。
- 3. 计算CNN特征:
- 这是最关键,也是计算成本最高的一步。
- 模型会遍历这2000个候选框,将每一个框内的图像裁剪下来,然后强制缩放/扭曲成CNN所要求的固定输入尺寸(比如AlexNet需要的 227×227 像素)。
- 接着,将这2000个被缩放后的图像块,逐一地送入一个强大的CNN(如AlexNet)中进行前向传播,为每一个候选框都提取出一个高维的特征向量(比如一个4096维的向量)。
- 4. 分类区域:
- 最后,用一组分类器(在原始论文中是多个支持向量机SVM)对上一步提取出的2000个特征向量进行分类,判断每个候选框是“人”、“马”、“电视”,还是“背景”。
尽管R-CNN的思路非常出色,并且在当年的检测精度上取得了巨大突破,但它的实现方式却存在一个致命的缺陷——速度极慢。
- 对于一个包含1000张图片的训练集,在训练中需要进行200万次前向传播。
- 计算: 1000 张图片×2000 个区域/图片=2,000,000 次CNN前向传播。
- 这意味着,仅仅是预测一张图片,就需要将一个庞大的CNN模型运行约2000次。这导致R-CNN处理一张图片需要几十秒的时间,完全无法用于实时应用。此外,它的训练过程也极其复杂,需要分步训练候选区域生成、CNN特征提取和SVM分类器,耗时耗力。
3.3.4. 非极大值抑制(Non-Max Suppression, NMS)
目标检测算法通常会针对同一个物体,生成多个重叠的边界框。因为无论是滑动窗口还是更先进的检测器,它们都会在物体周围的多个略有偏移的位置上都给出很高的“物体分数”。例如,一个窗口正好框住狗,得分98%;当窗口向右平移几个像素,大部分区域仍然是狗,得分可能依然高达90%。最终结果就是在一个真实的物体周围,簇拥着一堆“高分”的预测框。
![[Pasted image 20251002215717.png]]
显然,我们最终只想为每个物体保留一个最精确的边界框。NMS就是完成这个任务的算法。NMS算法会选择得分最高的那个“最佳”边界框,并抑制(抛弃)掉所有其他与之高度重叠的框。
非极大值抑制可以分为以下几步:
- 输入: 针对某一个类别(比如“Person”),我们得到所有的预测框列表,以及它们各自的置信度分数。
- 排序: 将这个列表中的所有框,按照置信度分数从高到低进行排序。
- 选取最佳: 选出列表中分数最高的那个框(我们称之为“Max-Box”),将它作为最终的检测结果之一保留下来。
- 计算重叠: 计算这个“Max-Box”与列表中所有其他框的重叠程度。
- 这个重叠程度通常用一个叫做“交并比(Intersection over Union, IoU)”的指标来衡量。它的计算公式是:$\text{IoU} = \frac{\text{两个框交集的面积}}{\text{两个框并集的面积}}$IoU的值域在0到1之间,0代表完全不重叠,1代表完全重合。
- 抑制(Suppress): 找出列表中所有与“Max-Box”的IoU值超过某个阈值(比如0.5)的框。这些框被认为是重复的检测,将它们从列表中删除。
- 迭代: 回到被筛选后的列表,重复步骤3-5,即在剩下的框里找到分数最高的,保留它,然后删除与它高度重叠的框。
- 结束: 当列表为空时,算法结束。所有在步骤3中被保留下来的框,就是最终干净的检测结果。
NMS是一个简单、高效且不可或缺的后处理算法。它确保了目标检测的最终输出是简洁有效的,即每一个物体只对应一个最准确的边界框。
3.3.5. 目标检测性能评估
目标检测领域最重要的三个评价指标:IoU、AP 和 mAP。
- 基础指标:交并比 (Intersection over Union, IoU)
- 目的: IoU是衡量单个预测框与真实框之间重合度的标准。它回答了一个最基本的问题:“我这个框画得到底准不准?”
- 公式:$IoU=\frac{\text{Area of Overlap}}{\text{Area of Union}}$即 两个框交集的面积 除以 两个框并集的面积。
- IoU是一个介于0和1之间的值。
- 如果两个框完全没有重叠,IoU = 0。
- 如果两个框完美重合,IoU = 1。
- IoU值越高,代表预测框的位置越准确。
- 作用: 在评估时,我们会设定一个IoU阈值(比如0.5)。如果一个预测框与真实框的IoU大于0.5,我们就认为这是一个成功的检测;否则,就是一个失败的检测。这是计算更高级指标AP的基础。
- 单类指标:平均精度 (Average Precision, AP)
- 目的: AP衡量的是模型在某一个特定类别(比如“汽车”)上的综合性能。
- 精确率 (Precision): 回答“你预测为‘汽车’的框里,有多少真的是‘汽车’?”。即
Precision = 真正例 / (真正例 + 假正例)。高精确率代表“不误报”。 - 召回率 (Recall): 回答“所有真实的‘汽车’里,你找到了多少辆?”。即
Recall = 真正例 / (真正例 + 假反例)。高召回率代表“不漏报”。 - P-R曲线: 精确率和召回率通常是相互制衡的。如果我们只保留置信度非常高的预测框,精确率会很高,但可能会漏掉一些置信度稍低的真实例子,导致召回率下降。通过不断改变置信度阈值,我们可以得到一系列的(Recall, Precision)点对,将它们画出来就是P-R曲线。
- AP的含义: 平均精度(AP)就是这条P-R曲线下方的面积。一个完美的模型,其P-R曲线会一直保持在顶部,AP值会接近1(或100%)。AP是一个能够综合评价模型在单个类别上“既不误报又不漏报”能力的黄金指标。
- 精确率 (Precision): 回答“你预测为‘汽车’的框里,有多少真的是‘汽车’?”。即
![[Pasted image 20251002220239.png]]
- 总体指标:平均精度均值 (mean Average Precision, mAP)
- 目的: mAP是衡量整个模型在所有类别上的平均性能,是目标检测领域最常用、最重要的最终评价指标。
- 计算过程非常简单:假设一个数据集有20个类别(比如PASCAL VOC数据集)。我们先独立计算出模型在“汽车”类别上的AP,在“行人”类别上的AP,在“狗”类别上的AP……一直到计算完所有20个类别的AP。
- 然后,将这20个AP值求一个简单的算术平均数,得到的结果就是mAP。
- 深度学习方法将目标检测性能从40%提升到70%以上,这个数值指的就是mAP。
- IoU: 评估一个框的质量。
- AP: 综合评估一个类别的检测质量。
- mAP: 综合评估整个模型在所有类别上的检测质量。
3.3.6. Fast R-CNN
Fast R-CNN是为了解决R-CNN速度太慢的缺点产生的。
Fast R-CNN的实现“快”的诀窍,源于一个思想转变:
R-CNN的“慢”法: 对一张图片,先找出2000个候选区域(RoI),然后将这2000个区域逐一送入CNN中提取特征。这意味着,一个庞大的CNN模型要重复运行2000次,其中大量的重叠区域被反复计算,极其浪费。
- Fast R-CNN的“快”法:
- 一次性提取特征: 不再对小图片块进行操作,而是将整张输入图片,只通过一次卷积网络(如VGG16),生成一个全图的“卷积特征图”。
- 沿用候选区域: 候选区域的生成方法不变,仍然使用像Selective Search这样的外部算法,在原始图片上生成约2000个RoI。
- 在特征图上定位区域: 最关键的一步,将在原始图片上的RoI坐标,映射到第一步生成的卷积特征图上,直接在特征图上“裁剪”出对应的特征区域。
这个“计算共享”的思路,避免了上千次的重复卷积运算,是Fast R-CNN实现速度飞跃的根本原因。
![[Pasted image 20251002222622.png]]
将原始RoI映射到特征图上的计算方法:
首先,我们需要知道CNN对图片尺寸的压缩比例。例子里,输入图片尺寸是 512x512,经过VGG16网络后,输出的特征图尺寸是 16x16。因此,下采样率为: $$\mathrm{Ratio}=\frac{\mathrm{Input~Size}}{\text{Feature Map Size}}=\frac{512}{16}=32$$ 我们只需要将原始RoI的坐标直接除以这个下采样率,就能得到它在特征图上的对应位置。
- 一个在原图上宽度为
200像素的框,在特征图上对应的宽度就是200 / 32 = 6.25。 - 一个在原图上高度为
145像素的框,在特征图上对应的高度就是145 / 32 = 4.53。
经过上一步,我们得到了约2000个尺寸各不相同的特征区域(比如 6.25×…, 4.53×…)。但我们知道,CNN的最后的全连接层需要接收固定尺寸的输入。如何解决这个矛盾呢?
这正是Fast R-CNN的第二个核心创新,即引入了一个名为“RoI池化层”的结构。
- 工作原理:
- RoI池化层接收这些大小不一的特征区域。
- 它将每个区域强制分割成一个固定大小的网格(比如 7×7)。
- 然后,在每个网格单元内执行最大池化(Max Pooling)操作。
- 效果: 无论输入的特征区域原来是多大,经过RoI池化层处理后,输出的永远是一个尺寸固定(比如 7×7)的特征图。这个固定尺寸的输出就可以被顺利地送入后续的全连接层进行分类和边界框回归了。
Fast R-CNN通过两大创新,极大地优化了R-CNN:
- 共享卷积计算: 将CNN对整张图只运行一次,避免了大量重复计算。
- RoI池化: 巧妙地解决了不同尺寸候选区域如何输入到全连接层的问题。
这些改进带来的效果是惊人的。在处理速度上,Fast R-CNN比R-CNN快了上百倍,训练速度也快了近10倍,同时精度还有小幅提升。
然而,Fast R-CNN并非完美。它的速度瓶颈转移到了候选区域的生成上,因为Selective Search算法本身仍然很慢,且在CPU上运行。
3.3.7. Faster R-CNN
Fast R-CNN通过“共享卷积计算”,极大地提升了检测速度。但它的整体速度,仍然受限于那个独立于神经网络之外、在CPU上缓慢运行的候选区域生成算法(如Selective Search)。整个系统不是一个端到端的整体。
Faster R-CNN的解决方案极具革命性,它引入一个名为“区域提议网络”(Region Proposal Network, RPN)的全新组件,用它来取代外部的候选区域生成算法。
![[Pasted image 20251002223052.png]]
RPN本身就是一个小型的、全卷积的神经网络。图中紫色虚线框内的图展示了它的工作原理:
- 共享特征: RPN不再在原始图像上工作,而是直接接收主干网络(如VGG)生成的深度卷积特征图。这使得它几乎是“零成本”的,因为它复用了已有的计算结果。
- 滑动窗口与锚点 (Anchors): RPN在特征图上进行滑动窗口操作(比如用一个
3x3的窗口)。- 在每个滑动窗口的中心点,RPN引入了一个至关重要的概念,锚点。它会预设
k个(例如图中的9x,代表9个)不同尺寸、不同长宽比的“参考框”。
- 在每个滑动窗口的中心点,RPN引入了一个至关重要的概念,锚点。它会预设
- 双重预测: 对于每一个锚点,RPN都有两个并行的输出“头”:
- 分类头: 一个二元分类器,用来判断这个锚点框住的区域是前景(有物体)还是背景。
- 回归头: 一个回归器,用来预测这个锚点框相对于真实物体位置的精细偏移(
dx, dy, dw, dh),从而得到一个更精确的候选框。
通过这种方式,RPN能够高效地在特征图上“撒网”,快速地生成高质量的候选区域。
Faster R-CNN将RPN和Fast R-CNN完美地融合在了一个端到端的统一网络框架中。整个流程如下:
- 特征提取: 输入图片经过一次主干网络(如VGG),生成一个共享的特征图。
- 区域提议: 这个特征图被同时送入RPN,RPN输出一系列候选区域(RoIs)。
- 区域池化: RoI池化层接收同一个特征图和RPN生成的RoIs,为每个RoI提取出固定大小的特征。
- 最终分类与回归: 这些固定大小的特征被送入最终的分类和回归头,得出每个RoI的精确类别和边界框位置。
这个统一的网络可以通过一个包含四部分损失的多任务损失函数进行端到端的训练:
- RPN的分类损失(前景/背景,使用交叉熵损失)
- RPN的回归损失(锚点框精调)
- 最终检测头的分类损失(具体物体类别,使用交叉熵损失)
- 最终检测头的回归损失(边界框精调,使用L1损失)
通过联合优化这四个损失,RPN和检测网络可以协同工作,互相促进。它首次将候选区域的生成这一关键步骤也纳入了深度学习的框架,用一个轻量、高效的RPN代替了缓慢的传统算法。这使得整个目标检测系统,从输入到输出,完全由一个单一的、统一的神经网络构成,可以进行端到端的训练。
3.3.8. 检测模型分类
3.3.8.1. 双阶段检测器 (Two-stage Object Detector)
这是一种将检测过程分为两个独立阶段的方法。
- 第一阶段 (Stage 1): 输出候选区域。这一阶段不关心物体具体是什么,只负责快速地找出图片中哪些区域可能包含物体,进行一个简单的“前景 vs 背景”的二元分类。Faster R-CNN中的区域提议网络就是第一阶段的典型代表。
- 第二阶段 (Stage 2): 对第一阶段提出的每个候选区域进行精确的分类,判断这个区域里具体是哪个类别。
代表模型: R-CNN、Fast R-CNN、Faster R-CNN 及其各种变体。
3.3.8.2. 单阶段检测器 (Single shot detector, SSD)
单阶段检测器(如SSD, YOLO, RetinaNet)在一个单一的流程中,直接输出图片中存在的物体类别以及它们对应的边界框坐标。它没有独立的候选区域提议阶段,而是将定位和分类任务在一个统一的网络中同时完成。
代表模型: YOLO(You Only Look Once)、SSD(Single Shot MultiBox Detector)、RetinaNet。
两个流派最核心的区别和权衡:
- 单阶段检测器:
- 优势: 结构简单,没有复杂的流水线,因此速度极快。
- 适用场景: 非常适合实时应用,例如自动驾驶、视频监控等对延迟要求极高的场景。
- 劣势 (早期): 在早期的发展中,由于需要处理大量背景候选框,导致正负样本极不均衡,其精度通常略低于双阶段检测器。
- 双阶段检测器:
- 优势: 由于第一阶段已经过滤掉了大量简单的背景区域,第二阶段可以更专注于对少数高质量候选框进行精细的分类和定位,因此通常能达到更高的精度。
- 适用场景: 更适合那些对准确率要求极高,而对实时性要求相对宽松的应用。
- 劣势: 结构相对复杂,速度通常慢于单阶段检测器。
现代中,以 RetinaNet 为代表的单阶段检测器,通过引入“焦点损失(Focal Loss)”等技术,极大地改善了正负样本不均衡的问题,使得单阶段模型的精度首次能够媲美甚至超越双阶段模型。
后续的YOLO系列(如YOLOv3, v4, v5...)也在不断地融合各种技术,在保持极高速度的同时,精度也得到了大幅提升。
3.3.9. YOLO
YOLO的思路与R-CNN系列完全不同。它不做“区域提议”,而是将目标检测视为一个单一的、端到端的回归问题。它的核心思想可以概括为两点:
- 划分网格 (Partition the image into SxS grid):
- YOLO首先将输入的图像粗暴地划分成一个
S x S的网格(比如3x3,或在实际应用中更常见的7x7、19x19)。
- YOLO首先将输入的图像粗暴地划分成一个
- 网格单元负责制 (Each object will be assigned to just one grid cell):
- 每一个物体,都由其中心点所在的那个网格单元来全权负责检测。
- 例如,橙色汽车的中心点落在了最中间的那个格子里,所以只有中间这个格子需要预测出这辆车。
YOLO的整个网络只会进行一次前向传播,然后直接输出一个巨大的三维张量(Tensor),这个张量就编码了所有检测信息。
![[Pasted image 20251002224029.png]]
- 输出尺寸: 例子是
3x3x8。3x3:代表了图像上的9个网格单元。8:代表每个网格单元需要预测的一个包含8个元素的向量。
- 单个网格的预测向量
y:] $$y=[p_c,b_x,b_y,b_h,b_w,c_1,c_2,c_3]$$ - $p_c$: 物体置信度。它代表这个网格内部存在一个物体中心点的概率。
- $(b_x,b_y,b_h,b_w)$: 边界框的4个坐标值。
- $(c_1,c_2,c_3)$: 类别概率。在 $p_c$ 很高(即确定有物体)的前提下,这个物体分别是类别1、类别2、类别3的概率。
- $b_x,b_y$: 这两个值代表物体中心点相对于其所在网格单元左上角的偏移量。PPT指出它们的值在
(0, 1)之间。这使得网络学习更容易,因为它只需要预测一个微小的偏移,而不是绝对坐标。 - $b_h,b_w$: 这两个值代表边界框的高度和宽度,是相对于整张图片尺寸的比例。因此它们的值可能大于1(比如一个横跨多个网格的大物体)。
YOLOv2及后续版本中,为了更好地适应不同形状的物体,每个网格单元实际上会预测B个(比如2或3个)边界框,并最终选用最好一个。这解决了原始YOLO一个格子只能检测一个物体的问题。
3.3.10. RetinaNet
- 在YOLO这样的模型中,一张图几百上千个网格单元,但通常只有几个里面有物体。这意味着绝大多数的单元格都是背景(负样本),只有极少数是前景(正样本)。
- 这种严重的正负样本不均衡,会导致模型在训练时被大量简单的“背景”样本所淹没,难以充分学习如何检测真正的物体。
- RetinaNet为此设计了一种全新的损失函数——焦点损失(Focal Loss)。Focal Loss是一种经过动态加权的交叉熵损失,它的核心思想是:降低大量简单、易分类样本(比如背景)在损失计算中的权重,让模型在训练时更专注于那些困难的、易错分的样本(比如前景物体)。
- 这个巧妙的设计,使得单阶段检测器在精度上首次超越了当时最先进的双阶段检测器(如Faster R-CNN),同时还保持了极高的速度。
3.4. 语义分割
3.4.1. 概念
图像分割的任务是为图像中的每一个像素点分配一个类别标签。它的终极目标是实现彻底的场景理解。它输出的不是一个粗略的矩形框,而是一个与原图等大的、像素级别的“掩码”图。
一个非常典型的应用是检测可行驶区域。对于自动驾驶汽车来说,仅仅知道“前方有路”是远远不够的,它必须精确地知道道路的每一个边缘在哪里,才能安全地行驶。
![[Pasted image 20251002225315.png]]
图像分割的三种主要类型,它们的精细程度和目标各不相同:
(b) 语义分割 (Semantic Segmentation)
- 任务: 回答“这个像素属于哪个类别?”
- 特点: 它只关心像素的类别,不区分个体。它不区分同一物体的不同实例。
- 所有的“汽车”都被涂成了同一种蓝色,所有的“行人”都被涂成了同一种粉色。模型并不知道这里有三辆不同的车,它只知道这些像素都属于“车”这个类别。
(c) 实例分割
- 任务: 回答“这个像素属于哪个物体实例?”
- 特点: 它需要找到并分割出场景中的每一个独立的物体。
- 在图(c)中,每一辆车、每一个行人都被赋予了一个独立的、颜色不同的掩码。模型清晰地识别出了“汽车1号”、“汽车2号”、“行人1号”等不同的个体。
- 实例分割可以被看作是目标检测和语义分割的结合体。一个典型的实例分割模型需要先像目标检测器一样,找到每个物体的位置(边界框),然后再对每个框内的物体进行像素级的分割。
(d) 全景分割 (Panoptic Segmentation)
- 统一语义分割和实例分割,为图中每一个像素同时分配类别标签和实例ID。
- 特点: 这是最全面、信息最丰富的分割任务,旨在提供一个完整无缝的场景解析。
- 图(d)看起来像是图(b)的“精细版”。它像语义分割一样,为所有像素(包括背景里的天空、树木)都上了色;同时,它又像实例分割一样,为每一个独立的对象(每辆车、每个人)都赋予了唯一的标识(比如用不同深浅的蓝色来区分不同的车)。
图像分割代表了计算机视觉对场景理解的最高层次。从只关心类别的语义分割,到区分个体的实例分割,再到最终统一两者的全景分割,这些技术让机器能够以像素级的精度来解析和理解我们周围的世界,为自动驾驶、医疗诊断、机器人技术等前沿领域提供了核心的技术支撑。
3.4.2. 编码器-解码器结构
编码器-解码器结构的核心思想非常符合直觉,它将分割任务分成了两个阶段:
- 编码 (Encoding): 先将输入的图片不断地压缩、提炼,让网络“理解”图片中包含了什么物体、形状和大小。
- 解码 (Decoding): 再将这个高度浓缩的、低分辨率的“理解”,一步步地“画”出来,生成高分辨率的分割图。
![[Pasted image 20251002225541.png]]
编码器 (Encoder)
- 结构: 编码器部分是左半边,即收缩路径。它通常由一系列的卷积层和最大池化(Max Pool)层组成。
- 功能: 它的工作模式和我们之前学习的图像分类网络(如VGG)的主干部分完全一样。在每一阶段,它通过卷积提取特征,然后通过池化将特征图的尺寸减半。这个过程不断重复,使得特征图的空间尺寸越来越小,但通道数(代表特征的丰富度)越来越多。
- 目的: 编码器的目标是捕捉图像的上下文信息和高级语义。经过编码器处理后,网络知道了“这张图的中间偏下位置大概有一个类别为汽车的物体”,但由于尺寸被严重压缩,它已经丢失了这辆车精确的轮廓和边缘等细节信息。
解码器 (Decoder)
- 结构: 解码器是“右半边,即扩张路径。它由一系列的上采样层和卷积层组成。
- 功能: 它的工作模式与编码器正好相反。在每一阶段,它通过上采样(比如转置卷积)将特征图的尺寸加倍,同时通过卷积减少通道数,逐步地将低分辨率的语义特征图,恢复到和原始输入图像一样大的尺寸。
- 目标: 解码器的目标是将编码器“理解”到的语义信息,重新定位到像素级别,恢复丢失的空间信息(特别是物体边界)。
如果仅仅是先编码再解码,效果并不会好。因为编码器在深层提取的高级语义特征虽然“懂得多”,但位置信息“太模糊”了。解码器仅凭这些模糊信息,很难画出清晰的物体轮廓。
U-Net的真正革命性创新,在于它引入了“跳跃连接”来解决这个问题。
- 定义: 将编码器在不同阶段的中间输出,直接“跳跃”到解码器中相对应的阶段,并与解码器的输入进行拼接或相加。
- 图中那些横跨“U”形两臂的灰色箭头,就是跳跃连接。
- 编码器浅层的特征图(比如“U”形最上方),分辨率很高,虽然语义信息不足(只知道一些边缘和纹理),但空间位置信息非常精确。
- 解码器深层的特征图(比如“U”形最下方),经过上采样后,语义信息很丰富(知道这里是“车”),但空间位置信息很模糊。
- 跳跃连接的作用,就是将编码器中包含“精确定位信息”的浅层特征,直接“喂”给解码器中包含“丰富语义信息”的对应层。
- 通过这种方式,解码器的每一层都同时获得了“是什么”(高级语义)和“在哪里”(低级细节)两种信息,从而能够生成既有正确类别、又有清晰边界的分割图。
U-Net的编码器-解码器结构,特别是其标志性的跳跃连接,完美地结合了深度网络中的高级语义特征和浅层网络中的低级空间细节特征。这种设计思想非常高效和强大,使得U-Net不仅在医学影像分割领域取得了巨大成功,也成为了后续无数分割网络乃至其他像素级预测任务(如图像去噪、图像生成)的经典范本。
3.4.3. U-Net
U-Net的名字来源于其标志性的U形网络结构,这个结构由一个“收缩路径”和一个“扩张路径”对称地组成。
编码器 (Encoder) - U形的左侧“收缩路径”
- 目标: 捕捉图像的上下文(context)信息,即“这张图里有什么”。
- 流程: “减小特征图尺寸,增加通道数”
- 具体操作: 这一路径由重复的模块构成,每个模块包含:
- 两个连续的
3x3卷积层(conv 3x3, ReLU)。 - 一个
2x2的最大池化层(max pool 2x2),负责将特征图的长宽减半。
- 两个连续的
- 图中每次卷积后,特征图的尺寸都会减小2个像素(例如从
572x572变为570x570)。这是因为原始的U-Net论文中使用的是无填充卷积。这种设计会导致输出的分割图比输入的图像要小。在现代的很多U-Net实现中,为了方便,通常会使用“same”填充来保持尺寸不变。
解码器 (Decoder) - U形的右侧“扩张路径”
- 目标: 实现精确定位,即“物体精确的边界在哪里”。
- 流程: “增加特征图尺寸,减少通道数”。
- 具体操作: 这一路径也由重复的模块构成,每个模块包含:
- 一个
2x2的上卷积(up-conv 2x2),它是一种上采样操作(如转置卷积),负责将特征图的长宽加倍。 - 与编码器对应层的特征图进行拼接(即跳跃连接)。
- 两个连续的
3x3卷积层(conv 3x3, ReLU)。
- 一个
“跳跃连接” (Skip Connections)
U-Net最核心、最具创新性的设计就是连接编码器和解码器的“跳跃连接”。
- 图中那些横向的、灰色的、标有“Copied feature maps”的箭头就是跳跃连接。
- 问题: 编码器在底层提取的特征虽然语义信息丰富(知道“这是个细胞”),但经过多次池化后,其空间位置信息已经非常模糊。解码器仅凭这些模糊信息,很难画出细胞清晰的边缘。
- 解决方案: U-Net将编码器路径中、池化之前的那些高分辨率特征图,“复制”一份,直接“跳跃”到解码器路径中,与解码器上采样后的特征图进行拼接。
- 效果: 这样一来,解码器的每一层都同时拥有了两种信息:来自网络深层的高级语义信息(知道是什么)和直接来自编码器浅层的高分辨率细节信息(知道精确的边缘在哪里)。这使得U-Net能够生成极其精细和准确的分割图。
- 图例中提到了“copy and crop”(复制和裁剪)。这里的“裁剪”是因为前面提到的无填充卷积。由于编码器路径的特征图比解码器路径的略大,所以在拼接前需要先将编码器的特征图裁剪一下,使它们的尺寸完全匹配。
![[Pasted image 20251002230054.png]]