当前位置: 首页 > article >正文

【深度学习】04-Cnn卷积神经网络-01- 卷积神经网络概述/卷积层/池化层/分类案例精讲

卷积神经网络(CNN,Convolutional Neural Network)是专门用于处理图像数据的神经网络。

图像的基本概念

图像其实是数组: ndarray -> [高,宽,3通道] --> uint8

每个值取值范围0-255,那么正好是 uint8 (无符号8位整型)的类型取值范围

一个数组,能变成图片,全靠渲染器进行渲染。

现阶段:学习阶段我们暂时使用 matplotlib 来渲染·输出图像。

import numpy as np
import matplotlib.pyplot as plt
# mac 电脑设置。
# 设置全局字体为 PingFang HK
plt.rcParams['font.family'] = 'PingFang HK'
plt.rcParams['axes.unicode_minus'] = False  # 解决负号显示问题

# 创建一个包含1行3列的子图布局
fig, axes = plt.subplots(1, 3, figsize=(12, 4))

# 全0的图像数据,黑色
img1 = np.full((200, 200, 3), 0)
axes[0].imshow(img1)
axes[0].set_title('全0 - 黑色')

# 全128的图像数据,灰色
img2 = np.full((200, 200, 3), 128)
axes[1].imshow(img2)
axes[1].set_title('全128 - 灰色')

# 全255的图像数据,白色
img3 = np.full((200, 200, 3), 255)
axes[2].imshow(img3)
axes[2].set_title('全255 - 白色')


# 显示图像
plt.show()

好的,接下来我们查看一个图片的数值:

把图片复制到文件夹命名

data/花朵.jpeg

import numpy as np
import matplotlib.pyplot as plt
img = plt.imread('./data/花朵.jpeg')
print(img.shape)
plt.imshow(img)
plt.show()

可见图片是一个4080 *3060 像素,3通道的图片

新建一个图像,命名为img.jpg

import numpy as np
import matplotlib.pyplot as plt

# 读取图像
img = plt.imread('./data/img.jpg')

# 输出图像的形状
print("图像的形状:", img.shape)

# 输出完整的图像数组
# print("图像的数值:", img)

# 只输出图像的前5个像素值,避免输出过多数据
print("图像前5个像素值:", img[:5, :5, :])

# 显示图像
plt.imshow(img)
plt.show()

代码的输出:可以看到每个像素的值,这样就不是全0,全128,全255的图了。 

图像的形状: (640, 640, 3)
图像前5个像素值: [[[212 113  94]
  [212 113  94]
  [212 113  94]
  [213 112  94]
  [213 112  94]]

 [[212 113  94]
  [212 113  94]
  [212 113  94]
  [213 112  94]
  [213 112  94]]

 [[212 113  94]
  [211 112  93]
  [211 112  93]
  [212 111  93]
  [212 111  93]]

 [[211 112  93]
  [211 112  93]
  [210 111  92]
  [211 110  92]
  [211 110  92]]

 [[211 112  93]
  [210 111  92]
  [210 111  92]
  [211 110  92]
  [211 110  92]]]

<Figure size 640x480 with 1 Axes>

图片在卷积神经网络(CNN,Convolutional Neural Network)中的处理原理是基于图像的像素点及其颜色信息。首先,图像是由像素点构成的,每个像素点在RGB(红、绿、蓝)三个通道上都有一个值,取值范围为0到255,这就是你在图中看到的R、G、B矩阵。

CNN是专门用于处理这种图像数据的神经网络,它通过一系列的卷积、池化(Pooling)、激活函数等操作,提取图像中的特征。

