当前位置:   article > 正文

一篇文章弄懂卷积神经网络基础概念_池化下采样 stride

池化下采样 stride

一篇文章弄懂卷积神经网络基础概念

卷积神经网络可以说是图像处理的天花板,也是当下图像处理在深度学习方面最热门的研究。接下来,从卷积核、池化、全连接等方面介绍卷积神经网络中的关键操作。

下采样和上采样

  • 下采样即由输入图像中提取特征。其中有两个作用,一是减少计算量,防止过拟合;二是增大感受野,使得后面的卷积核能够学到更加全局的信息。下采样常用的方式有两种:采用stride为2的池化层和采用stride为2的卷积层(下采样的过程是一个信息损失的过程)。
  • 上采样即将图像恢复到原来的尺寸(使图像由小分辨率映射到大分辨率)。其目的是为了进一步计算(图像补全、图像的语义分割),上采样常用的方式有三种:插值法、转置卷积以及Up-Pooling。

该文章中下采样主要为卷积(普通卷积、空洞卷积、池化)而上采样主要为转置卷积。

卷积

卷积操作的作用是提取图像中的局部信息。卷积核的大小通常比输入数据小,因此每次卷积计算得到的是输入数据的一个小的局部区域的特征。通过不同大小的卷积核和不同的卷积核数量,可以提取出不同尺度和不同方向的特征。
在这里插入图片描述

普通卷积

import torch
import torch.nn as nn
# 定义输入
input_data = torch.tensor([[[
                             [0.1 ,0.2,0.3,0.1,0.1,0.5],
                             [0.2,0.1,0.2,0.3,0.1,0.1],
                             [0.2,0.1,0.2,0.3,0.1,0.1],
                             [0.2,0.1,0.2,0.3,0.1,0.1],
                             [0.2,0.1,0.2,0.3,0.1,0.1],
                             [0.2,0.1,0.2,0.3,0.1,0.1]
                            ]]])
print(input_data)# 查看自定义张量input_data
# 定义标准卷积层
conv = nn.Conv2d(in_channels=1, out_channels=1, kernel_size=3, stride=1, padding=0)
print(conv.state_dict())# 返回一个字典,其中包含了模型的所有参数
# 进行普通卷积操作
conv_result = conv(input_data)
print('Convolution result shape:', conv_result.shape)# 查看卷积操作后的形态
print('Convolution result:', conv_result)# 查看卷积操作后的结果
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19

输出结果

tensor([[[[0.1000, 0.2000, 0.3000, 0.1000, 0.1000, 0.5000],
          [0.2000, 0.1000, 0.2000, 0.3000, 0.1000, 0.1000],
          [0.2000, 0.1000, 0.2000, 0.3000, 0.1000, 0.1000],
          [0.2000, 0.1000, 0.2000, 0.3000, 0.1000, 0.1000],
          [0.2000, 0.1000, 0.2000, 0.3000, 0.1000, 0.1000],
          [0.2000, 0.1000, 0.2000, 0.3000, 0.1000, 0.1000]]]])
OrderedDict([('weight', tensor([[[[-0.3229,  0.2283,  0.2123],
          [ 0.1449, -0.1590,  0.1524],
          [-0.2071, -0.0818,  0.2543]]]])), ('bias', tensor([-0.1603]))])
Convolution result shape: torch.Size([1, 1, 4, 4])
Convolution result: tensor([[[[-0.0384, -0.0675, -0.2571, -0.0657],
          [-0.1148, -0.0156, -0.1792, -0.2152],
          [-0.1148, -0.0156, -0.1792, -0.2152],
          [-0.1148, -0.0156, -0.1792, -0.2152]]]],
       grad_fn=<ConvolutionBackward0>)
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15

空洞卷积

空洞卷积是卷积神经网络中的一种卷积方式,它的作用主要有以下几个方面:

  1. 扩大感受野:在传统卷积操作中,每个卷积核只能获取相邻的像素信息。而空洞卷积通过在卷积核内部增加跳跃的间隔(即空洞大小),可以让卷积核获取更远的像素信息,从而扩大感受野,提高图像识别的准确率。
  2. 减少参数量:在传统卷积操作中,每个卷积核的参数量取决于卷积核大小和通道数。而空洞卷积通过增加卷积核的空洞大小,可以在不增加参数量的情况下扩大感受野。
  3. 保持分辨率:在传统的卷积操作中,通过池化操作可以降低特征图的分辨率,从而减少计算量。而空洞卷积可以在不降低分辨率的情况下扩大感受野,从而保持特征图的分辨率。
  4. 改善边缘信息:在传统卷积操作中,由于卷积核只能获取相邻的像素信息,因此对于边缘信息的提取效果不佳。而空洞卷积通过扩大感受野,可以获取更远的像素信息,从而改善边缘信息的提取效果。

在这里插入图片描述

