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

news2024/9/29 18:28:57

卷积神经网络(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.coloradmin.cn/o/2177528.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

高空抛物AI检测算法:精准防控,技术革新守护城市安全

近年来&#xff0c;随着城市化进程的加速&#xff0c;高楼大厦如雨后春笋般涌现&#xff0c;但随之而来的高空抛物问题却成为城市管理的一大难题。高空抛物不仅严重威胁行人的安全&#xff0c;还可能引发法律纠纷和社会问题。为了有效预防和减少高空抛物事件的发生&#xff0c;…

pnpm依赖安装失败解决|pnpm项目从一个文件夹复制到另一个文件夹运行失败问题解决-以vbenAdmin项目为例

1 前言 最近在使用vben admin项目迁移时&#xff0c;从一个文件夹复制到另一个文件夹运行不起来&#xff0c;排查了一天&#xff0c;终于把问题排查出来了&#xff0c;特地记录一下&#xff0c;便于自己看也便于大家看。 使用项目安装包版本&#xff1a; v2.11.5 https://gi…

【产教融合】新媒体产业园携手高校,共育数字创意人才

在新媒体浪潮的推动下&#xff0c;数字创意产业正以前所未有的速度蓬勃发展。为了应对这一趋势&#xff0c;新媒体产业园积极响应“产教融合”的号召&#xff0c;携手国内多所顶尖高校&#xff0c;共同开启数字创意人才培养的新篇章。 树莓集团一直以来都在新媒体领域有着卓越的…

uni-app如果自定义tabbar实现底部样式有凸起效果,背景带圆角

想要实现的效果、 大部分可以参考这一篇文章 小程序弹出框是没办法遮挡住底部的tabbar的&#xff0c;解决的办法是使用自定义tabbar。。uni-app小程序如何自定义tabbar-CSDN博客 我们只要改下index.wxml和index. wxs的代码就行了 <view class"tab-bar"><b…

stm32 bootloader跳转程序设计

文章目录 1、bootloader跳转程序设计&#xff08;1&#xff09;跳转程序&#xff08;2&#xff09;、app程序中需要注意<1>、在keil中ROM起始地址和分配的空间大小<2>、在system_stm32f4xx.c中设置VECT_TAB_OFFSET为需要偏移的地址<3>、main函数中使能中断 总…

浅析 Keil 中的 sct 文件

目录 一、程序的存储与运行1、存储2、加载、运行 二、sct 分散加载文件1、简介2、文件格式2.1 加载域2.2 执行域2.3 输入节区描述 3、配置 sct 文件 一、程序的存储与运行 1、存储 程序编译后&#xff0c;应用程序中所有具有同一性质的数据(包括代码)被归到一个域&#xff0c…

Java必修课——Spring框架

目录 一、Spring框架概述二、IOC概念和原理2.1、什么是IOC2.2、IOC接口 三、深入理解Java基础中的集合框架3.1、Collection3.2、Map3.3、集合工具类 四、练习写一个SpringMVC框架1、介绍2、程序实践3、总结 五、Java开发者必备10大数据工具和框架 一、Spring框架概述 Spring是…

从追随者到领跑者:suker书客如何粉碎技术障碍,成就行业传奇

护眼灯从小众需求逐渐走向了大众消费&#xff0c;一度引来许多品牌的相继入场&#xff0c;以吸顶灯、吊灯、台灯和落地灯等各大护眼品类为代表&#xff0c;均在悄然替代普通的台灯&#xff0c;这同时也揭示了关于护眼灯的发展潜力。 一些企业看到护眼灯市场前景后&#xff0c;…

煤矿厂智能化可视化:提升安全与效率

运用图扑可视化技术对煤矿厂进行实时监控与数据分析&#xff0c;提高安全管理水平和生产效率。

C语言基础之数组

上一篇讲述了C语言函数的使用&#xff0c;本文讲述数组的相关概念&#xff0c;通过一维数组、二维数组、数组越界等详细讲解数组相关的具体内容&#xff0c;以辅助读者了解并掌握数组相关概念。 一维数组 一维数组的定义与创建 若无数组&#xff0c;我们要存储一堆类型相同的…

osalTaskREC_t ‘REC’缩写的含义

osalTaskREC_t中‘REC’缩写的含义。 在osal中定义了 osalTimerRec_t&#xff0c; osalTaskRec_t 结构体&#xff0c;那么osal源码中类型名 osalTaskREC_t中‘REC’缩写的含义是什么&#xff1f; 查了下往上资料&#xff0c;rec应该是 Record&#xff08;记录&#xff09;’的…

AI大模型之旅-最强开源文生图工具Stable Diffusion WebUI 教程

1.1克隆 Automatic1111 的 GitHub 仓库 在你想安装 Web UI 的文件夹路径下执行 git clone https://github.com/AUTOMATIC1111/stable-diffusion-webui 这将会克隆整个仓库到本地。 这里会默认访问 https://huggingface.co/ 下载 因此需要魔法 1.2 进入仓库目录 cd stable-di…

手机改IP地址怎么弄?全面解析与操作指南

在当今数字化时代&#xff0c;IP地址作为设备在网络中的唯一标识&#xff0c;其重要性不言而喻。有时候&#xff0c;出于隐私保护、网络访问需求或其他特定原因&#xff0c;我们可能需要更改手机的IP地址。然而&#xff0c;对于大多数普通用户来说&#xff0c;如何操作可能还是…

Xshell调用powershell连接Teleport

公司最近切换telport管理SSH的连接访问。配置完成后&#xff0c;通过powershell可能远程访问。但是powershell缺少session管理功能&#xff0c;每次连接都记不住远程IP&#xff0c;很是头疼。 利用Xshell的管理能力是否可行&#xff1f;那是相当可行。 首先&#xff0c;新建se…

环境变量配置文件

环境变量配置文件 系统级配置文件 /etc/profile 系统范围的配置文件&#xff0c;适用于所有用户的登录 shell。 定义了系统级别的环境变量&#xff0c;并调用其他配置文件&#xff08;如 /etc/bash.bashrc&#xff09;。 /etc/bash.bashrc 非登录 shell 的全局配置文件。 在系…

Java异步编程:初学者快速入门到精通指南

异步编程简介 异步编程允许程序在执行某些操作&#xff08;如网络请求、文件I/O等&#xff09;时不被阻塞&#xff0c;能够继续执行其他任务。这不仅可以提高程序的响应性&#xff0c;还能提升资源的利用率。 为什么选择Java进行异步编程&#xff1f; Java提供了多种异步编程…

Echarts折线图的末尾部分线条虚线

原理&#xff1a;等于画了两条线&#xff0c;一条实线一条虚线&#xff1b;把实线的最后的值给虚线&#xff1b;再将提示框进行过滤&#xff0c;防止多个点以及值为空的情况 初步实现参考&#xff1a; option {xAxis: {type: category,data: [Mon, Tue, Wed, Thu, Fri, Sat, …

《低空经济:文旅行业的新引擎 》

《低空经济&#xff1a;文旅行业的新引擎 》 一、低空经济与文旅行业的融合态势 低空经济作为新兴经济形态&#xff0c;正与文旅行业深度融合&#xff0c;为文旅发展带来新机遇。 近年来&#xff0c;随着科技的不断进步和人们对旅游体验的不断追求&#xff0c;低空经济与文旅…

js列表数据时间排序和取唯一值

1.取唯一值[...new Set(array)] const array [1, 2, 3, 2, 4, 5, 3, 5]; // 使用Set去除重复元素 const uniarray [...new Set(array)]; console.log(uniarray); // 输出: [1, 2, 3, 4, 5] 2.排序 var u [1,3,2,5,4]; var uu u.sort(); console.log(uu); var u [1,3…

ACL 2023--MetaAdapt: 通过元学习实现领域自适应的少量样本虚假信息检测

https://github.com/Yueeeeeeee/MetaAdapt 随着社交媒体上出现的新话题&#xff08;例如COVID-19&#xff09;成为虚假信息传播的来源&#xff0c;克服原始训练领域&#xff08;即源领域&#xff09;与这些目标领域之间的分布变化&#xff0c;仍然是虚假信息检测中的一项复杂任…