查看全课大纲(第 35 / 93 节)
  1. 1.计算机视觉概述
  2. 2.计算机视觉应用场景
  3. 3.困难与挑战
  4. 4.开源库介绍
  5. 5.图像显示与存储
  6. 6.CLAHE
  7. 7.腐蚀膨胀与开闭运算
  8. 8.滤波与边缘填充
  9. 9.各种滤波
  10. 10.图像金字塔
  11. 11.傅里叶变换
  12. 12.短时傅里叶变换与小波变换
  13. 13.颜色特征与颜色直方图
  14. 14.几何特征_边缘
  15. 15.几何特征-角点与斑点
  16. 16.局部特征-SIFT特征描述子
  17. 17.局部特征-SURF特征描述子
  18. 18.局部特征-ORB特征描述子
  19. 19.其他特征描述子
  20. 20.传统图像分割技术
  21. 21.GraphCut
  22. 22.GrabCut
  23. 23.人脸检测的传统方法
  24. 24.行人检测的传统方法HOG+SVM
  25. 25.行人检测DPM
  26. 26.人工神经网络的架构
  27. 27.目标函数与梯度下降
  28. 28.误差反向传播
  29. 29.可手算的神经网络
  30. 30.改进目标函数与克服梯度消散
  31. 31.神经网络之传统神经网络与深度网络的差异
  32. 32.各种梯度下降算法
  33. 33.如何选择合适的梯度下降算法
  34. 34.避免过适应
  35. 35.CNN的架构
  36. 36.CNN的误差反向传播_卷积层
  37. 37.CNN的误差反向传播_池化层
  38. 38.分类所用的数据集
  39. 39.Alexnet详解
  40. 40.VGG详解
  41. 41.GoogLeNet_v1
  42. 42.BatchNormalization
  43. 43.GoogLeNet_v3v4
  44. 44.ResNet
  45. 45.ResNeXt
  46. 46.CNN设计准则
  47. 47.图像检索与推土机距离
  48. 48.基于颜色相似性
  49. 49.基于形状相似性
  50. 50.基于纹理相似性
  51. 51.基于局部特征相似性
  52. 52.DL的二值哈希编码
  53. 53.高维空间中检索KDTree
  54. 54.高维空间中检索LSH
  55. 55.目标识别任务综述
  56. 56.RCNN
  57. 57.SPP-Net
  58. 58.Fast R-CNN
  59. 59.Faster R-CNN
  60. 60.R-CNN系列模型回顾
  61. 61.R-FCN的设计思路
  62. 62.R-FCN的实现
  63. 63.YOLOv1
  64. 64.YOLOv2_9000
  65. 65.YOLOv3
  66. 66.图像分割应用场景与数据集
  67. 67.上采样的实现方式
  68. 68.FCN网络架构的由来
  69. 69.FCN构建细节
  70. 70.DeepLabv1
  71. 71.CRF
  72. 72.DeepLabv2
  73. 73.DeepLabv3
  74. 74.特定的医学影像分割任务
  75. 75.U-Net
  76. 76.3D U-Net
  77. 77.V-Net
  78. 78.DenseNet
  79. 79.病理切片分析任务及数据集
  80. 80.病理切片分析
  81. 81.图说任务及其传统处理方法
  82. 82.深度语言模型与RNN
  83. 83.LSTM及其变种
  84. 84.NIC模型
  85. 85.SAT模型
  86. 86.图说的性能指标
  87. 87.判别模型与生成模型
  88. 88.KL散度与JS散度
  89. 89.VAE
  90. 90.GAN的基本原理
  91. 91.DCGAN与CGAN
  92. 92.Wasserstein GAN
  93. 93.SRGAN

CNN的架构

卷积神经网络的整体架构

小象实战讲义 · 基于深度学习的计算机视觉

在掌握了深度学习的基本概念和优化方法后,我们终于要进入计算机视觉的核心——卷积神经网络(CNN)。本节将为你系统拆解CNN的经典架构,从输入一张图片开始,一步步解析卷积层、激活函数、池化层和全连接层是如何协同工作,最终完成图像识别任务的。学完本节,你将能清晰地描述CNN的完整工作流程,并理解其核心组件的作用。

💡 核心导读

  • CNN的三大支柱:理解卷积层、池化层和全连接层在架构中的角色与分工。
  • 从3D张量到特征图:掌握图像作为多通道张量输入,以及卷积核如何通过滑动扫描提取局部特征。
  • 激活函数的进化:从Sigmoid到ReLU,理解非线性激活如何缓解梯度消失问题,成为深度网络优化的关键。
  • 降维与特征融合:剖析池化层(尤其是最大池化)如何在不增加参数的情况下实现降维和特征鲁棒性。
  • 从特征到决策:了解全连接层与Softmax层如何将高维特征映射为最终的分类概率。