import torch
import torch.nn as nn
# 定义输入
input_data = torch.tensor([[[
                             [0.1 ,0.2,0.3,0.1,0.1,0.5],
                             [0.2,0.1,0.2,0.3,0.1,0.1],
                             [0.2,0.1,0.2,0.3,0.1,0.1],
                             [0.2,0.1,0.2,0.3,0.1,0.1],
                             [0.2,0.1,0.2,0.3,0.1,0.1],
                             [0.2,0.1,0.2,0.3,0.1,0.1]
                            ]]])
print(input_data)
# 定义标准卷积层和空洞卷积层
conv = nn.Conv2d(in_channels=1, out_channels=1, kernel_size=3, stride=1, padding=0)
print(conv.state_dict())
# 空洞卷积输出结果
dilated_conv = nn.Conv2d(in_channels=1, out_channels=1, kernel_size=3, stride=1, padding=2, dilation=2)
print(dilated_conv.state_dict())# 返回一个字典,其中包含了模型的所有参数
dilated_conv_result = dilated_conv(input_data)
print('Dilated convolution result shape:', dilated_conv_result.shape)# 查看卷积操作后的形态
print('Dilated convolution result:', dilated_conv_result)
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21

输出结果


tensor([[[[0.1000, 0.2000, 0.3000, 0.1000, 0.1000, 0.5000],
          [0.2000, 0.1000, 0.2000, 0.3000, 0.1000, 0.1000],
          [0.2000, 0.1000, 0.2000, 0.3000, 0.1000, 0.1000],
          [0.2000, 0.1000, 0.2000, 0.3000, 0.1000, 0.1000],
          [0.2000, 0.1000, 0.2000, 0.3000, 0.1000, 0.1000],
          [0.2000, 0.1000, 0.2000, 0.3000, 0.1000, 0.1000]]]])
OrderedDict([('weight', tensor([[[[ 0.0818,  0.1001, -0.1972],
          [-0.0940, -0.2605,  0.1210],
          [ 0.1136,  0.2079,  0.0602]]]])), ('bias', tensor([-0.0697]))])
OrderedDict([('weight', tensor([[[[-0.2004, -0.2327, -0.1165],
          [-0.0940,  0.0574, -0.0417],
          [-0.0378, -0.2901,  0.3276]]]])), ('bias', tensor([0.3039]))])
Dilated convolution result shape: torch.Size([1, 1, 6, 6])
Dilated convolution result: tensor([[[[0.3047, 0.3805, 0.2748, 0.2120, 0.2449, 0.2829],
          [0.3146, 0.3664, 0.2596, 0.2495, 0.2543, 0.2411],
          [0.2563, 0.3082, 0.1581, 0.1279, 0.1709, 0.1047],
          [0.2447, 0.3082, 0.1613, 0.1480, 0.1909, 0.1577],
          [0.2372, 0.2389, 0.1941, 0.2060, 0.2275, 0.1980],
          [0.2372, 0.2389, 0.1941, 0.2060, 0.2275, 0.1980]]]],
       grad_fn=<ConvolutionBackward0>)
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21

转置卷积

反卷积(Deconvolution)操作是卷积神经网络(CNN)中的一种常见操作,也称为转置卷积[2](Transposed Convolution)或分数步长卷积(Fractionally Strided Convolution)。在CNN中,卷积操作常用于提取输入图像的特征,反卷积操作则用于将特征图还原为原始图像或进行像素级别的分割。
在这里插入图片描述

import torch
import torch.nn as nn
# 定义输入和卷积核
t = torch.tensor([[
                   [ 0.1 , 0.2 ],
                   [ 0.2 , 0.1 ]]
                 ])
print(type(t),t)
# in_channels表示输入通道数,out_channels表示输出通道数,kernel_size表示卷积核大小
conv_transpose = nn.ConvTranspose2d(in_channels=1, out_channels=1, kernel_size=2, stride=1)
print(conv_transpose.state_dict())# 返回一个字典,其中包含了模型的所有参数
# 输出结果
conv_transpose_result = conv_transpose(t)
print('conv_transpose_result:', conv_transpose_result)
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14

输出结果

<class 'torch.Tensor'> tensor([[[0.1000, 0.2000],
         [0.2000, 0.1000]]])
OrderedDict([('weight', tensor([[[[ 0.1511, -0.4327],
          [ 0.2216,  0.0240]]]])), ('bias', tensor([-0.4246]))])
tensor([[[-0.4095, -0.4377, -0.5112],
         [-0.3722, -0.4493, -0.4631],
         [-0.3803, -0.3976, -0.4222]]], grad_fn=<SqueezeBackward1>)
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7

膨胀卷积和转置卷积的区别

