• Chapter6视觉处理基础


    6.1 卷积神经网络简介

    在这里插入图片描述

    # 图6-1是用一个比较简单的卷积神经网络对手写输入数据进行分类
    # 由卷积层(conv2d), 池化层(MaxPool2d)和全连接层(Linear)叠加而成
    import torch.nn as nn 
    import torch.nn.functional as F 
    # 这个地方的cuda:0 实际上并不是0号GPU,他取决于CUDA_VISIBLE_DEVICES
    # 然后逻辑GPU和物理GPU有一个对应关系
    # 如果CUDA_VISIBLE_DEVICES为2,1,3
    # 那么CUDA:0就是2号GPU, CUDA:1 就是1号GPU CUDA:3 就是3号GPU
    
    device = torch.device("cuda:0" if torch.cuda.is_available() else "cpu")
    
    class CNNNet(nn.Module):
        def __init__(self):
            super(CNNNet, self).__init__()
            self.conv1 = nn.Conv2d(in_channels=3, out_channels=16,kernel_size=5, stride=1)
            self.pool1 = nn.MaxPool2d(kernel_size=2, stride=2)
            self.conv2 = nn.Conv2d(in_channels=16, out_channels=36, kernel_size=3, stride=1)
            self.pool2 = nn.MaxPool2d(kernel_size=2, stride=2)
            # nn.Linear是一个类,使用时进行类的实例化
            # 实例化的时候,nn.Linear需要输入两个参数,
            # in_features为上一层神经元的个数,out_features为这一层的神经元个数
            self.fc1 = nn.Linear(1296,128)
            self.fc2 = nn.Linear(128,10)
    
        def forward(self, x):
            x = self.pool1(F.relu(self.conv1(x)))
            x = self.pool2(F.relu(self.conv2(x)))
            print(x.shape)
            # 其维度进行随意变化的话,可以使用view()方法,
            # 比如我想将其维度变化成:1*6,则使用方法view(1,6)即可。
            x = x.view(-1, 36*6*6)
            x = F.relu(self.fc2(F.relu(self.fc1(x))))
            return x 
    
    net = CNNNet()
    net = net.to(device)
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37

    6.2 卷积层

    6.2.1 卷积核

    卷积核是整个卷积过程的核心,比较简单的卷积核或过滤器有Horizontalfilter, Verticalfilter, Sobel Filter等,这些过滤器能够检测图像的水平边缘,垂直边缘,增强图像中心区域权重等

    6.6.2步幅

    卷积核的值在移动的过程中都是共享的,卷积神经网络采用参数共享的方法大大降低了参数的数量。
    在这里插入图片描述

    • 假设输入数据大小为n, 过滤器为f*f, 步幅为s,填充为0
      则输出大小为(n-f)/s + 1
      n-f即得到余下有多少个列,除以s即得到还可以移动几次,如果不能整除,则向下取整,然后+1是指加上第一次卷积
    • 假设输入数据大小为n, 过滤器为f*f, 步幅为s,填充为p
      则输出大小为(n+2p-f)/s + 1

    6.2.3 填充

    要进行padding的原因:

    • 图像缩小
    • 和中间图像信息相比,边缘图像信息丢失。padding可以防止图像边缘部分的特征信息丢失
      根据是否拓展Padding又分为Same, Valid.
      采用Same方式时,对图片扩展并补0,(即保证输入和输出大小相同)
      采用Valid方式时,不对图片进行扩展(即no padding)
      在实际训练过程中一般选择Same方式,使用Same不会丢失信息。设补0的圈数为p,输入数据大小为n, 过滤器大小为f, 步幅大小为s,则有:
      在这里插入图片描述
      因为要保证输入n, 输出也为n,而经过填充p后的实际输出为n+2p-f+1
      n = n+2p-f+1 所以p = (f-1)/2
      f 一般为奇数,1.因为如果f是偶数,则填充不对称2.f为奇数,便于指出过滤器的中心位置(虽然用偶数的过滤器也许可以取得较好的结果)

    6.2.4 多通道上的卷积

    彩色图片就3通道,RGB,3通道图片的卷积运算与单通道图片的卷积运算基本一致,对于3通道的RGB图片,其对应的滤波器算子同样也是3通道的。
    在这里插入图片描述
    例如上图是663,表示高度height, 宽度width,通道数 channel。过程是将每个单通道(RGB)与对应的filter进行卷积运算求和,然后再将3通道的和相加,得到输出图片的一个像素值。
    不同滤波器组卷积得到不同的输出,个数由滤波器组决定,图6-11中只有1个滤波器组,所以结果只有一个;如果有2个333的filter,则会得到442的输出

    6.2.5 激活函数

    卷积神经网络与标准的神经网络类似,为保证其非线性,也需要使用激活函数,即在卷积运算后,把输出值另加偏移量,输入到激活函数,然后作为下一层的输入
    在这里插入图片描述
    常见的激活函数为:nn.Sigmoid, nn.ReLU, nn.LeakyReLU, nn.Tanh

    6.2.6 卷积函数

    torch.nn.Conv2d
    在这里插入图片描述
    在这里插入图片描述

    dilation:其默认值为1
    在这里插入图片描述
    在这里插入图片描述 这种情况实际为Pytorch中,dilation = 2的情况。
    特别注意:在Pytorch中,dilation = 1等同于没有dilation的标准卷积。

    参考博客

    6.2.7 转置卷积

    转置卷积(Transposed Convolution)也叫反卷积(Deconvolution)或部分跨越卷积(Fractionally-Strided Convolution)
    通过卷积的正向传播的图像一般越来越小,记为下采样(Downsampled).卷积的方向传播实际上就是一种转置卷积,它是上采样(up-Sampling)
    转置卷积详解1

    B站转置卷积详解
    转置卷积详解2
    在这里插入图片描述

    在这里插入图片描述
    总结:
    转置卷积的作用:上采样
    在这里插入图片描述
    这里不能使用 I = O C − 1 I = OC^{-1} I=OC1,因为不能保证C可逆,可逆只对方阵而言,但并不能保证C是方阵。所以放宽条件:不要求还原卷积前的数据,只要求还原卷积前的大小即可

    torch.nn.ConvTranspose2d(in_channels, out_channels, kernel_size, stride=1, padding=0, output_padding=0, groups=1, bias=True, dilation=1, padding_mode='zeros')
    
    • 1

    6.3 池化层

    池化(Pooling)又称为下采样,通过卷积层获得图像特征后,理论上可以直接使用这些特征训练分类器。但这样计算量太大,且容易产生过拟合现象。
    故要对卷积层进行池化处理,有3中方法:
    1。最大池化Max Pooling:选择Pooling窗口中的最大值作为采样值
    2。均值池化Mean Pooling:将Pooling窗口中的所有值相加取平均,以平均值作为采样值
    3。全局最大(或均值)池化:与平常最大或最小池化相对而言,全局池化是对整个特征图的池化而不是在移动窗口范围内的池化
    在这里插入图片描述
    池化的作用:
    在CNN中可用来减小尺寸,提高运算速度,减小噪声影响,让各特征更具有健壮性。
    池化层比卷积层更简单,它没有卷积运算,只是在滤波器算子滑动区域内取最大值或平均值。
    池化的作用则体现在降采样:保留显著特征,降低特征维度,增大感受野。
    深度网络越往后面越能捕捉到物体的语义信息,这种语义信息是建立在较大的感受野基础上。

    6.3.1 局部池化

    在移动窗口内的池化被称为局部池化
    nn.MaxPool2d
    nn.AvgPool2d -----更常用

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

    6.3.2 全局池化

    全局池化也分为最大或平均池化。
    全局平均池化(Global Average Pooling, GAP),不以窗口的形式取均值,而是以特征图为单位进行均质化,即一个特征图输出一个值

    在这里插入图片描述
    在这里插入图片描述
    使用全局平均池化代替CNN中传统的全连接层。在使用卷积层的识别任务中,全局平均池化能够为每一个特定的类别生成一个特征图(Feature Map)
    GAP的优势在于:

    • 各个类别与Feature Map之间的联系更加直观(相比于全连接层的黑箱来说),Feature Map被转化为分类概率也更加容易,因为在GAP中不用调参,避免了过拟合问题。
    • GAP汇总了空间信息,因此对输入的空间转换鲁棒性更强。所以目前卷积网络中最后几个全连接层,大都用GAP替换
    • 全局最大池化层(GlobalMaxPooling2D)在pytorch中没有对应名称的池化层,但可以使用pytorch中的自适应池化层(AdaptiveMaxPool2d(1)或nn.AdaptiveAvgPool2d(1))来实现

    6.4 现代经典网络

    6.4.1 LeNet-5 模型

    (1)模型架构
    输出层–卷积层–池化层–卷积层–池化层–全连接层–全连接层–输出
    (2)模型特点

    • 每个卷积层包含3部分:卷积,池化,和非线性激活函数
    • 使用卷积提取空间特征
    • 采用降采样(Subsample)的平均池化层(Average Pooling)
    • 使用双曲正切(Tanh)的激活函数
    • 最后使用MLP作为分类器

    Tanh比sigmoid函数晚诞生,sigmoid函数的一个缺点就是输出不以0为中心,使得收敛变慢。
    而tanh则解决了这个问题,它是一个奇函数
    tanh ⁡ ( x ) = sinh ⁡ ( x ) cosh ⁡ ( x ) = e x − e − x e x + e − x \tanh (x)=\frac{\sinh (x)}{\cosh (x)}=\frac{e^{x}-e^{-x}}{e^{x}+e^{-x}} tanh(x)=cosh(x)sinh(x)=ex+exexex
    在这里插入图片描述
    尽管tanh函数和sigmoid函数存在梯度消失的问题,但是与之类似,如果函数的梯度过大又会导致梯度爆炸的问题,显然tanh和sigmoid的导函数非常有界,根据导数公式,很容易得出t a n h ′ ( x ) ∈ [ 0 , 1 ] 所以完全不用担心因为使用激活函数而产生梯度爆炸的问题。

    • LeNet-5论文阅读,博客编写
    • AlexNet论文阅读,博客编写
    • VGG论文阅读,博客编写
    • GoogleNet论文阅读,博客编写
    • ResNet论文阅读,博客编写
    • [ ]
  • 相关阅读:
    (2022版)一套教程搞定k8s安装到实战 | Secret
    Android开发 -- MPAndroidChart动态刷新和清除数据点
    Android 常用布局介绍
    Towhee 每周模型
    硬件管理平台-硬件产品库-硬件项目
    Windows 性能突然打鸡血,靠 Bug 修复了多年顽疾
    CENTURY模型可以模拟土壤呼吸吗?CENTURY模型实践技术应用与案例分析
    HashMap:Java中的高性能键值对存储
    【OpenVINO™】基于 C# 和 OpenVINO™ 部署 Blazeface 模型实现人脸检测
    Centos7 安装 Nginx及启动命令
  • 原文地址:https://blog.csdn.net/weixin_43845922/article/details/126807061