具体步骤如下:

  1. 输入图像:输入的图像通常是由三通道的RGB图像构成。每个像素的颜色由红色(R)、绿色(G)和蓝色(B)通道的强度值表示。图中的示例表示,图像会被拆分为R、G、B三张单通道的图像。

  2. 卷积操作:CNN通过应用卷积核(Kernel/Filter)来提取图像中的局部特征。卷积核是一个小矩阵(例如3x3或5x5),它会逐步在输入图像上滑动,计算对应区域的加权和,从而提取到边缘、角点等局部特征。

  3. 激活函数(ReLU):卷积操作完成后,通常会通过ReLU(Rectified Linear Unit)激活函数对结果进行非线性变换,消除负值,这有助于引入网络的非线性,从而使模型能够处理更加复杂的模式。

  4. 池化(Pooling):池化层的作用是对特征图进行下采样,减小特征图的尺寸。最常见的是最大池化(Max Pooling),它会在一个小区域(如2x2)的特征图中,取该区域内的最大值,这样可以减少数据量,同时保留重要的特征。

  5. 全连接层(Fully Connected Layer):经过多个卷积层和池化层之后,图像的特征被逐渐提取出来。最终,图像的特征图被展平为一个一维向量,输入到全连接层进行分类或回归任务。

  6. 输出层:在图像分类任务中,输出层通常是一个Softmax层,用来输出各个类别的概率。对于其他任务,比如目标检测或图像分割,输出层会有所不同。

总之,CNN通过一系列的卷积操作提取图像的局部特征,再通过池化降低计算复杂度,最后通过全连接层进行特征整合,达到对图像内容的理解。

这张图展示的RGB图像表示就是典型的卷积神经网络中的输入形式。

卷积神经网络(CNN,Convolutional Neural Network)的概述

卷积神经网络概述

什么是卷积神经网络(CNN, Convolutional Neural Network)?

卷积神经网络(CNN)是一种深度学习模型,主要用于处理图像和视频等数据。与传统的神经网络不同,CNN 利用了卷积运算,通过自动提取局部特征来简化图像处理任务,尤其适合处理高维数据(如图像)的问题。

CNN的主要构成部分
  1. 卷积层(Convolutional Layer)

    • 作用:卷积层是 CNN 中的核心组件,负责从输入图像中自动提取局部特征。通过卷积操作,卷积层可以捕捉到图像中的边缘、纹理、轮廓等低级特征。在较深的卷积层中,模型可以提取到更复杂的模式,如图像中的物体形状、位置等高级特征。

    • 卷积操作:卷积核(Kernel)是一个小尺寸的矩阵(如 3x3 或 5x5),它会遍历图像的不同位置,通过加权求和的方式提取局部信息。

    • ReLU 激活函数:通常在卷积层之后会使用 ReLU 激活函数,这是一种非线性函数,用于引入非线性特征并加速训练。

  2. 池化层(Pooling Layer)

    • 作用:池化层的主要作用是对卷积层输出的特征图进行降维,减少特征图的大小,同时保留关键特征。池化层可以减少计算量,防止过拟合。

    • 最大池化(Max Pooling):最常用的池化方式之一是最大池化,它会从一个局部区域(如 2x2 的窗口)中选取最大值。这种操作既减少了数据维度,又保留了最显著的特征。

    • 平均池化(Average Pooling):有时也会使用平均池化,它会取窗口内所有像素值的平均值,但一般来说最大池化更常用。

  3. 全连接层(Fully Connected Layer, FC)

    • 作用:全连接层位于网络的最后部分,负责将卷积层和池化层提取的特征组合起来,输出最终的分类或回归结果。全连接层与传统的神经网络相似,每个神经元与前一层的所有神经元相连接。

    • 作用机制:在经过多个卷积层和池化层后,特征图被展平(flatten)为一维向量,并输入到全连接层。最后,网络的输出通常通过 Softmax 函数进行归一化,用于图像分类任务。

CNN的附加组成
  • 批量归一化(Batch Normalization):用于加速模型的训练速度,减少训练时间,还能提高模型的性能。批量归一化通过调整和缩放网络中每一层的激活值,解决了深度网络训练中的梯度消失或爆炸问题。

  • Dropout:一种正则化技术,用来防止模型过拟合。在训练时,随机丢弃一定比例的神经元,使得模型更具鲁棒性。在测试时,所有神经元参与运算。

CNN的运作流程
  1. 输入图像:输入一个 RGB 图像,该图像被表示为一个三维数组(形状为 height x width x channels)。

  2. 卷积层提取特征:第一个卷积层提取基本特征,如边缘、角点等;随着网络加深,后续卷积层提取更高级的语义信息。

  3. 池化层降维:池化层逐步降低特征图的维度,保留显著特征,减少计算量。

  4. 全连接层整合特征:池化后的特征被展平,通过全连接层,最终整合成分类结果。

  5. 输出结果:通过 Softmax 函数等将最终结果转化为各个类别的概率分布。

