第六章 视觉处理基础

第六章 视觉处理基础

6.1 卷积神经网络简介

        卷积神经网络由一个或多个卷积层和顶端的全连通层(对应经典的神经网络)组成,同时也包括关联权重和池化层(Pooling Layer)等。图6-1就是一个卷积神经网络架构。

        图6-1为卷积神经网络的一般结构,其中包括卷积神经网络的常用层, 如卷积层、池化层、全连接层和输出层;有些还包括其他层,如正则化层、 高级层等。用代码定义这个卷积神经网络。

 1)导入相关模块

import torch
import torch.nn as nn
import torch.nn.functional as F
import torch.optim as optim
from torchvision import datasets, transforms

 2)定义网络(对于图6-1)

class CNNNet01(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=5,stride=1)
        self.pool2 = nn.MaxPool2d(kernel_size=2, stride=2)
        self.dense1 = nn.Linear(900,128)
        self.dense2 = nn.Linear(128,10)
      

    def forward(self,x):
        x=self.pool1(F.relu(self.conv1(x)))
        x=self.pool2(F.relu(self.conv2(x)))
        x=x.view(-1,900)
        x=F.relu(self.dense2(F.relu(self.dense1(x))))
        return x

6.2 卷积层

        卷积层是卷积神经网络的核心层,而卷积(Convolution)又是卷积层的核心。

        参考:CNN中的卷积和反卷积_HHzdh的博客-CSDN博客

        参考:卷积和反卷积输出的计算公式_HHzdh的博客-CSDN博客_反卷积计算公式

6.2.1 卷积核

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

1)垂直边缘检测。

        这个过滤器是3×3矩阵(注,过滤器一般是奇数阶矩阵),其特点是有值的是第1列和第3列,第2列为0。经过这个过滤器作用后,就把原数据垂直边缘检测出来了,如图6-4所示。

 2)水平边缘检测。

        3×3矩阵,其特点是有值的是第1行和第3行,第2行为 0。经过这个过滤器作用后,就把原数据水平边缘检测出来了。

6.2.2 步幅

        小窗口(实际上就是卷积核或过滤器)在左边窗口中每次移动的格数 (无论是自左向右移动,或自上向下移动)称为步幅(strides),在图像中就是跳过的像素个数。

6.2.3 填充

        当输入图片与卷积核不匹配时或卷积核超过图片边界时,可以采用边界填充(Padding)的方法。即把图片尺寸进行扩展,扩展区域补零,如图6-10所示。当然也可不扩展。

        一般选择Same方式,使用Same不会丢失信息 。

6.2.4 多通道上的卷积 

        3通道图片的卷积运算与单通道图片的卷积运算基本一致,对于3通道的RGB图片,其对应 的滤波器算子同样也是3通道的。例如一个图片是6×6×3,分别表示图片的 高度(Height)、宽度(Weight)和通道(Channel)。过程是将每个单通道 (R,G,B)与对应的filter进行卷积运算求和,然后再将3通道的和相加, 得到输出图片的一个像素值。

6.2.5 激活函数

        卷积神经网络与标准的神经网络类似,为保证其非线性,也需要使用激活函数,即在卷积运算后,把输出值另加偏移量,输入到激活函数,然后作为下一层的输入,如图6-13所示。常用的激活函数有:nn.Sigmoid、nn.ReLU、nnLeakyReLU、nn.Tanh 等。

6.2.6 卷积函数 

Conv2d(in_channels, out_channels, kernel_size, stride=1,padding=0, dilation=1, groups=1,bias=True, padding_mode=‘zeros’)

         五个常用参数的含义如下:

  • in_channels:输入的通道数目;
  • out_channels:输出的通道数目;
  • kernel_size:卷积核的大小;
  • stride:卷积每次滑动的步长;
  • padding:填充,设置在所有边界增加值为 0 的边距的大小。

        卷积神将网络的计算公式:N=(W-F+2P)/S+1,其中N:输出大小,W:输入大小,F:卷积核大小,P:填充值的大小,S:步长大小

 例子:

