深度学习卷积神经网络--浅析(一)

一、CNN卷积神经网络

        基于卷积神经⽹络架构的模型在计算机视觉领域中已经占主导地位,当今⼏乎所有的图像识别、⽬标检测或语义分割相关的学术竞赛和商业应⽤都以这种⽅法为基础。本文将简单介绍卷积神经网络和卷积操作,了解卷积神经网络如何一步一步计算结果。   

         上面手写识别可以看到,经过不同的卷积层提取后的一个二维图像数据,每一层的特征图也会不一样,最终将会表示成一个数字结果,实现数字识别的目标

        我们将介绍构成所有卷积⽹络主⼲的基本元素。这包括卷积层(conv2d)本⾝、填充(padding)和步幅(stride)的基本细节、⽤于在相邻区域汇聚信息的汇聚层(pooling)、在每⼀层中多通道(channel)的使⽤,并基于基于pytorch实现。

import torch.nn as nn

#基于torch的卷积层,最大池化层,非线性单元实现
nn.Conv2d(in_channels, out_channels, kernel_size=3, stride=1, padding=1)
nn.MaxPool2d(kernel_size=2, stride=2)
nn.ReLU()

二、卷积层

1、不变性

        首先,对于一个手写数字识别的目标,⽆论哪种⽅法找到这个物体,都应该和数字的位置⽆关。卷积神经⽹络正是将空间不变性(spatial invariance)的这⼀概念系统化,主要包括两个特点:

        (1)平移不变性:不管检测对象出现在图像的哪一个位置,神经网络的浅层应该对识别对象在不同区域都应该具有相似的反应

        (2)局部性:卷积神经网络的浅层应该只观测图像的局部区域,而不过度在意图像中相隔较远的区域

2、卷积

        首先忽略图片的多维度即通道,我们使用一张二维图片表示卷积操作

我们使用一个3*3的二维图片与2*2的卷积核做卷积操作,依次移动卷积核,即可得到一个2*2的卷积输出结果,对于一张m*n的图像,卷积核也是如此运动,当然卷积核的大小,卷积核每次移动的步长都可以定义

3、卷积层

        我们通过一个简单实验展示卷积核的特征提取,使用卷积层寻找图像种的变化位置用来检测图像的边缘:

首先我们需要一张图片,这里使用一张6*8二维矩阵的黑白图像,中间四列用0代替(表示黑色),其余用1表示代表白色

 之后我们使用一个1*2大小的卷积核 【1   -1】与图像实现卷积运算,如果⽔平相邻的两元素相同,则输出为零,否则输出为⾮零

结果显示检测到的垂直边缘,具有非0值

4、训练卷积核

        如果我们只需寻找⿊⽩边缘,那么以上【1    -1 】的垂直边缘检测器⾜以,当我们需要捕捉更加丰富的特征信息,简单的卷积核作为检测器将不满足要求,同时卷积核的数据也未知。那么我们可以通过训练的方式,让深度学习网络自动去拟合所需要的卷积核参数。

         卷积核的参数主要包括两个部分:1、权重 weight,2、 偏置 bias。当前卷积层输入为x,输出为y时,我们可以将卷积操作简单概况为 y = w*x + b,其中w为weight,b为bias。

5、感受野

        对应y每一个子像素结果,当前可能影响到结果的x的所有元素个数作为感受野。

此图卷积核大小为2*2时,结果19的感受野即为前一层的0,1,2,3。感受野大小即为4。当对输出结果再做一次2*2的卷积操作后将网络加深一层,感受野将扩展为输入的3*3最初输入的9个元素,当一个特征图的尺寸需要扩展更广区域,我们可以构建一个更深的网络。

6、填充(padding)和步幅(stride)

        上图输⼊的⾼度和宽度都为3,卷积核的⾼度和宽度都为2,⽣成的输出表征的维数为2。有