总结:
  1. 什么是卷积神经网络?

    • 含有卷积层的神经网络,专用于从图像中自动提取特征。适用于图像分类、目标检测等任务。

  2. 卷积神经网络的构成

    • 卷积层(Convolutional Layer):提取图像特征。

    • 池化层(Pooling Layer):降维,减少计算量。

    • 全连接层(Fully Connected Layer):输出最终的分类或回归结果。

通过卷积、池化和全连接操作,卷积神经网络(CNN, Convolutional Neural Network) 能够有效地从复杂的高维数据中提取有意义的模式和特征,是现代计算机视觉任务的核心模型。

卷积层的介绍

为什么需要padding,因为我们的卷积核是有大小的,是一个形状的,如果我们不在原始图片周围加0来扩大图片的话,那么边缘信息,就不会在卷积核的中心,导致学习内容缺失或者说和中心数据学习不一样,所以padding 的主要作用是用于学习边缘信息。也就是说,padding是对原始特征外圈补几圈零。因为在卷积计算的时候0是不会影响计算结果的。

接下来我们创建一个卷积层来看看生成的特征大小:
import matplotlib.pyplot as plt
import torch
from torch import nn

# 1. 读取图像
# 使用 matplotlib 库中的 imread 函数读取图像。读取的图像通常是一个 NumPy 数组,
# 形状为 (height, width, channels),其中 channels 为 3(RGB 颜色通道)。
img = plt.imread('./data/img.jpg')

# 打印图像的原始形状,方便确认图像的维度信息
print(img.shape)  # 输出形状如 (高度, 宽度, 通道数)

# 2. 转换图像数据
# 将读取的图像数据转换为 PyTorch 张量。
# 在图像处理中,PyTorch 期望的输入数据形式是 (batch_size, channels, height, width),
# 而不是通常的 (height, width, channels)。
# 通过 permute 操作调整图像维度顺序 (channels, height, width),然后使用 unsqueeze 在最前面添加 batch_size 维度。
# 转换为 float32 类型以符合 PyTorch 处理需求,默认的图像数据通常是 uint8 类型(0-255)。
img = torch.tensor(img).permute(2, 0, 1).unsqueeze(0).to(torch.float32)

# 打印调整后的张量形状,应该是 (1, channels, height, width),即 (batch_size, 通道数, 高度, 宽度)
print(img.shape)

# 3. 定义卷积层
# 使用 nn.Conv2d 来定义一个二维卷积层。
# 参数说明:
# - in_channels:输入图像的通道数,这里是 3,表示 RGB 图像有三个颜色通道。
# - out_channels:卷积层的输出通道数,设置为 5,表示会有 5 个输出的特征图。
# - kernel_size:卷积核的大小,设置为 (3, 5),表示卷积核的大小为 3x5。
# - stride:卷积核在图像上滑动的步长,这里设置为 (1, 2),表示在高度方向步长为 1,宽度方向步长为 2。
# - padding:填充大小,这里设置为 2,表示在高度和宽度方向上各自填充 2 像素,保持图像特征图的尺寸。

conv = nn.Conv2d(in_channels=3, out_channels=5, kernel_size=(3, 5), stride=(1, 2), padding=2)

# 4. 处理图像
# 将图像张量 img 输入到卷积层 conv 中,生成特征图 fm。
# fm 是卷积操作后得到的输出张量,其形状为 (batch_size, out_channels, new_height, new_width)。
# 其中 new_height 和 new_width 由卷积层的卷积核大小、步长和填充方式决定。
fm = conv(img)

# 打印卷积后的特征图形状,输出的 shape 应该是 (1, 5, new_height, new_width),
# 其中 1 表示 batch_size,5 表示输出的通道数(out_channels),new_height 和 new_width 是卷积后的特征图尺寸。
print(fm.shape)

