1.卷积层的概念

  卷积层可以进行特征提取(特别是图像识别邻域),它通过卷积核在输入数据(如图像)上进行滑动,对局部区域进行计算,提取出各种特征,这些特征包含了图像的关键信息,比如边缘、纹理、形状等。通过多个卷积核的协同工作,卷积层可以从不同角度提取图像的特征,为后续的图像识别、分类等任务提供有力支持

2.卷积层核心

1.卷积核

  卷积核,也称为滤波器,它是一个小型的矩阵,是卷积层进行特征提取的核心工具。这个矩阵的大小通常比较小,常见的有3*3、5*5等

  卷积核在工作时,会在输入数据上进行滑动,对每个局部区域进行加权求和运算,每个卷积和都有自己独特的‘偏好’,能够捕捉特定类型的特征

  在卷积神经网络中,卷积核的参数是通过训练学习得到的。在训练过程中,网络会根据大量的训练数据,不断调整卷积核的权值,使得卷积核能够更好地提取出对任务有用的特征。而且,不同的卷积核可以提取不同的特征,通过组合多个卷积核,卷积层就能从多个角度对输入数据进行分析,提取出丰富多样的特征信息

  卷积核还能----权值共享,在卷积运算中,同一个卷积核在输入数据的不同位置上使用相同的权值。也就是说,无论卷积核滑动到图像的哪个区域,它对该区域的加权计算方式都是一样的。这是卷积神经网络的一个重要特性,权值共享大大减少了模型需要学习的参数数量,降低了计算复杂度,同时也提高了模型的泛化能力,使得模型能够更好地适应不同位置的相同特征

2.卷积运算

假设我们有一个 5×5 的输入图像矩阵和一个 3×3 的卷积核矩阵,卷积运算的具体过程如下:​

  1. 首先,将卷积核的左上角与输入图像的左上角对齐,然后将卷积核中的每个元素与对应的输入图像元素相乘,再将这些乘积相加,得到输出特征图的第一个元素​
  2. 接着,将卷积核向右滑动一个单位(步幅为 1,关于步幅后面会详细介绍),重复上述乘法和加法操作,得到输出特征图的下一个元素​
  3. 按照这样的方式,卷积核在输入图像上从左到右、从上到下依次滑动,直到覆盖整个输入图像,从而得到完整的输出特征图

    

左上角对齐的计算: 

 得到输出特征图左上角的元素为 - 8。然后依次滑动卷积核,计算出其他位置的元素,最终得到输出特征图。通过这样的卷积运算,卷积核就能够从输入图像中提取出各种特征,将原始的图像数据转化为更具代表性的特征表示

  3.填充

  随着卷积核的滑动,输出特征图的尺寸会逐渐变小。为了解决这个问题引入了填充的概念

  填充,简单来说,就是在输入数据的边缘添加额外的行和列,使得卷积核在进行运算时能够覆盖到输入数据的边缘部分。常见的填充方式有两种:零填充(Zero Padding)和相同填充(Same Padding)。零填充是指在边缘添加的元素值都为 0;相同填充则是通过计算,使得填充后卷积核在输入数据上滑动得到的输出特征图尺寸与输入数据相同(这里的相同并不是严格意义上的完全一样,可能会有一些微小的差异,具体取决于卷积核大小和步幅等因素)

  填充的作用主要有两个:一是保留边缘信息,让卷积核能够对输入数据的边缘进行充分的计算,避免边缘信息的丢失,这对于一些需要关注图像边缘细节的任务(如边缘检测、目标分割等)非常重要;二是控制输出特征图的尺寸。通过合理设置填充参数,可以调整输出特征图的大小,使其满足后续网络层的输入要求,或者根据任务需求来优化网络的性能

4.步幅

  步幅(Stride)是卷积层中另一个重要的超参数,它决定了卷积核在输入数据上滑动的步长。默认情况下,步幅为 1,即卷积核每次滑动一个单位

  步幅对输出特征图的尺寸和计算量有着直接的影响。当步幅大于 1 时,卷积核在滑动过程中会跳过一些元素,这样输出特征图的尺寸会相应减小。

5.通道

  在卷积层中,通道(Channel)是一个重要的概念,它为我们提供了一个多维的视角来处理数据。通道可以理解为数据的不同维度或特征维度

  对于输入数据,常见的图像数据通常有三个通道,即 RGB 通道,分别表示红色、绿色和蓝色。每个通道包含了图像在相应颜色分量上的信息,通过这三个通道的组合,我们可以呈现出丰富多彩的图像。除了 RGB 图像,在一些特殊的应用场景中,还可能会有更多的通道,比如在医学影像中,可能会有多个通道来表示不同的生理指标或成像模态

  在卷积运算中,每个卷积核都会对输入数据的每一个通道进行卷积操作

  输出通道则是指卷积层输出的特征图的数量。每个输出通道对应一个卷积核,也就是说,卷积层中有多少个卷积核,就会有多少个输出通道。每个卷积核都可以提取出不同的特征,通过多个输出通道,卷积层能够同时提取出多种不同类型的特征,从而丰富了特征表示

  输入通道和输出通道之间通过卷积核建立联系,它们共同决定了卷积层的计算复杂度和特征提取能力。增加输入通道数可以让卷积层获取更多的原始信息,而增加输出通道数则可以使卷积层提取出更丰富多样的特征

3.输出尺寸计算

  在卷积层中,准确计算输出尺寸是至关重要的,它直接关系到后续网络层的输入以及整个模型的结构和性能。对于二维卷积层(nn.Conv2d),输出特征图的高度和宽度可以通过以下公式计算:​