时,当卷积核大小大于1时,在应⽤了连续的卷积之后,我们最终得到的输出远小于输⼊大小。卷积的输出形状取决于输⼊形状和卷积核的形状,有时为了保证输入与输出图像大小的一致,则需要填充(padding)和步幅(stride)。原始图像的边界丢失了许多有⽤信息。而填充是解决此问题最有效的⽅法;有时,我们可能希望⼤幅降低图像的宽度和⾼度。例如,如果我们发现原始的输⼊分辨率⼗分冗余。步幅则可以在这类情况下提供帮助。

1.填充(padding)

在输⼊图像的边界填充元素(通常填充元素是0)

 如图我们将3 *3输⼊填充到5 *5(padding=1),那么它的输出就增加为4 *4。卷积神经⽹络中卷积核的⾼度和宽度通常为奇数,例如1、3、5或7。选择奇数的好处是,保持空间维度的同时,我们可以在顶部和底部填充相同数量的⾏,在左侧和右侧填充相同数量的列。此时padding = ( kernel{_{size}}-1)/2

2.步幅(stride)

        卷积窗⼝从输⼊张量的左上⻆开始,向下、向右滑动。有时候为了⾼效计算或是缩减采样次数,卷积窗⼝可以跳过中间位置,每次滑动多个元素。我们将每次卷积核窗口滑动元素的数量称为步幅。当stride=1,即为逐个元素扫描,stride=2,即为隔行隔列扫描。

三、多输入多输出通道

        刚刚我们介绍的都是为通道数channel为1的简单二维图像,但是常常图像都是具有多通道的数据。例如彩色图像具有标准的RGB三通道来代表红、绿和蓝。或者卷积神经网络中的位于深层的卷积层,来自上一层的输入通道数往往很大用于表征高维的特征信息。

1、多输入通道

        当输⼊包含多个通道时,需要构造⼀个与输⼊数据具有相同输⼊通道数的卷积核,以便对多输入通道的数据做卷积运算提取特征。假设输入的通道数为c_{_{i}},那么卷积核的输入通道数也需要c_{_{i}}那么卷积核的大小为c_{_{i}}*k_{_{w}}*k_{_{h}},因此我们可以对每个通道输入的二维数据和卷积核进行卷积操作,然后将结果相加。

 2、多输出通道

        上图虽然具有了多个通道的数据输入,但是输出通道仍然只有一个。为了不断扩展提取特征数量,随着神经网络层数的加深,我们常常会增加输出通道的维度,通过减少空间分辨率以获得更大的通道深度,因此神经网络中间卷积层输出通道常常不为1。

        用c_{i}, c_{o}和表示卷积层的输入和输出通道的数目,为了获得多个通道的输出,我们可以为每个输出通道创建一个c_{_{i}}*k_{_{w}}*k_{_{h}}的卷积核,结果将创建一个c_{_{o}}*c_{_{i}}*k_{_{w}}*k_{_{h}}大小的卷积核。这样,每个输出通道先获取所有输⼊通道,再以对应该输出通道的卷积核计算出结果,即先获得c_{_{i}}*k_{_{w}}*k_{_{h}}的卷积结果,后获得c_{_{o}}*c_{_{i}}*k_{_{w}}*k_{_{h}}的卷积结果。

3、1*1 卷积层

        1* 1卷积层是一个特别的卷积层,即卷积核大小为1*1。因为使⽤了最⼩窗⼝,1*1卷积失去了卷积层的特有能⼒——在⾼度和宽度维度上,识别相邻元素间相互作用的能⼒。其实1*1卷积的计算发⽣在通道上。

        上图展示了3通道输入,2通道输出的卷积计算。

我们可以将1 * 1卷积层看作在每个像素位置应用的全连接层,以c_{_{i}}个输⼊值转换为c_{o}个输出值。因为这仍然是⼀个卷积层,所以跨像素的权重是⼀致的。我们常常使用1*1代替全连接层,作为神经网络的最后一层,可以实现同样的效果,但是运算速度会提示。