关键点总结:

  1. 读取和调整图像数据

    • 使用 plt.imread() 读取图像,默认返回一个形状为 (height, width, channels) 的 NumPy 数组。

    • 转换为 PyTorch 张量并调整维度,使其符合 PyTorch 中卷积层的输入要求 (batch_size, channels, height, width)

  2. 卷积层的参数

    • in_channels=3:输入图像的通道数,即 RGB 图像的 3 个通道。

    • out_channels=5:输出 5 个特征图。

    • kernel_size=(3, 5):卷积核的尺寸为 3x5。

    • stride=(1, 2):高度方向步长为 1,宽度方向步长为 2。

    • padding=2:在卷积操作前对输入图像进行 2 像素的填充。

  3. 卷积操作

    • 卷积层将输入图像通过卷积核操作生成多个特征图。

    • 卷积后输出特征图的尺寸取决于输入图像的尺寸、卷积核大小、步长、填充量等。

这个过程展示了如何使用 PyTorch 读取图像、处理图像并通过卷积层生成特征图的整个流程。

输出:

这个输出表示在不同步骤中张量(图像)的形状,具体解释如下:

  1. (640, 640, 3):

    • 这是读取的原始图像的形状。

    • 640 x 640 表示图像的高度和宽度均为 640 像素。

    • 3 表示图像的通道数,3 通道通常代表 RGB 图像(红、绿、蓝)。

  2. torch.Size([1, 3, 640, 640]):

    • 这是图像在被转换为 PyTorch 张量并调整维度后的形状。

    • 1:表示批处理的大小(batch size),这里设置为 1,表示只有一张图像。

    • 3:表示图像的通道数,仍然是 RGB 图像的 3 个通道。

    • 640 x 640:表示图像的高度和宽度,依然是 640x640 像素。

    • 总的来说,这个形状表示 PyTorch 中标准的 4 维图像张量 (batch_size, channels, height, width)

  3. torch.Size([1, 5, 642, 320]):

    • 这是经过卷积层后的输出张量的形状。

    • 1:表示批处理的大小,仍然是 1。

    • 5:表示输出的通道数(卷积核的数量),即卷积层有 5 个输出特征图(因为卷积层设置了 out_channels=5)。

    • 642:表示卷积操作后特征图的高度,原始高度为 640,经过了卷积运算后变为 642。这是由于卷积核和填充的设置造成的。

      • 卷积层的 padding=2kernel_size=(3, 5) 影响了输出的尺寸,导致高度增加。

    • 320:表示卷积操作后特征图的宽度,原始宽度为 640,经过步长为 2 的卷积操作后宽度减少到 320(宽度缩小了大约一半)。

卷积后的特征图尺寸的计算:

卷积层的输出尺寸可以通过公式计算:

高度的计算:

H_{out} = \frac{(H_{in} + 2 \times \text{padding} - \text{kernel\_size})}{\text{stride}} + 1

宽度的计算:   

W_{out} = \frac{(W_{in} + 2 \times \text{padding} - \text{kernel\_size})}{\text{stride}} + 1

对高度(H_in = 640,kernel_size = 3,padding = 2,stride = 1): 

H_{out} = \frac{(640 + 2 \times 2 - 3)}{1} + 1 = 642

对宽度(W_in = 640,kernel_size = 5,padding = 2,stride = 2):

W_{out} = \frac{(640 + 2 \times 2 - 5)}{2} + 1 = 320

因此,卷积层的输出张量形状为 (1, 5, 642, 320),即批处理大小为 1,输出通道为 5,高度为 642,宽度为 320。

总结:

  • (640, 640, 3):原始 RGB 图像的形状。

  • torch.Size([1, 3, 640, 640]):转换后的 PyTorch 张量的形状,批大小为 1,通道数为 3,高宽为 640x640。

  • torch.Size([1, 5, 642, 320]):经过卷积层后的输出特征图,批大小为 1,输出 5 个特征图,特征图大小为 642x320。

池化层的介绍

import torch 
from torch import nn

# 设置随机种子以保证每次运行得到相同的随机数
torch.random.manual_seed(22)

# 创建一个 3x3 的张量,值在 [0, 10) 范围内,数据类型为 float32,batch_size = 1,通道数 = 1
data = torch.randint(0, 10, [1, 3, 3], dtype=torch.float32)