卷积神经网络的基本组件

卷积神经网络(Convolutional Neural Network, CNN)是专门为处理图像这类网格状数据而设计的深度学习模型。其成功的关键在于它巧妙地利用了图像的空间局部性和平移等变性(再经池化获得一定的平移不变性)。一个典型的CNN由以下几个基本组件构成:

  1. 卷积层 (Convolutional Layer):这是CNN的核心。其作用是对原始图像或上一层输出的特征图进行卷积加工,以提取局部特征。卷积层内部包含需要学习的权重参数(即卷积核的值),并且通常紧随一个非线性激活函数。
  2. 激活函数 (Activation Function):为网络引入非线性,使其能够学习复杂的模式。早期常用Sigmoid函数,而现在最主流的是修正线性单元 (ReLU)。
  3. 池化层 (Pooling Layer):通常接在卷积层之后,用于降维和特征融合。最常用的是最大池化 (Max Pooling),在某些特定场景下也会使用平均池化 (Average Pooling)。
  4. 全连接层 (Fully-Connected Layer):在网络的末端,将经过多次卷积和池化后得到的二维特征图“展平”成一维向量,并进行全局的综合与判别。其层间神经元两两相连,结构与传统神经网络相同。

这些组件按照“卷积 -> 激活 -> 池化”的顺序反复堆叠,最后连接全连接层,构成了CNN的典型架构。例如,经典的AlexNet就包含了5个卷积层、数个池化层以及3个全连接层。

卷积层:特征提取的引擎

图像的张量表示

图像进入CNN时,本身就是一个三维张量(Tensor)。除了我们熟知的长和宽两个空间维度,还有一个通道(Channel) 维度。

  • 彩色图像:通常有3个通道,分别对应红(R)、绿(G)、蓝(B) 三原色。因此输入是一个 [高度, 宽度, 3] 的张量。
  • 灰度图像:只有1个通道,输入是 [高度, 宽度, 1] 的张量。

在使用TensorFlow或PyTorch等框架编程时,我们操作的就是这样的三维张量。

卷积操作详解

卷积层的核心操作是使用一个称为卷积核(Kernel) 或滤波器(Filter) 的小窗口,在输入张量上进行滑动扫描。

import numpy as np

# 模拟一个简单的3x3单通道输入图像
input_2d = np.array([[1, 2, 3],
                     [4, 5, 6],
                     [7, 8, 9]], dtype=np.float32)

# 定义一个2x2的卷积核
kernel = np.array([[1, 0],
                   [0, -1]], dtype=np.float32)

# 手动实现步长为1,无填充的卷积操作
output_height = input_2d.shape[0] - kernel.shape[0] + 1
output_width = input_2d.shape[1] - kernel.shape[1] + 1
output = np.zeros((output_height, output_width))

for i in range(output_height):
    for j in range(output_width):
        region = input_2d[i:i+kernel.shape[0], j:j+kernel.shape[1]]
        output[i, j] = np.sum(region * kernel) # 对应位置相乘后求和

print("输入图像:")
print(input_2d)
print("\n卷积核:")
print(kernel)
print("\n卷积输出(未加激活):")
print(output)
输入图像:
[[1. 2. 3.]
 [4. 5. 6.]
 [7. 8. 9.]]

卷积核:
[[ 1.  0.]
 [ 0. -1.]]

卷积输出(未加激活):
[[-4. -4.]
 [-4. -4.]]

关键概念解析:

  • 滑动扫描:卷积核以一定的步长(Stride) 在输入上移动。步长为1时每次移动1个像素;步长为2时每次移动2个像素,这会导致输出特征图尺寸缩小。
  • 多卷积核与输出通道:每一层卷积层都包含多个卷积核。每个卷积核独立地在输入上进行卷积操作,产生一个二维的特征图(Feature Map)。所有卷积核产生的特征图堆叠起来,就构成了该卷积层的输出,其通道数等于卷积核的数量。
    • 例如,若输入是 32x32x3 的图像,使用6个尺寸为 5x5x3 的卷积核进行卷积(步长1,无填充),将得到 28x28x6 的输出特征图。这里卷积核的第三个维度 3 必须与输入通道数一致。
  • 局部特征提取:每个卷积核本质上是一个特征检测器。例如,一个对角线为1的卷积核,会对图像中对角线模式明显的区域产生高响应(输出值大)。卷积核的具体模式(是检测边缘、角点还是纹理)不是人为设定的,而是在训练过程中通过误差反向传播自动学习得到的。
  • 权重共享:同一个卷积核在整个输入图像上滑动使用,其参数(权重)是共享的。这极大地减少了参数量,并赋予了模型平移等变性(输入平移,输出特征同步平移);再配合池化,才能获得一定的平移不变性。

