【深度学习】2022-03-21 卷积与池化

4. 神经网络

网络型号:

请添加图片描述

4. 1卷积

4.1.1 概念

卷积是将输入乘以卷积核,然后相加。它可以获得图像的局部特征。因此,卷积核也称为滤波器。

卷积时参数的计算公式:

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-GQusqaHq-1647827095381)(image-20220216185903991.png)]

分类

  • 膨胀卷积(Dilated Convolutions)
  • 引入了膨胀率(dilation rate)。
  • 膨胀率是核中每个值之间的距离。一个膨胀率为2的3×3的核与一个5×5的核有相同的视野,唯一的区别就是3*3的核只有9个参数。
  • 空洞卷积的好处是它以相同的计算成本提供了更宽的视野。空洞卷积在实时分割中非常流行。
  • 当需要比较宽阔的可视域(field of view)同时又没有多卷积或者更大核的条件时,可以采用膨胀卷积。
  • 转置卷积(Transposed Convolutions)
  • 上采样不是卷积的逆运算,也是卷积的一种。
  • 只是将大小恢复到卷积前的大小,但值可能不同。
  • 步:
  • 在输入特征图元素间填充“stride-1`行和列的0
  • 在输入特征图四周填充“kernel_size-padding-1`行和列的0
  • 上下左右翻转卷积核参数
  • 做正常卷积运算(填充0,步距1)
    【深度学习】2022-03-21 卷积与池化

4.1.2 特点

使用卷积的数据下采样和特征提取

  • 卷积运算后输出通道数=卷积核数*卷积核的通道数
  • 卷积核的个数和卷积核的通道数是不同的概念。设计网络时会给出每层卷积核的数量,但可能不会给出卷积核的通道数。
  • 默认情况下,卷积核的通道数=输入的通道数,因为这是卷积运算的必要条件。

4.1.3 PyTorch中的卷积

以二维卷积为例

torch.nn.Conv2d(in_channels, out_channels, kernel_size, stride=1, padding=0, dilation=1, groups=1, bias=True, padding_mode='zeros', device=None, dtype=None)

  • in_channels:输入图像的通道数
  • out_channels:卷积产生的通道数
  • kernel_size:卷积核大小
  • stride:步长,默认1
  • padding:填充的边距,可以是Str{‘valid’, ‘same’}。或者一个元组(2,3),或者一个整数。默认0。
  • dilation:卷积核每个元素之间的间距,默认1。也就是没有间隔
  • groups:从输入通道到输出通道的阻塞连接数。默认值:1
import torch
import torchvision
from torch import nn
from torch.nn import Conv2d
from torch.utils.data import DataLoader
from torch.utils.tensorboard import SummaryWriter
from torchvision import transforms

dataset = torchvision.datasets.CIFAR10("dataset", train=False, transform=transforms.ToTensor(), download=True)
dataLoader = DataLoader(dataset, batch_size=64)


class MyNN(nn.Module):

    def __init__(self) -> None:
        super().__init__()
        # 将二维卷积核定义为变量
        # in_channels: 输入矩阵通道数
        # out_channels: 输出矩阵通道数
        # kernel_size: 卷积核大小
        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


demo_nn = MyNN()
writer = SummaryWriter("nn")

step = 0
for data in dataLoader:
    imgs, target = data
    output = demo_nn(imgs)
    print(imgs.shape)  # torch.Size([64, 3, 32, 32])
    print(output.shape)  # torch.Size([64, 6, 30, 30])

    # 将图像添加到tensorboard中
    writer.add_images("input", imgs, step)
    # 因为输出图像有6个channel,无法进行展示,因此将其转换为3通道
    # 第一个参数:要转换的矩阵
    # 第二个参数:转换后形状,
    #   第一个参数是像素点个数,-1表示不知道有多少个像素,会自动计算,
    #   3是通道数,
    #   30,30是宽和高
    output = torch.reshape(output, (-1, 3, 30, 30))
    print(output.shape)  # torch.Size([128, 3, 30, 30])
    writer.add_images("output", output, step)

    step += 1