# batch norm 和leaky relu函数促进了健康的梯度流
class Discriminator(nn.Module):
    def __init__(self, ngpu):
        super(Discriminator, self).__init__()
        self.ngpu = ngpu
        self.main = nn.Sequential(
            # input is (nc) x 64 x 64     128,3*64*64
            nn.Conv2d(nc, ndf, 4, 2, 1, bias=False), # 64-4+2/2+1=32  
            nn.LeakyReLU(0.2, inplace=True),
            # state size. (ndf) x 32 x 32  64*32*32
            
            nn.Conv2d(ndf, ndf * 2, 4, 2, 1, bias=False), # 32-4+2/2+1=16
            nn.BatchNorm2d(ndf * 2),
            nn.LeakyReLU(0.2, inplace=True), 
            # state size. (ndf*2) x 16 x 16  128*16*16
            
            nn.Conv2d(ndf * 2, ndf * 4, 4, 2, 1, bias=False), # 16-4+2/2+1=8
            nn.BatchNorm2d(ndf * 4), # 256
            nn.LeakyReLU(0.2, inplace=True),
            # state size. (ndf*4) x 8 x 8   256*8*8
            
            nn.Conv2d(ndf * 4, ndf * 8, 4, 2, 1, bias=False), # 8-4+2/2+1=4
            nn.BatchNorm2d(ndf * 8),
            nn.LeakyReLU(0.2, inplace=True),
            # state size. (ndf*8) x 4 x 4  512*4*4
            
            nn.Conv2d(ndf * 8, 1, 4, 1, 0, bias=False), # 4-4/2+1=1
            nn.Sigmoid() # 128,1*1024
        )

    def forward(self, input):
        return self.main(input)

 

 一些点:

  • Conv1d:用于文本数据,只对宽度进行卷积,对高度不进行卷积,而Conv2d:用于图像数据,对宽度和高度都进行卷积
  • Conv2d(输入通道数, 输出通道数, kernel_size(长和宽)),当卷积核为方形时,只写一个就可以,但是当卷积核不是方形时,长和宽都要写,如下nn.Conv2d(H,W,....)

6.2.7 转置卷积

        转置卷积(Transposed Convolution)在一些文献中也称为反卷积 (Deconvolution)或部分跨越卷积(Fractionally-Strided Convolution)。转置卷积在生成式对抗网络(GAN)中使用很普遍。

   pytorch中反卷积的函数为:

class torch.nn.ConvTranspose2d(in_channels, out_channels, kernel_size, stride=1, padding=0,output_padding=0,groups=1,bias=True, dilation=1)
# 一般为以下
nn.ConvTranspose2d(in_channels, out_channels, kernel_size, stride, padding)

        参数的含义如下:

  • in_channels(int) – 输入信号的通道数
  • out_channels(int) – 卷积产生的通道数
  • kernel_size(int or tuple) - 卷积核的大小
  • stride(int or tuple,optional) - 卷积步长,即要将输入扩大的倍数。
  • padding(int or tuple, optional) - 输入的每一条边补充0的层数,高宽都增加2*padding
  • output_padding(int or tuple, optional) - 输出边补充0的层数,高宽都增加padding
  • groups(int, optional) – 从输入通道到输出通道的阻塞连接数
  • bias(bool, optional) - 如果bias=True,添加偏置
  • dilation(int or tuple, optional) – 卷积核元素之间的间距

        而对于输入输出的计算,首先参数out_channels指定输出的通道数,即一定是output_size*output_size*out_channels,故主要计算输出的output_size,公式如下:

        outputsize=(inputsize-1)*stride-2*padding+kernelsize+outputpadding

        一般来说用以下公式:

         outputsize=(inputsize-1)*stride-2*padding+kernelsize

 例子:

# Generator Code
# 生成器 反卷积
class Generator(nn.Module):
    def __init__(self, ngpu):
        super(Generator, self).__init__()
        self.ngpu = ngpu  # Number of GPUs available. Use 0 for CPU mode. 可用的 GPUs 数量。
        self.main = nn.Sequential(
            # input is Z, going into a convolution   100维 
            nn.ConvTranspose2d( nz, ngf * 8, 4, 1, 0, bias=False), #(1-1)*1+4-2*0=4  
            nn.BatchNorm2d(ngf * 8),
            nn.ReLU(True),
            # state size. (ngf*8) x 4 x 4   4*4*512
            '''
            class torch.nn.ConvTranspose2d(in_channels, out_channels, kernel_size, stride=1, padding=0, 
                                                       output_padding=0, groups=1, bias=True, dilation=1)
            '''
            
            
            nn.ConvTranspose2d(ngf * 8, ngf * 4, 4, 2, 1, bias=False), # (4-1)*2-2*1+4=8
            nn.BatchNorm2d(ngf * 4),
            nn.ReLU(True),
            # state size. (ngf*4) x 8 x 8   8*8*256
            
            nn.ConvTranspose2d( ngf * 4, ngf * 2, 4, 2, 1, bias=False), # (8-1)*2-2*1+4=16
            nn.BatchNorm2d(ngf * 2),
            nn.ReLU(True),
            # state size. (ngf*2) x 16 x 16  16*16*128
            
            nn.ConvTranspose2d( ngf * 2, ngf, 4, 2, 1, bias=False), # (16-1)*2-2*1+4=32
            nn.BatchNorm2d(ngf),
            nn.ReLU(True),
            # state size. (ngf) x 32 x 32   32*32*64
            
            
            nn.ConvTranspose2d( ngf, nc, 4, 2, 1, bias=False), # (32-1)*2-2*1+4=64
            nn.Tanh()
            # state size. (nc) x 64 x 64   64*64*3
        )

    def forward(self, input):
        return self.main(input)

 6.3 池化层 

        常用的池化 方式通常有3种。

  • 最大池化(Max Pooling):选择Pooling窗口中的最大值作为采样值。
  • 均值池化(Mean Pooling):将Pooling窗口中的所有值相加取平均, 以平均值作为采样值。
  • 全局最大(或均值)池化:与平常最大或最小池化相对而言,全局池化是对整个特征图的池化而不是在移动窗口范围内的池化。

 6.3.1 局部池化

        我们通常使用的最大或平均池化,是在特征图(Feature Map)上以窗口的形式进行滑动(类似卷积的窗口滑动),操作为取窗口内的平均值作为结果,经过操作后,特征图降采样,减少了过拟合现象。其中在移动窗口内的池化被称为局部池化

        最大池化常使用nn.MaxPool2d,平均池化使用 nn.AvgPool2d。