# 打印生成的 3x3 张量,初始数据为随机生成的
print(data)
# 输出的张量如下:
# tensor([[[9., 6., 6.],
#          [4., 2., 2.],
#          [2., 1., 8.]]])

# 定义一个最大池化层,池化窗口大小为 (2, 2),步长为 (1, 1),不使用填充
pool = nn.MaxPool2d(kernel_size=(2, 2), stride=(1, 1), padding=0)

# 对数据应用最大池化操作,并打印结果
print(pool(data))
# 最大池化过程:从每个 2x2 的窗口取最大值
# 1. 第一个窗口 [9, 6, 4, 2],最大值为 9
# 2. 第二个窗口 [6, 6, 2, 2],最大值为 6
# 3. 第三个窗口 [4, 2, 2, 1],最大值为 4
# 4. 第四个窗口 [2, 2, 1, 8],最大值为 8
# 输出如下:
# tensor([[[9., 6.],
#          [4., 8.]]])

# 定义一个平均池化层,池化窗口大小为 (2, 2),步长为 (1, 1),不使用填充
pool2 = nn.AvgPool2d(kernel_size=(2, 2), stride=(1, 1), padding=0)

# 对数据应用平均池化操作,并打印结果
print(pool2(data))
# 平均池化过程:从每个 2x2 的窗口取平均值
# 1. 第一个窗口 [9, 6, 4, 2],平均值为 (9+6+4+2)/4 = 5.25
# 2. 第二个窗口 [6, 6, 2, 2],平均值为 (6+6+2+2)/4 = 4.00
# 3. 第三个窗口 [4, 2, 2, 1],平均值为 (4+2+2+1)/4 = 2.25
# 4. 第四个窗口 [2, 2, 1, 8],平均值为 (2+2+1+8)/4 = 3.25
# 输出如下:
# tensor([[[5.2500, 4.0000],
#          [2.2500, 3.2500]]])

代码输出:

输出解释:

1. 随机生成的数据:一个 1x3x3 的张量,表示一个批次中的单张图像,大小为 3x3,数据值为随机生成的 0 到 9 之间的浮点数。

2. 最大池化的结果

• 将 3x3 的数据分为若干个 2x2 的区域,对每个区域选取最大值作为输出。最终输出的是 2x2 的张量,表示池化后的图像。

3. 平均池化的结果

• 同样的 2x2 窗口区域,对每个区域计算其平均值,输出同样是 2x2 的张量。

这段代码展示了在 PyTorch 中如何使用最大池化和平均池化操作,并通过实例演示了池化过程中的计算方式。

我们以一个3*3*3 的案例来讲解多通道池化层的计算过程,但是实际中肯定不会出现这么小的图像数据,实际中我们的池化窗口一般是 3*3

kernel_size=(3,3)

 步长一般设计为 2*2

stride=(2,2)

 然后 padding的话,一般没有特别要求,建议自己超参数,多设计几次,炼丹。

import torch
from torch import nn

# 设置随机种子以保证每次运行生成相同的随机数,确保结果可复现
torch.random.manual_seed(22)

# 创建一个 3x3x3 的张量,值在 [0, 10) 范围内,数据类型为 float32。
# 这里 3x3 表示每张图像的大小(3x3 像素),有 3 个通道(类似 RGB 三通道)。
data = torch.randint(0, 10, [3, 3, 3], dtype=torch.float32)

# 打印生成的张量
print(data)
# 输出的张量数据如下:
# tensor([[[9., 6., 6.],
#          [4., 2., 2.],
#          [2., 1., 8.]],

#         [[0., 1., 0.],
#          [3., 2., 4.],
#          [4., 9., 0.]],

#         [[0., 1., 3.],
#          [2., 9., 7.],
#          [8., 4., 1.]]])
# 这个张量表示 3 个通道,每个通道是 3x3 的二维图像数据。

# 定义一个最大池化层,窗口大小为 (2, 2),步长为 (1, 1),不进行填充。
pool = nn.MaxPool2d(kernel_size=(2, 2), stride=(1, 1), padding=0)

# 对数据应用最大池化操作
print(pool(data))