​H(in)和W(in):分别表示输入特征图的高度和宽度;

padding:是填充的大小,即在输入特征图的四周添加的额外像素行数和列数;

dilation:为膨胀系数,它决定了卷积核元素之间的间隔,默认为 1,即卷积核元素紧密相连;

kernel_size:是卷积核的大小;

stride:是步幅,也就是卷积核在输入特征图上每次滑动的步长;

注:结果要向下取整

4.卷积层的PyTorch实现

  在PyTorch中,nn.Conv2d是用于构建二维卷积层的重要模块,它的定义如下:

1.in_channels

  这个参数表示输入数据的通道数

  对于常见的 RGB 图像,其通道数为 3,分别对应红色、绿色和蓝色通道;如果是灰度图像,通道数则为 1。在处理多模态数据或特定领域的数据时,通道数可能会根据数据的特性而有所不同

2.out_channels

  这个参数表示输出数据的通道数,同时也是卷积核的数量

  每一个卷积核都可以看作是一个独特的 “特征探测器”,在对输入数据进行卷积运算后,会生成一个对应的输出通道

3.kernel_size

  这个参数用于指定卷积核的大小(是一个整数,也可以是元组)

  较小的卷积核(如 3×3)可以捕捉到数据中的局部细节信息,同时计算量相对较小,适合提取精细的特征;而较大的卷积核(如 5×5 或 7×7)能够覆盖更大的感受野,获取更全局的特征,但计算量会相应增加,并且可能会丢失一些局部细节

4.stride

  这个参数表示卷积和在输入数据上滑动的步长,默认为1

  步长的大小直接影响输出特征图的尺寸和模型的计算效率。当步长为 1 时,卷积核每次滑动一个单位,能够更细致地对输入数据进行处理,保留更多的细节信息,但计算量相对较大;当步长大于 1 时,卷积核在滑动过程中会跳过一些元素,输出特征图的尺寸会相应减小,计算量也会降低,不过可能会丢失一些细节特征

5.padding

  这个参数表示在数据边缘添加额外的行和列,以控制输出特征图的尺寸和保留边缘信息

  常见的填充方式有零填充(Zero Padding),即添加的元素值都为 0,这也是默认的填充模式(padding_mode='zeros')。填充的大小可以是一个整数,表示在输入数据的四周均匀添加相同数量的填充行和列;也可以是一个元组(pad_h,pad_w),分别表示在高度和宽度方向上的填充数量。当padding=0时,卷积核在边缘部分无法像在中心区域那样完整地进行计算,会导致输出特征图的尺寸减小,同时边缘信息也会有所损失;而通过合理设置填充值,可以使输出特征图的尺寸与输入数据相同(在满足一定条件下),或者根据需要调整输出尺寸,从而更好地保留边缘信息

6.dilation

  这个参数称为卷积核的扩张率,默认为1,它决定了卷积核之间的间隔

  当dilation=1时,卷积核元素紧密相连,进行常规的卷积运算;当dilation>1时,卷积核元素之间会有一定的间隔,这种方式被称为膨胀卷积(Dilated Convolution)。膨胀卷积可以在不增加卷积核大小的情况下扩大感受野,即卷积核能够 “看到” 更大范围的输入数据。

7.groups

  这个参数称为分组卷积,默认为1

  当groups>1时,输入通道会被分为groups组,每组内的卷积操作独立进行,然后将每组的结果拼接起来作为输出。分组卷积可以降低模型的计算复杂度,同时在一定程度上增加模型的泛化能力

8.bias

  这个参数表示是否给每个输出通道添加偏置项,偏置项是一个可学习的参数向量,它可以帮助模型更好地拟合数据,是一个布尔值,默认为True

  在卷积运算中,当bias=True时,在将卷积核与输入数据的局部区域进行点积运算得到的结果上,会加上对应的偏置值,然后再进行后续的处理(如激活函数操作)。偏置项的存在为模型增加了一定的灵活性,使其能够更好地适应不同的数据分布和任务需求

9.padding_mode

  这个参数是指定填充模式,默认为'zeros',零填充

  PyTorch 还支持其他填充模式,如'reflect'(反射填充)和'replicate'(复制填充) 。反射填充是指在填充时,以输入数据边缘的像素值为对称轴,进行镜像反射填充;复制填充则是直接复制输入数据边缘的像素值进行填充

图解:

 

代码:

import torch
import torch.nn as nn
import torchvision
from torch.utils.data import DataLoader
import torchvision.transforms as transforms
from torch.nn import Conv2d
from torch.utils.tensorboard import SummaryWriter

dataset = torchvision.datasets.CIFAR10('./dataset', train=False, transform=torchvision.transforms.ToTensor(), download=False)
dataloader = DataLoader(dataset=dataset, batch_size=64)

class Module(nn.Module):
    def __init__(self):
        super(Module,self).__init__()
        self.conv1 = Conv2d(in_channels=3, out_channels=6, kernel_size=3, stride=1, padding=0)

    def forward(self,x):
        x=self.conv1(x)
        return x

module = Module()
writer = SummaryWriter('../logs')

step = 0
for data in dataloader:
    imgs,targets = data
    output = module(imgs)
    print(imgs.shape)
    print(output.shape)
    writer.add_images('input', imgs, step)
    output = torch.reshape(output, (-1,3,30,30))
    writer.add_images('output', output, step)
    step = step + 1

writer.close()

 结果:

 

Logo

腾讯云面向开发者汇聚海量精品云计算使用和开发经验,营造开放的云计算技术生态圈。

更多推荐