6.3.2 全局池化

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

6.4 现代经典网络

6.4.1 LeNet-5模型

(1)模型架构 LeNet-5模型结构为输入层-卷积层-池化层-卷积层-池化层-全连接层-全连接层-输出,为串联模式,如图6-19所示。

(2)模型特点 ·每个卷积层包含3个部分:卷积、池化和非线性激活函数。

  • 使用卷积提取空间特征。
  • 采用降采样(Subsample)的平均池化层(Average Pooling)。
  • 使用双曲正切(Tanh)的激活函数。
  • 最后用MLP作为分类器。

6.4.2 AlexNet模型

(1)模型架构

        AlexNet为8层深度网络,其中5层卷积层和3层全连接层,不计LRN层和池化层,如图6-20所示。

 (2)模型特点

  • 由5层卷积和3层全连接组成,输入图像为3通道224×224大小,网络规模远大于LeNet。
  • 使用ReLU激活函数。
  • 使用Dropout,可以作为正则项防止过拟合,提升模型鲁棒性。
  • 具备一些很好的训练技巧,包括数据增广、学习率策略、Weight Decay等。

6.4.3 VGG模型

(1)模型结构

 (2)模型特点

  • 更深的网络结构:网络层数由AlexNet的8层增至16和19层,更深的网络意味着更强大的网络能力,也意味着需要更强大的计算力,不过后来硬件发展也很快,显卡运算力也在快速增长,以此助推深度学习的快速发展。
  • 使用较小的3×3的卷积核:模型中使用3×3的卷积核,因为两个3×3的感受野相当于一个5×5,同时参数量更少,之后的网络都基本遵循这个范式。

6.4.4 GoogleNet模型

        VGG是增加网络的深度,但深度达到一个程度时,可能就成为瓶颈。 GoogLeNet则从另一个维度来增加网络能力,每单元有许多层并行计算,让网络更宽了,基本单元如图6-22所示。

 (1)模型结构

        网络总体结构如图6-23所示,包含多个图6-22所示的Inception模块,为便于训练添加了两个辅助分类分支补充梯度,如图6-23所示。

 (2)模型特点

  • 引入Inception结构,这是一种网中网(Network In Network)的结 构。 通过网络的水平排布,可以用较浅的网络得到较好的模型能力,并进行多特征融合,同时更容易训练。另外,为了减少计算量,使用了1×1卷积来 先对特征通道进行降维。堆叠Inception模块就叫作Inception网络,而 GoogLeNet就是一个精心设计的性能良好的Inception网络(Inception v1)的实例,即GoogLeNet是Inception v1网络的一种。
  • 采用全局平均池化层。 将后面的全连接层全部替换为简单的全局平均池化,在最后参数会变得 更少。而在AlexNet中最后3层的全连接层参数差不多占总参数的90%,使用 大网络在宽度和深度上允许GoogleNet移除全连接层,但并不会影响到结果 的精度,在ImageNet中实现93.3%的精度,而且要比VGG还快。不过,网络 太深无法很好训练的问题还是没有得到解决,直到ResNet提出了Residual Connection。

6.4.5 ResNet模型

(1)模型结构

         其完整网络结构如图6-25所示:通过引入残差,Identity恒等映射,相当于一个梯度高速通道,可以更容易地训练避免梯度消失的问题。

 (2)模型特点

  • 层数非常深,已经超过百层。
  • 引入残差单元来解决退化问题。
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值