# 定义一个平均池化层,窗口大小为 (2, 2),步长为 (1, 1),不进行填充。
pool = nn.AvgPool2d(kernel_size=(2, 2), stride=(1, 1), padding=0)

# 对数据应用平均池化操作
print(pool(data))

多通道池化层代码输出 

tensor([[[9., 6., 6.],
         [4., 2., 2.],
         [2., 1., 8.]],

        [[0., 1., 0.],
         [3., 2., 4.],
         [4., 9., 0.]],

        [[0., 1., 3.],
         [2., 9., 7.],
         [8., 4., 1.]]])
tensor([[[9., 6.],
         [4., 8.]],

        [[3., 4.],
         [9., 9.]],

        [[9., 9.],
         [9., 9.]]])
tensor([[[5.2500, 4.0000],
         [2.2500, 3.2500]],

        [[1.5000, 1.7500],
         [4.5000, 3.7500]],

        [[3.0000, 5.0000],
         [5.7500, 5.2500]]])

解释:

输入张量的形状

  • 输入张量的形状是 (3, 3, 3),表示 3 个通道,每个通道的图像大小为 3x3。

  • 张量的内容表示 3x3 图像的像素值,生成的 3 个通道张量如下:

    通道 1:  9 6 6
            4 2 2
            2 1 8
    ​
    通道 2:  0 1 0
            3 2 4
            4 9 0
    ​
    通道 3:  0 1 3
            2 9 7
            8 4 1

最大池化操作(Max Pooling)

最大池化计算过程

最大池化后的输出

tensor([[[9., 6.],
        [4., 8.]],
​
       [[3., 4.],
        [9., 9.]],
​
       [[9., 9.],
        [9., 9.]]])
  1. nn.MaxPool2d(kernel_size=(2, 2), stride=(1, 1), padding=0)

    • kernel_size=(2, 2):表示 2x2 的池化窗口。

    • stride=(1, 1):表示每次滑动 1 个像素。

    • padding=0:表示不进行填充,池化窗口完全在图像内移动。

  2. 对每个 2x2 的窗口,选择其中的最大值作为输出:

  3. 通道 1

    1. 窗口 [9, 6, 4, 2],最大值为 9。

    2. 窗口 [6, 6, 2, 2],最大值为 6。

    3. 窗口 [4, 2, 2, 1],最大值为 4。

    4. 窗口 [2, 2, 1, 8],最大值为 8。

  4. 通道 2

    1. 窗口 [0, 1, 3, 2],最大值为 3。

    2. 窗口 [1, 0, 2, 4],最大值为 4。

    3. 窗口 [3, 2, 4, 9],最大值为 9。

    4. 窗口 [2, 4, 9, 0],最大值为 9。

  5. 通道 3

    1. 窗口 [0, 1, 2, 9],最大值为 9。

    2. 窗口 [1, 3, 9, 7],最大值为 9。

    3. 窗口 [2, 9, 8, 4],最大值为 9。

    4. 窗口 [9, 7, 4, 1],最大值为 9。

平均池化操作(Average Pooling)

平均池化计算过程

平均池化后的输出

tensor([[[5.2500, 4.0000],
        [2.2500, 3.2500]],
​
      [[1.5000, 1.7500],
        [4.5000, 3.7500]],
​
      [[3.0000, 5.0000],
        [5.7500, 5.2500]]])
  1. nn.AvgPool2d(kernel_size=(2, 2), stride=(1, 1), padding=0)

  2. 和最大池化的窗口大小、步长、填充方式相同,但池化时计算的是窗口内像素的平均值。

  3. 对每个 2x2 的窗口,计算其中的像素平均值作为输出:

         通道 1

  • 窗口 [9, 6, 4, 2],平均值为 (9 + 6 + 4 + 2) / 4 = 5.25

    窗口 [6, 6, 2, 2],平均值为 (6 + 6 + 2 + 2) / 4 = 4.00

    窗口 [4, 2, 2, 1],平均值为 (4 + 2 + 2 + 1) / 4 = 2.25

    窗口 [2, 2, 1, 8],平均值为 (2 + 2 + 1 + 8) / 4 = 3.25

  • 通道 2

  • 窗口 [0, 1, 3, 2],平均值为 (0 + 1 + 3 + 2) / 4 = 1.50

  • 窗口 [1, 0, 2, 4],平均值为 (1 + 0 + 2 + 4) / 4 = 1.75

  • 窗口 [3, 2, 4, 9],平均值为 (3 + 2 + 4 + 9) / 4 = 4.50

  • 窗口 [2, 4, 9, 0],平均值为 (2 + 4 + 9 + 0) / 4 = 3.75

  • 通道 3

    窗口 [0, 1, 2, 9],平均值为 (0 + 1 + 2 + 9) / 4 = 3.00

    窗口 [1, 3, 9, 7],平均值为 (1 + 3 + 9 + 7) / 4 = 5.00

    窗口 [2, 9, 8, 4],平均值为 (2 + 9 + 8 + 4) / 4 = 5.75

    窗口 [9, 7, 4, 1],平均值为 (9 + 7 + 4 + 1) / 4 = 5.25