感受野(Receptive Field)

卷积核每一次只“看”输入上的一个小窗口,但在多层堆叠之后,输出特征图上的一个点,实际上间接“看过”了原图上更大的一片区域——这片区域就是该点的感受野。

以连续两层 3x3 卷积(步长1、无填充)为例:第一层输出上的每个点对应原图 3x3 的区域;第二层再做一次 3x3 卷积时,它会覆盖第一层输出的 3x3 个点,而这 9 个点各自又对应原图的 3x3 区域,合起来第二层输出上的一个点就对应原图 5x5 的范围。层数越深,感受野越大,网络能捕捉的语义范围也就越广——这也是深层 CNN 能从边缘、纹理逐步抽象到物体部件乃至整体目标的原因。

反过来看,如果感受野已经覆盖了整张图,再继续堆叠卷积层,对扩大感知范围就没有额外收益了。因此设计网络时,感受野大小需要与目标任务中目标的空间尺度相匹配。

卷积层的超参数与尺寸计算

卷积层的输出尺寸由以下几个超参数共同决定:

  • 核尺寸(Kernel Size):如 3x3, 5x5,特殊的 1x1 卷积用于跨通道信息融合。
  • 步长(Stride):滑动步长。步长大于1具有降维作用。
  • 零填充(Zero Padding):在输入图像边缘补0,以控制输出尺寸,防止边缘信息丢失过快。
  • 核数量(Number of Kernels):决定输出特征图的通道数。

输出尺寸的计算公式如下(分别计算高度和宽度,公式相同): 输出尺寸 = (输入尺寸 - 核尺寸 + 2 × 填充) / 步长 + 1

例如,输入为 32x32,使用 5x5 卷积核,步长为1,无填充(padding=0): 输出尺寸 = (32 - 5 + 2*0) / 1 + 1 = 28

激活函数:引入非线性

卷积操作本质上是线性的加权求和。为了让网络能够拟合复杂的非线性函数,必须在卷积后施加非线性激活函数。

  • Sigmoid:早期常用的S型函数,将输入压缩到(0,1)之间。但它有两个主要缺点:
    1. 梯度消失:当输入值很大或很小时,其导数接近0,在深层网络中反向传播的梯度会急剧缩小,导致底层权重难以更新。
    2. 计算量较大:涉及指数运算。
  • ReLU (Rectified Linear Unit):当前最主流的激活函数。公式为 f(x) = max(0, x)。
    • 优点:
      1. 计算高效:只有比较和取0操作。
      2. 缓解梯度消失:在正区间导数为1,梯度可以无衰减地传播。
      3. 产生稀疏性:使部分神经元输出为0,让网络变得稀疏,可能更有利于特征选择。
    • 生物学解释:模拟了神经元“激活”或“抑制”的状态。

在CNN中,标准的流程是:先进行卷积运算,然后立即对结果施加ReLU激活。如果卷积步长大于1,则先完成降维的卷积操作,再对降维后的特征图进行激活。

池化层:降维与特征融合

池化层通常紧跟在卷积-激活层之后,其主要作用是:

  1. 降维(下采样):减少特征图的空间尺寸(长和宽),从而降低计算量和参数量。
  2. 特征融合与增强鲁棒性:聚合局部区域的特征,使特征对小的平移、旋转等形变更加鲁棒。
  3. 无参数需要学习:池化操作是确定性的,没有需要训练的参数。

最大池化(Max Pooling) 是最常用的池化方式。它在一个局部区域(如2x2窗口)内取最大值作为该区域的代表输出。

import numpy as np

# 模拟一个4x4的单通道特征图,模拟ReLU激活后的输出(假设无负值)
feature_map = np.array([[1, 1, 2, 4],
                        [5, 6, 7, 8],
                        [3, 2, 1, 0],
                        [1, 2, 3, 4]], dtype=np.float32)

# 用分块取最大值的方式实现2x2最大池化,步长为2
pool_size = (2, 2)
stride = 2
output_h = feature_map.shape[0] // pool_size[0]
output_w = feature_map.shape[1] // pool_size[1]
max_pool_output = np.zeros((output_h, output_w))