4、汇聚层(poolling)

        与卷积层类似,汇聚层运算符由⼀个固定形状的窗⼝组成,该窗⼝根据其步幅大小在输入的所有区域上滑动,为固定形状窗⼝(有时称为汇聚窗口)遍历的每个位置计算⼀个输出。然而,不同于卷积层中的输⼊与卷积核之间的互相关计算,汇聚层不包含参数。相反,池运算是确定性的,我们通常计算汇聚窗⼝中所有元素的最⼤值或平均值。这些操作分别称为最⼤汇聚层(maximum pooling)和平均汇聚层(average pooling)。

最⼤汇聚层(Max pooling)直接上图

通过与卷积窗口类似的滑动操作,如图,在蓝色窗口覆盖内,可以将最大值提取出来即为4 。类似平均汇聚层即为将蓝色窗口覆盖内的数据做平均。

使用pooling操作不会改变通道数,输出与输入通道数将会保持一致,如若改变通道数通过conv卷积操作实现。

        池化操作通常紧跟在卷积层之后,可以应用于卷积层的输出特征图上。它通过在每个池化窗口上执行聚合操作来减小特征图的尺寸,池化操作的主要作用如下:

  1. 特征降维:池化操作通过减小特征图的空间尺寸,降低模型的参数量和计算复杂度。它可以帮助减少过拟合的风险,提高模型的泛化能力。

  2. 保留主要特征:通过对每个池化窗口进行聚合操作(如最大值或平均值),池化操作可以提取出最显著的特征。这有助于保留输入数据中的重要信息,同时降低对细节的敏感性。这种特性使得模型对输入数据的小变化具有一定的鲁棒性。

  3. 平移不变性:池化操作在一定程度上具有平移不变性。即使在输入特征图中进行平移时,池化操作的输出仍然保持不变。这种平移不变性有助于模型学习到与位置无关的特征,从而提高模型的视觉识别能力。

四、非线性单元

        上面我们利用卷积层计算输出,当包含连续两层卷积层,结果可以表示为y_{_{2}} = w_{_{1}}*x+b_{_{1}}y_{_{2}} = w_{_{2}}*y_{_{1}}+b_{_{2}},当我们不断如此加深网络,即不断堆叠卷积层可以获得更好的结果吗,事实是不可以,我们可以简单证明,我们将y_{1}带入第二个公式中可以得到

y_{2} = w_{2} *(w_{1} * x+b_{1}) +b_{2} = w_{2} *w_{1}*x + w_{2}*b_{1}+b_{2}

我们使用w代替w_{2} *w_{1}b代替常数项w_{2}*b_{1}+b_{2}。则又可以表示为

y_{2} = w*x+b

以此类推,不论我如此加深多少网络层数,网络最后都可以表示为一个多项式乘积的形式,这样的模型并不能很好提取高度抽象的特征值,因此为了发挥多层架构的潜⼒,我们还需要⼀个额外的关键要素:在卷积操作之后对每个隐藏单元应用非线性的激活函数(activation function),使得不同层之间分离,就不可能再将我们的卷积神经网络退化成线性模型。下面简单介绍一些激活函数

1、Relu激活函数

    修正线性单元(Rectified linear unit,ReLU),是最常用的激活函数 Relu(x) = max(x,o)

         当输⼊为负时,ReLU函数的导数为0,⽽当输⼊为正时,ReLU函数的导数为1。注意,当输⼊值精确等于0时,ReLU函数不可导。在此时,我们默认使⽤左侧的导数,即当输⼊为0时导数为0。我们可以忽略这种情况,因为输⼊可能永远都不会是0。使⽤ReLU的原因是,它求导表现得特别好:要么让参数消失,要么让参数通过。这使得优化表现得更好,并且ReLU减轻了困扰以往神经⽹络的梯度消失问题。

2、sigmoid函数

        sigmoid可以将一个从负无穷到正无穷的输入变换至区间(0,1)的输出,sigmoid在隐藏层中已经较少使⽤,它在⼤部分时候被更简单、更容易训练的ReLU所取代。sigmoid仍然被⼴泛⽤作输出单元上的激活函数,实用于0-1二值任务。

  • 5
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值