• 卷积神经网络(CNN)理解


    1、引言(卷积概念)

        在介绍CNN中卷积概念之前,先介绍一个数字图像中“边缘检测edge detection”案例,以加深对卷积的认识。图中为大小8X8的灰度图片,图片中数值表示该像素的灰度值。像素值越大,颜色越亮,所以为了示意,我们把右边小像素的地方画成深色,图的中间两个颜色的分界线就是我们要检测的边界。

        该怎么检测边界呢?我们可以设计这样的一个 滤波器(filter,也称为kernel),大小3×3:

          然后,我们用这个filter,往我们的图片上“盖”,覆盖一块跟filter一样大的区域之后,对应元素相乘,然后求和。计算一个区域之后,就向其他区域挪动,接着计算,直到把原图片的每一个角落都覆盖到了为止。这个过程就是 “卷积”。 (我们不用管卷积在数学上到底是指什么运算,我们只用知道在CNN中是怎么计算的。) 这里的“挪动”,就涉及到一个步长,假如我们的步长是1,那么覆盖了一个地方之后,就挪一格,容易知道,总共可以覆盖6×6个不同的区域。

          通过上述操作,发现边界被准确探测出。

          卷积神经网络(CNN)中的卷积,就是通过一个个的filter,不断地提取特征,从局部的特征到总体的特征,从而进行图像识别等等功能。

          那么问题来了,我们怎么可能去设计这么多各种各样的filter?首先,我们都不一定清楚对于一大堆图片,我们需要识别哪些特征,其次,就算知道了有哪些特征,想真的去设计出对应的filter,恐怕也并非易事,要知道,特征的数量可能是成千上万的。

          其实学过神经网络之后,我们就知道,这些filter,根本就不用我们去设计,每个filter中的各个数字,不就是参数吗,我们可以通过大量的数据,来让机器自己去“学习”这些参数嘛。这就是CNN的原理。

    2、CNN基本概念

          在理解CNN中卷积概念后,有一些基本概念需要理解,包括padding填白、stride步长、pooling池化、对多通道图片卷积。

    2.1 padding填白

          从上面的引子中,我们可以知道,原图像在经过filter卷积之后,变小了,从(8,8)变成了(6,6)。假设我们再卷一次,那大小就变成了(4,4)了。

          这样有啥问题呢? 主要有两个问题: 每次卷积,图像都缩小,这样卷不了几次就没了;  相比于图片中间的点,图片边缘的点在卷积中被计算的次数很少。这样的话,边缘的信息就易于丢失。

           为了解决这个问题,我们可以采用padding的方法。我们每次卷积前,先给图片周围都补一圈空白,让卷积之后图片跟原来一样大,同时,原来的边缘也被计算了更多次。

          比如,我们把(8,8)的图片给补成(10,10),那么经过(3,3)的filter之后,就是(8,8),没有变。

          我们把上面这种“让卷积之后的大小不变”的padding方式,称为 “Same”方式, 把不经过任何填白的,称为 “Valid”方式。这个是我们在使用一些框架的时候,需要设置的超参数。

    2.2 stride步长

          前面我们所介绍的卷积,都是默认步长是1,但实际上,我们可以设置步长为其他的值。 比如,对于(8,8)的输入,我们用(3,3)的filter, 如果stride=1,则输出为(6,6); 如果stride=2,则输出为(3,3)。

          举栗子:

    • 栗子1:stride=1,padding=0(遍历采样,无填充:padding=‘valid’)
    • 栗子2:stride=1,padding=1(遍历采样,有填充:padding=‘same’)
    • 栗子3:stride=2,padding=0(降采样,无填充:尺寸缩小二点五分之一)
    • 栗子4:stride=2,padding=1(降采样,有填充;尺寸缩小二分之一)

          Stride的作用:是成倍缩小尺寸,而这个参数的值就是缩小的具体倍数,比如步幅为2,输出就是输入的1/2;步幅为3,输出就是输入的1/3。

    1. 栗子1: 一个特征图尺寸为4*4的输入,使用3*3的卷积核,步幅=1,填充=0
    2. 输出的尺寸=(4 - 3)/1 + 1 = 2

    1. 栗子2: 一个特征图尺寸为5*5的输入,使用3*3的卷积核,步幅=1,填充=1
    2. 输出的尺寸=(5 + 2*1 - 3)/1 + 1 = 5

    1. 栗子3: 一个特征图尺寸为5*5的输入, 使用3*3的卷积核,步幅=2,填充=0
    2. 输出的尺寸=(5-3)/2 + 1 = 2

    1. 栗子4: 一个特征图尺寸为6*6的输入, 使用3*3的卷积核,步幅=2,填充=1
    2. 输出的尺寸=(6 + 2*1 - 3)/2 + 1 = 2.5 + 1 = 3.5 向下取整=3
    3. (降采样:边长减少1/2

          在PyTorch中,卷积层的步幅(stride)也是一个一维张量,通常包含两个或四个元素,具体取决于卷积层的类型(2D或3D卷积)。对于2D卷积层,步幅通常是一个包含两个元素的张量,格式为 [stride_height, stride_width]。对于3D卷积或其他更复杂的层,步幅可能包含四个元素,格式为 [stride_batch, stride_height, stride_width, stride_channel],但这种情况较少见,因为通常不会在批处理维度或通道维度上应用步幅。

    1. import torch.nn as nn
    2. # 定义一个2D卷积层,步幅为(2, 2)
    3. conv_layer = nn.Conv2d(in_channels=3, out_channels=64, kernel_size=3, stride=(2, 2), padding=1)

          在这个例子中,stride=(2, 2) 表示卷积核在高度和宽度方向上每次移动两个像素。这种设置通常用于减少特征图的尺寸,实现下采样。

     2.3 pooling池化

          这个pooling,是为了提取一定区域的主要特征,并减少参数数量,防止模型过拟合。 比如下面的MaxPooling,采用了一个2×2的窗口,并取stride=2:

          

          除了MaxPooling,还有AveragePooling,顾名思义就是取那个区域的平均值。

    2.4 对多通道(channels)图片的卷积

          这个需要单独提一下。彩色图像,一般都是RGB三个通道(channel)的,因此输入数据的维度一般有三个:(长,宽,通道)。 比如一个28×28的RGB图片,维度就是(28,28,3)。

          前面的引子中,输入图片是2维的(8,8),filter是(3,3),输出也是2维的(6,6)。

          如果输入图片是三维的呢(即增多了一个channels),比如是(8,8,3),这个时候,我们的filter的维度就要变成(3,3,3)了,它的最后一维要跟输入的channel维度一致。 这个时候的卷积,是三个channel的所有元素对应相乘后求和,也就是之前是9个乘积的和,现在是27个乘积的和。因此,输出的维度并不会变化。还是(6,6)。

          但是,一般情况下,我们会 使用多个filters同时卷积,比如,如果我们同时使用4个filter的话,那么 输出的维度则会变为(6,6,4)。

         图中的输入图像是(8,8,3),filter有4个,大小均为(3,3,3),得到的输出为(6,6,4)。

    其实,如果套用我们前面学过的神经网络的符号来看待CNN的话,

    • 我们的输入图片就是X,shape=(8,8,3);
    • 4个filters其实就是第一层神金网络的参数W1,shape=(3,3,3,4),这个4是指有4个filters;
    • 我们的输出,就是Z1,shape=(6,6,4);
    • 后面其实还应该有一个激活函数,比如relu,经过激活后,Z1变为A1,shape=(6,6,4);

    所以,在前面的图中,我加一个激活函数,给对应的部分标上符号,就是这样的:

    3、CNN的结构组成

          上面我们已经知道了卷积(convolution)、池化(pooling)以及填白(padding)是怎么进行的,接下来我们就来看看CNN的整体结构,它包含了3种层(layer):

    3.1 卷积层(Convolutional layer, conv)

          由滤波器filters和激活函数构成。 一般要设置的超参数包括filters的数量、大小、步长,以及padding是“valid”还是“same”。当然,还包括选择什么激活函数。

    3.2 Pooling layer(池化层-pool)

         这里里面没有参数需要我们学习,因为这里里面的参数都是我们设置好了,要么是Maxpooling,要么是Averagepooling。 需要指定的超参数,包括是Max还是average,窗口大小以及步长。 通常,我们使用的比较多的是Maxpooling,而且一般取大小为(2,2)步长为2的filter,这样,经过pooling之后,输入的长宽都会缩小2倍,channels不变。

    3.3 Fully Connected layer(全链接层-FC)

          全连接层(Fully Connected Layer),也称为密集层(Dense Layer),是神经网络中的一层,其中每个神经元都与前一层的所有神经元相连接。全连接层通常用于神经网络的最后几层,将学到的特征映射到最终的输出,例如分类任务的类别数。

          在全连接层中,每个神经元都有一组参数(权重和偏置),这些参数用于对输入数据进行线性变换,然后通过激活函数进行非线性变换。全连接层的输出是输入数据和权重矩阵的线性组合,再加上偏置向量。

    参考博客:

    【1】多通道图片的卷积_多通道卷积过程-CSDN博客

    【2】CNN中stride(步幅)和padding(填充)的详细理解_cnn stride-CSDN博客

  • 相关阅读:
    什么是低代码开发,为何大企业都选择低代码来做数字化?
    深度学习之PyTorch实战(4)——迁移学习
    【正点原子STM32连载】第三十七章 触摸屏实验 摘自【正点原子】MiniPro STM32H750 开发指南_V1.1
    Promise实例.then()链式调用,中段Promise链,Promise错误穿透.catch()
    前端生成海报图技术选型与问题解决
    MOS管米勒效应
    一种信息系统免疫安全防护架构
    winapi获取鼠标指向当前元素
    【S1002基于vue+nodejs的学生竞赛报名管理系统-哔哩哔哩】 https://b23.tv/xhyyT9U
    2022.06青少年软件编程(Python)等级考试试卷(四级)
  • 原文地址:https://blog.csdn.net/qq_32867925/article/details/139796082