for i in range(0, feature_map.shape[0], stride):
    for j in range(0, feature_map.shape[1], stride):
        region = feature_map[i:i+pool_size[0], j:j+pool_size[1]]
        if region.shape == (pool_size[0], pool_size[1]): # 确保区域完整
            max_pool_output[i//stride, j//stride] = np.max(region)

print("ReLU激活后的特征图 (4x4):")
print(feature_map)
print("\n经过2x2最大池化(步长2)后的输出 (2x2):")
print(max_pool_output)
ReLU激活后的特征图 (4x4):
[[1. 1. 2. 4.]
 [5. 6. 7. 8.]
 [3. 2. 1. 0.]
 [1. 2. 3. 4.]]

经过2x2最大池化(步长2)后的输出 (2x2):
[[6. 8.]
 [3. 4.]]

池化层同样有尺寸和步长两个超参数。常见的设置是2x2池化窗口配合步长2,这样可以将特征图尺寸减半,而通道数保持不变。例如,224x224x64的特征图经过这样的池化后,变为112x112x64。

平均池化(Average Pooling) 取局部区域的平均值作为输出,用于降维。它的特殊形式全局平均池化(Global Average Pooling) 把池化窗口设为整张特征图,每个通道只输出一个数,因此在 GoogLeNet 等网络中被用来替代全连接层,大幅减少参数量。

全连接层与Softmax:从特征到分类

经过多次“卷积-激活-池化”的循环后,我们得到了高度抽象但空间尺寸较小的特征图。为了完成分类任务,需要将这些特征转换为一组类别分数。

  1. 全连接层:首先将最后的特征图展平(Flatten) 成一个长的一维向量。这个向量作为输入,送入一个或多个全连接层。全连接层的作用是综合所有局部特征,进行全局的推理和判别。
  2. Softmax层:通常作为网络的最后一层,接在最终的全连接层之后。它将全连接层输出的实数向量(称为logits)转换为一个概率分布。
    • 公式:对于第 i 个类别的输出分数 z_i,其Softmax概率为 σ(z)_i = exp(z_i) / Σ_j exp(z_j)。
    • 作用:
      • 突出最大值:通过指数运算放大较大值的相对差距。
      • 归一化为概率:将所有输出值压缩到(0,1)之间,且和为1,符合概率解释。
      • 可微性:整个函数是可微的,便于使用梯度下降法优化。
    • 例如,在ImageNet1000分类任务中,最后一个全连接层输出1000个值,经过Softmax后得到1000个类别的预测概率。

📝 动手练一练

  1. 概念辨析:请简述卷积层中的“步长(Stride)”和“填充(Padding)”分别有什么作用?如果希望卷积层不改变输入特征图的空间尺寸(高和宽),可以如何设置这些参数?(假设使用3x3卷积核)
👉 点击查看参考答案

步长(Stride) 决定了卷积核在输入上滑动的间隔。步长越大,输出特征图的尺寸越小,具有降维作用,但可能丢失一些空间信息。

填充(Padding) 是在输入特征图边缘补0(或其他值),主要作用有两个:一是控制输出尺寸,防止因卷积核尺寸和步长导致尺寸收缩过快;二是保留边缘信息,让卷积核能更公平地处理图像边缘的像素。

要使3x3卷积不改变空间尺寸,一个常见的设置是:步长(Stride)= 1,填充(Padding)= 1。根据尺寸计算公式:输出尺寸 = (输入尺寸 - 3 + 2*1) / 1 + 1 = 输入尺寸。

  1. 手算练习:假设有一个单通道的5x5输入矩阵 I,和一个2x2的卷积核 K,均无填充(padding=0),步长(stride)为1。
    • I = [[1,0,1,2,1], [0,2,1,0,1], [1,1,0,2,0], [2,2,1,1,0], [2,0,1,2,1]]
    • K = [[1,0], [0,1]] 请手动计算卷积输出特征图左上角第一个值(即卷积核覆盖I的左上角2x2区域时的结果)。
👉 点击查看参考答案

卷积操作是对应位置相乘后求和。 卷积核覆盖的输入区域为 [[1,0], [0,2]]。 计算:(1*1) + (0*0) + (0*0) + (2*1) = 1 + 0 + 0 + 2 = 3。 因此,输出特征图左上角第一个值是 3。

本章小结

本节我们系统构建了卷积神经网络(CNN)的整体架构蓝图。CNN通过卷积层的局部感受野和权重共享高效提取图像特征,经由ReLU激活函数引入非线性并克服梯度消失,利用池化层进行降维和增强特征鲁棒性,最后通过全连接层和Softmax层完成从特征到类别概率的映射。这种“卷积->激活->池化”的模块化堆叠结构,是深度学习在计算机视觉领域取得突破性进展的基石。

📋 行动清单

  • 画出数据流图:在白板上画出一个简化CNN的数据流,标注从[H,W,3]输入到Softmax概率输出的尺寸变化。
  • 复现计算过程:使用NumPy手动实现一个包含卷积、ReLU、最大池化的小型前向传播过程,验证尺寸计算公式。
  • 对比思考:思考全连接层和卷积层在参数数量和连接方式上的根本区别,理解后者为何更适合图像数据。

—— 小象教研组