总结:

  • 最大池化:对于每个 2x2 的窗口,选取最大值,保留图像中特征最显著的部分。

  • 平均池化:对于每个 2x2 的窗口

池化层(Pooling Layer)在卷积神经网络中的作用和机制

背景与历史

池化层最早应用于卷积神经网络(CNN)中,用来降低特征图的尺寸,减少模型参数,并加快计算速度。卷积神经网络的最初版本如LeNet(由Yann LeCun在1990年代提出)就已经引入了池化层的概念。池化层作为卷积层的补充,可以避免过拟合,并增强模型的泛化能力。

池化层的作用
  1. 降低维度:池化层通过下采样的方式,减少特征图的大小(如从 4x4 到 2x2),从而减少数据量。这对于后续的计算有很大的帮助。

  2. 减少计算量:随着特征图的尺寸减小,后续层所需的计算量也会随之减小。这使得模型在处理大规模数据时更加高效。

  3. 防止过拟合:池化层通过对特征进行下采样,可以避免网络过度拟合训练数据的细节,提高模型的泛化能力。

  4. 位置不变性:池化层保留了重要特征,同时忽略了小范围内的位移。因此,模型在面对同一物体在不同位置时具有更强的鲁棒性。

池化机制

池化层通常使用固定大小的窗口滑动于输入特征图之上,并对窗口内的值进行某种操作(如最大值或平均值)。最常用的池化方法有两种:

  1. 最大池化(Max Pooling)

    • 从窗口内取最大值。最大池化可以保留局部区域中最强的激活特征,通常用于提取边缘、角点等显著特征。

    • 例如在2x2的窗口中,如果输入为 [0, 1, 3, 2],则最大池化的结果为 3。

  2. 平均池化(Average Pooling)

    • 从窗口内取平均值。平均池化对于平滑特征图、减少噪声有一定的帮助,但通常在现代的 CNN 中,最大池化比平均池化使用得更多。

    • 例如在2x2的窗口中,如果输入为 [0, 1, 3, 2],则平均池化的结果为 (0+1+3+2)/4 = 1.5。

池化操作中的关键参数
  1. 池化核大小(Kernel Size):池化操作的窗口大小,常见的是 2x2 或 3x3 的核。

  2. 步长(Stride):池化核在输入特征图上滑动的步长。较大的步长可以减少池化后的特征图尺寸。一般常用步长与池化核大小相同,例如步长为 2 的 2x2 池化。

  3. 填充(Padding):在边界处是否进行填充操作。如果使用填充,输入特征图的边界会被增加一些值(通常是 0),以便在边缘区域也能进行池化操作。

PyTorch中的池化层API