转置卷积和膨胀卷积是两个不同的概念,它们之间的作用和区别如下所述:

  1. 转置卷积是一种反卷积操作,也称为反卷积或上采样(upsampling)操作。它的作用是将输入张量的大小扩大,通常用于图像分割、语义分割、图像生成等任务中。转置卷积的核函数可以看作是卷积核的转置,可以通过反向卷积来实现。在转置卷积中,卷积核的大小和步长是可调的,通过调整这些参数可以控制输出的大小和形状。
  2. 膨胀卷积是一种空洞卷积(dilated convolution)操作,它的作用是在不增加模型参数和计算量的情况下增加卷积层的感受野(receptive field)。膨胀卷积通过在卷积核中间插入一些空洞(dilation)来实现,这些空洞可以增加卷积核的有效大小。在膨胀卷积中,卷积核的大小和步长是固定的,但通过调整膨胀率可以控制卷积核的感受野。
  3. 两者的区别 转置卷积和膨胀卷积都是卷积神经网络中常用的操作,但它们的作用和使用场景是不同的。转置卷积用于对输入张量进行上采样操作,通常用于图像分割、图像生成等任务中。而膨胀卷积用于增加卷积层的感受野,可以提高模型对图像中局部特征的识别能力,通常用于语义分割、物体检测等任务中。此外,转置卷积的核函数大小和步长是可调的,而膨胀卷积的核函数大小和步长是固定的,但可以通过调整膨胀率来控制卷积核的感受野。

感受野:指卷积神经网络中每个输出特征图的每个像素点对应输入图像的区域大小。

池化

池化操作(Pooling)其主要作用是在卷积层之间减少特征图的维度,从而减少模型的参数数量和计算量,避免过拟合。常见的池化操作有最大池化(Max Pooling)和平均池化(Average Pooling)两种。

最大池化

最大池化计算简单而且能够更好的保留纹理特征,得到的图像颜色更亮。

import torch
import torch.nn as nn
# 创建一个最大池化层,池化窗口大小为3x3,步长为1
pool = nn.MaxPool2d(kernel_size=3, stride=1)
print(pool)
# 创建一个输入张量,大小为(1, 1, 4, 4)
x = torch.Tensor([[[
                    [ 1,  2,  3,  4], 
                    [ 5,  6,  7,  8], 
                    [ 9, 10, 11, 12], 
                    [13, 14, 15, 16]
                ]]])
# 将输入张量传递给池化层,并计算输出
output = pool(x)
# 打印输出张量
print(output)
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16

输出结果

MaxPool2d(kernel_size=3, stride=1, padding=0, dilation=1, ceil_mode=False)
tensor([[[[11., 12.],
          [15., 16.]]]])
  • 1
  • 2
  • 3

平均池化

import torch
import torch.nn as nn
# 创建一个最大池化层,池化窗口大小为3x3,步长为1
pool = nn.AvgPool2d(kernel_size=3, stride=1)
print(pool)
# 创建一个输入张量,大小为(1, 1, 4, 4)
x = torch.Tensor([[[
                    [ 1,  2,  3,  4], 
                    [ 5,  6,  7,  8], 
                    [ 9, 10, 11, 12], 
                    [13, 14, 15, 16]
                ]]])
# 将输入张量传递给池化层,并计算输出
output = pool(x)
# 打印输出张量
print(output)
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16

输出结果

AvgPool2d(kernel_size=3, stride=1, padding=0)
tensor([[[[ 6.,  7.],
          [10., 11.]]]])
  • 1
  • 2
  • 3

注:池化层是不可学习的,用stride为2的可学习卷积层来代替pooling可以得到更好的效果,当然同时也增加了一定的计算量。

全连接

全连接层(Fully Connected Layer)是卷积神经网络中的一种常用层,通常位于卷积层和输出层之间。全连接层的作用是将经过卷积层和池化层处理后的特征图进行展平(Flatten),然后连接一个或多个全连接层进行分类或回归。

import torch
import torch.nn as nn
# 创建一个全连接层,输入维度为4,输出维度为2
fc = nn.Linear(4, 2)
print(fc.state_dict())# 返回一个字典,其中包含了模型的所有参数
# 创建一个输入张量,大小为(1, 4)
x = torch.tensor([0.1,0.2,0.2,0.1])
# 将输入张量传递给全连接层,并计算输出
output = fc(x)
# 打印输出张量
print(output)# 第一个:-0.4654×0.1+0.0059 ×0.2+ 0.2813×0.2+0.1×(-0.2186)-0.3949 = -0.40586
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11

输出结果

OrderedDict([('weight', tensor([[-0.4654,  0.0059,  0.2813, -0.2186],
        [ 0.4194,  0.0747,  0.2652,  0.0923]])), ('bias', tensor([-0.3949, -0.1806]))])
tensor([-0.4059, -0.0615], grad_fn=<AddBackward0>)
  • 1
  • 2
  • 3
声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/我家自动化/article/detail/75166
推荐阅读
相关标签
  

闽ICP备14008679号