writer.close()

4.1.4 卷积示例

输入是5×5,无填充的边缘,3 x 3的卷积核,stride=1。输出大小是3 x 3。
请添加图片描述

更多卷积动画可以看Github演示:Convolution arithmetic

4.2 池化

4.2.1 概念

池化即降采样(subsample),作用是降低输入图片的尺寸,降低数据的大小。

在卷积神经网络中,每个卷积层后面总是跟着一个池化层。

添加池化层的效果是加快计算速度并使某些检测到的特征更强。

池化操作也会用到kernel和步长。

  • 最大池化:Max Pooling(最常用)
  • 平均值池化:Average Pooling

4.2.2 池化的作用

  • 可以减少计算量、内存使用量、参数数量(防止过拟合)
  • 提高神经网络的容错能力(图片平移、位置变化)

请添加图片描述

池化和卷积的异同:

  1. 渠道方面:
  2. 使用池化不会导致数据矩阵的深度发生变化,只会降低高度和带宽,达到降维的目的。前几个通道是池化的,池化后还有几个通道。
  3. 上一层的feature map的个数(也即图层个数)与下一层的卷积核通道数一致。
  4. 卷积对应一个卷积核,池化对应一个池化核。卷积核中有参数,但池化核只是一个没有参数的帧。
  5. 使用方面都需要,定义其大小(size),步长(stride),padding类型。
  6. 卷积里面一般用padding same ;池化里面用padding valid

4.2.3 PyTorch中的池化

torch.nn.MaxPool2d(kernel_size, stride=None, padding=0, dilation=1, return_indices=False, ceil_mode=False)

  • kernel_size– 卷积核大小
  • stride– 步长,默认为卷积核大小
  • padding– 要在两侧添加的隐式零填充
  • dilation– 卷积核每个元素之间的间距,默认1
  • ceil_mode– 向上取整模式,True或者False
import torch
import torchvision.datasets
from torch import nn
from torch.nn import MaxPool2d
from torch.utils.data import DataLoader
from torch.utils.tensorboard import SummaryWriter


class MyNN(nn.Module):

    def __init__(self) -> None:
        super().__init__()
        # MaxPool2d: 最大池化
        # ceil_mode: 向上取整模式,当输入矩阵最后剩余的大小不足kernel_size时,
        # 如果ceil_mode为Ture则保留,否则不保留
        self.max_pool = MaxPool2d(kernel_size=3, stride=1, ceil_mode=True)

    def forward(self, input):
        output = self.max_pool(input)
        return output


dataset = torchvision.datasets.CIFAR10("./dataset", train=False, download=True,
                                       transform=torchvision.transforms.ToTensor())
dataLoader = DataLoader(dataset, batch_size=64)

writer = SummaryWriter("max-pool")
# 后边不写数据类型时默认为Long,会报错 RuntimeError: "max_pool2d" not implemented for 'Long'
input = torch.tensor([[1, 2, 0, 3, 1],
                      [0, 1, 2, 3, 1],
                      [1, 2, 1, 0, 0],
                      [5, 2, 3, 1, 1],
                      [2, 1, 0, 1, 1]], dtype=float)

input = torch.reshape(input, (-1, 1, 5, 5))
print(input.shape)

demo_nn = MyNN()
output = demo_nn(input)
print(output)

step = 0
for data in dataLoader:
    imgs, targets = data
    writer.add_images("max-pool-input", imgs, step)
    output = demo_nn(imgs)
    writer.add_images("max-pool-output", output, step)

    step += 1


writer.close()

文章出处登录后可见!

已经登录?立即刷新

共计人评分,平均

到目前为止还没有投票!成为第一位评论此文章。

(0)
心中带点小风骚的头像心中带点小风骚普通用户
上一篇 2022年3月23日 下午12:00
下一篇 2022年3月23日 下午12:20

相关推荐