在 PyTorch 中,使用 torch.nn 模块可以非常方便地实现池化层,最常用的是 nn.MaxPool2dnn.AvgPool2d

  1. MaxPool2d 示例

    import torch
    import torch.nn as nn
    ​
    # 定义一个2x2的最大池化层
    max_pool = nn.MaxPool2d(kernel_size=2, stride=2)
    ​
    # 假设输入是一个4x4的特征图
    input_tensor = torch.tensor([[1, 2, 3, 4],
                                [5, 6, 7, 8],
                                [9, 10, 11, 12],
                                [13, 14, 15, 16]]).unsqueeze(0).unsqueeze(0)
    ​
    # 应用最大池化操作
    output_tensor = max_pool(input_tensor)
    print(output_tensor)

  2. AvgPool2d 示例

    import torch
    import torch.nn as nn
    ​
    # 定义一个2x2的平均池化层
    avg_pool = nn.AvgPool2d(kernel_size=2, stride=2)
    ​
    # 假设输入是一个4x4的特征图
    input_tensor = torch.tensor([[1, 2, 3, 4],
                                [5, 6, 7, 8],
                                [9, 10, 11, 12],
                                [13, 14, 15, 16]]).unsqueeze(0).unsqueeze(0)
    ​
    # 应用平均池化操作
    output_tensor = avg_pool(input_tensor)
    print(output_tensor)

池化层的历史与问题解决
  1. 背景:在早期的神经网络中,直接使用全连接层处理图像特征,导致了巨大的参数量。池化层通过降低特征图的维度,显著减少了参数数量,同时提升了计算效率。

  2. 解决的问题

    • 降低特征图的尺寸:池化层通过下采样减少特征图的尺寸。

    • 减少模型的计算量:池化降低了特征图尺寸,从而减少了计算量。

    • 增强模型的泛化能力:池化通过忽略一些不重要的细节,增强了模型的泛化能力。

    • 减少过拟合的风险:池化层在减少参数数量的同时,降低了过拟合的风险。

总结

池化层是卷积神经网络中的关键组件,用于通过下采样操作来减少特征图的维度和模型计算量。它能增强模型对输入图像位置变化的鲁棒性,同时避免模型过拟合。在现代的 CNN 中,最大池化(Max Pooling)是最常用的池化方法,而 PyTorch 提供了灵活的 API 让用户轻松实现池化操作。

通过掌握池化的机制与原理,你可以更好地理解 CNN 如何高效地处理大规模图像数据,并进一步优化深度学习模型。

好的到这里我们已经讲解完了卷积神经网络中的卷积层和池化层, 然后再加一个全连接层(深度学习03神经网络有讲过)

【深度学习】03-神经网络 5 (完结篇) 一文讲解 pytroch手机价格神经网络分类与准确率优化案例-CSDN博客

因此全连接层,卷积层,池化层 三者一起我们就可以实现一个图像分类的案例了。

图像分类案例

具体代码和数据集我会另开一个文章来讲解。预知后续如何请听下回分解。


http://www.kler.cn/a/321284.html

相关文章:

  • Flink Job更新和恢复
  • 【SpringBoot】20 同步调用、异步调用、异步回调
  • 基于STM32的智能家居安防系统设计
  • javaWeb小白项目--学生宿舍管理系统
  • 基于Python 和 pyecharts 制作招聘数据可视化分析大屏
  • 学习日志010--python异常处理机制与简单文件操作
  • 【MySQL】数据库--索引
  • 未来数字世界相关技术、应用:AR/VR/MR;数字人、元宇宙、全息显示
  • 开源链动 2+1 模式 S2B2C 商城小程序:激活 KOC,开启商业新征程
  • 将Mixamo的模型和动画导入UE5
  • C--结构体和位段的使用方法
  • 一道涉及 Go 中的并发安全和数据竞态(Race Condition)控制的难题
  • 碎纸片的自动拼接复原技术
  • tcp、udp通信调试工具Socket Tool
  • 协议IP规定,576字节和1500字节的区别
  • MySQL关卡任务书
  • 单样本Cellchat(V2)细胞通讯分析学习和整理
  • 2.2 HuggingFists中的编程语言
  • [NewStarCTF 2023 公开赛道]Begin of PHP1
  • Qt | Linux+QFileSystemWatcher文件夹和文件监视(例如监视U盘挂载目录)
  • 计算机毕业设计之:云中e百货微信小程序设计与实现(源码+文档+定制)
  • 力扣9.25
  • 微信小程序开发第五课
  • LSI SAS 9361-8i和SAS3008 12 gb / s PCIe 3.0 RAID 阵列卡配置
  • Codeforces Round 592 (Div. 2) C题 The Football Season(Exgcd)
  • AI大模型横评-9月Update(O1,Grok2,Qwen,Step-2)