卷积神经网络基础

news2024/9/21 19:19:46

由于篇幅所限,本章将重点介绍计算机视觉的经典模型(卷积神经网络)和两个典型任务(图像分类和目标检测)。主要涵盖如下内容:

卷积神经网络:卷积神经网络(Convolutional Neural Networks, CNN)是计算机视觉技术最经典的模型结构。本教程主要介绍卷积神经网络的常用模块,包括:卷积、池化、激活函数、批归一化、丢弃法等。

  • 图像分类:介绍图像分类算法的经典模型结构,包括:LeNet、AlexNet、VGG、GoogLeNet、ResNet,并通过眼疾筛查的案例展示算法的应用。

  • 目标检测:介绍目标检测YOLOv3算法,并通过林业病虫害检测案例展示YOLOv3算法的应用。

计算机视觉的发展历程

计算机视觉的发展历程要从生物视觉讲起。对于生物视觉的起源,目前学术界尚没有形成定论。有研究者认为最早的生物视觉形成于距今约7亿年前的水母之中,也有研究者认为生物视觉产生于距今约5亿年前寒武纪【1, 2】。寒武纪生物大爆发的原因一直是个未解之谜,不过可以肯定的是在寒武纪动物具有了视觉能力,捕食者可以更容易地发现猎物,被捕食者也可以更早的发现天敌的位置。视觉能力加剧了猎手和猎物之间的博弈,也催生出更加激烈的生存演化规则。视觉系统的形成有力地推动了食物链的演化,加速了生物进化过程,是生物发展史上重要的里程碑。经过几亿年的演化,目前人类的视觉系统已经具备非常高的复杂度和强大的功能,人脑中神经元数目达到了1000亿个,这些神经元通过网络互相连接,这样庞大的视觉神经网络使得我们可以很轻松的观察周围的世界,如 图2 所示。


图2:人类视觉感知

对人类来说,识别猫和狗是件非常容易的事。但对计算机来说,即使是一个精通编程的高手,也很难轻松写出具有通用性的程序(比如:假设程序认为体型大的是狗,体型小的是猫,但由于拍摄角度不同,可能一张图片上猫占据的像素比狗还多)。那么,如何让计算机也能像人一样看懂周围的世界呢?研究者尝试着从不同的角度去解决这个问题,由此也发展出一系列的子任务,如 图3 所示。


图3:计算机视觉子任务示意图

  • (a) Image Classification: 图像分类,用于识别图像中物体的类别(如:bottle、cup、cube)。

  • (b) Object Localization: 目标检测,用于检测图像中每个物体的类别,并准确标出它们的位置。

  • © Semantic Segmentation: 图像语义分割,用于标出图像中每个像素点所属的类别,属于同一类别的像素点用一个颜色标识。

  • (d) Instance Segmentation: 实例分割,值得注意的是,(b)中的目标检测任务只需要标注出物体位置,而(d)中的实例分割任务不仅要标注出物体位置,还需要标注出物体的外形轮廓。

在早期的图像分类任务中,通常是先人工提取图像特征,再用机器学习算法对这些特征进行分类,分类的结果强依赖于特征提取方法,往往只有经验丰富的研究者才能完成,如 图4 所示。


图4:早期的图像分类任务

在这种背景下,基于神经网络的特征提取方法应运而生。Yann LeCun是最早将卷积神经网络应用到图像识别领域的,其主要逻辑是使用卷积神经网络提取图像特征,并对图像所属类别进行预测,通过训练数据不断调整网络参数,最终形成一套能自动提取图像特征并对这些特征进行分类的网络,如 图5 所示。


图5:早期的卷积神经网络处理图像任务示意

这一方法在手写数字识别任务上取得了极大的成功,但在接下来的时间里,却没有得到很好的发展。其主要原因一方面是数据集不完善,只能处理简单任务,在大尺寸的数据上容易发生过拟合;另一方面是硬件瓶颈,网络模型复杂时,计算速度会特别慢。

目前,随着互联网技术的不断进步,数据量呈现大规模的增长,越来越丰富的数据集不断涌现。另外,得益于硬件能力的提升,计算机的算力也越来越强大。不断有研究者将新的模型和算法应用到计算机视觉领域。由此催生了越来越丰富的模型结构和更加准确的精度,同时计算机视觉所处理的问题也越来越丰富,包括分类、检测、分割、场景描述、图像生成和风格变换等,甚至还不仅仅局限于2维图片,包括视频处理技术和3D视觉等。

卷积神经网络

卷积神经网络是目前计算机视觉中使用最普遍的模型结构。本章节主要向读者介绍卷积神经网络的一些基础模块,包括:

  • 卷积(Convolution)
  • 池化(Pooling)
  • ReLU激活函数
  • 批归一化(Batch Normalization)
  • 丢弃法(Dropout)

回顾一下,手写数字识别任务,应用的是全连接网络进行特征提取,即将一张图片上的所有像素点展开成一个1维向量输入网络,存在如下两个问题:

1. 输入数据的空间信息被丢失。 空间上相邻的像素点往往具有相似的RGB值,RGB的各个通道之间的数据通常密切相关,但是转化成1维向量时,这些信息被丢失。同时,图像数据的形状信息中,可能隐藏着某种本质的模式,但是转变成1维向量输入全连接神经网络时,这些模式也会被忽略。

2. 模型参数过多,容易发生过拟合。 在手写数字识别案例中,每个像素点都要跟所有输出的神经元相连接。当图片尺寸变大时,输入神经元的个数会按图片尺寸的平方增大,导致模型参数过多,容易发生过拟合。

为了解决上述问题,我们引入卷积神经网络进行特征提取,既能提取到相邻像素点之间的特征模式,又能保证参数的个数不随图片尺寸变化。图6 是一个典型的卷积神经网络结构,多层卷积和池化层组合作用在输入图片上,在网络的最后通常会加入一系列全连接层,ReLU激活函数一般加在卷积或者全连接层的输出上,网络中通常还会加入Dropout来防止过拟合。



图6:卷积神经网络经典结构


说明:

在卷积神经网络中,计算范围是在像素点的空间邻域内进行的,卷积核参数的数目也远小于全连接层。卷积核本身与输入图片大小无关,它代表了对空间邻域内某种特征模式的提取。比如,有些卷积核提取物体边缘特征,有些卷积核提取物体拐角处的特征,图像上不同区域共享同一个卷积核。当输入图片大小不一样时,仍然可以使用同一个卷积核进行操作。


卷积(Convolution)

这一小节将为读者介绍卷积算法的原理和实现方案,并通过具体的案例展示如何使用卷积对图片进行操作,主要涵盖如下内容:

  • 卷积计算

  • 填充(padding)

  • 步幅(stride)

  • 感受野(Receptive Field)

  • 多输入通道、多输出通道和批量操作

  • 卷积算子应用举例

卷积计算

卷积是数学分析中的一种积分变换的方法,在图像处理中采用的是卷积的离散形式。这里需要说明的是,在卷积神经网络中,卷积层的实现方式实际上是数学中定义的互相关 (cross-correlation)运算,与数学分析中的卷积定义有所不同,这里跟其他框架和卷积神经网络的教程保持一致,都使用互相关运算作为卷积的定义,具体的计算过程如 图7 所示。



图7:卷积计算过程


说明:

卷积核(kernel)也被叫做滤波器(filter),假设卷积核的高和宽分别为 k h k_h kh k w k_w kw,则将称为 k h × k w k_h\times k_w kh×kw卷积,比如 3 × 5 3\times5 3×5卷积,就是指卷积核的高为3, 宽为5。


  • 如图7(a)所示:左边的图大小是 3 × 3 3\times3 3×3,表示输入数据是一个维度为 3 × 3 3\times3 3×3的二维数组;中间的图大小是 2 × 2 2\times2 2×2,表示一个维度为 2 × 2 2\times2 2×2的二维数组,我们将这个二维数组称为卷积核。先将卷积核的左上角与输入数据的左上角(即:输入数据的(0, 0)位置)对齐,把卷积核的每个元素跟其位置对应的输入数据中的元素相乘,再把所有乘积相加,得到卷积输出的第一个结果:

0 × 1 + 1 × 2 + 2 × 4 + 3 × 5 = 25         ( a ) 0\times1 + 1\times2 + 2\times4 + 3\times5 = 25 \ \ \ \ \ \ \ (a) 0×1+1×2+2×4+3×5=25       (a)

  • 如图7(b)所示:将卷积核向右滑动,让卷积核左上角与输入数据中的(0,1)位置对齐,同样将卷积核的每个元素跟其位置对应的输入数据中的元素相乘,再把这4个乘积相加,得到卷积输出的第二个结果:

0 × 2 + 1 × 3 + 2 × 5 + 3 × 6 = 31         ( b ) 0\times2 + 1\times3 + 2\times5 + 3\times6 = 31 \ \ \ \ \ \ \ (b) 0×2+1×3+2×5+3×6=31       (b)

  • 如图7(c)所示:将卷积核向下滑动,让卷积核左上角与输入数据中的(1, 0)位置对齐,可以计算得到卷积输出的第三个结果:

0 × 4 + 1 × 5 + 2 × 7 + 3 × 8 = 43         ( c ) 0\times4 + 1\times5 + 2\times7 + 3\times8 = 43 \ \ \ \ \ \ \ (c) 0×4+1×5+2×7+3×8=43       (c)

  • 如图7(d)所示:将卷积核向右滑动,让卷积核左上角与输入数据中的(1, 1)位置对齐,可以计算得到卷积输出的第四个结果:

0 × 5 + 1 × 6 + 2 × 8 + 3 × 9 = 49         ( d ) 0\times5 + 1\times6 + 2\times8 + 3\times9 = 49 \ \ \ \ \ \ \ (d) 0×5+1×6+2×8+3×9=49       (d)

卷积核的计算过程可以用下面的数学公式表示,其中 a a a 代表输入图片, b b b 代表输出特征图, w w w 是卷积核参数,它们都是二维数组, ∑ u , v   \sum{u,v}{\ } u,v  表示对卷积核参数进行遍历并求和。

b [ i , j ] = ∑ u , v a [ i + u , j + v ] ⋅ w [ u , v ] b[i, j] = \sum_{u,v}{a[i+u, j+v]\cdot w[u, v]} b[i,j]=u,va[i+u,j+v]w[u,v]

举例说明,假如上图中卷积核大小是 2 × 2 2\times 2 2×2,则 u u u可以取0和1, v v v也可以取0和1,也就是说:
b [ i , j ] = a [ i + 0 , j + 0 ] ⋅ w [ 0 , 0 ] + a [ i + 0 , j + 1 ] ⋅ w [ 0 , 1 ] + a [ i + 1 , j + 0 ] ⋅ w [ 1 , 0 ] + a [ i + 1 , j + 1 ] ⋅ w [ 1 , 1 ] b[i, j] = a[i+0, j+0]\cdot w[0, 0] + a[i+0, j+1]\cdot w[0, 1] + a[i+1, j+0]\cdot w[1, 0] + a[i+1, j+1]\cdot w[1, 1] b[i,j]=a[i+0,j+0]w[0,0]+a[i+0,j+1]w[0,1]+a[i+1,j+0]w[1,0]+a[i+1,j+1]w[1,1]

可以自行验证,当 [ i , j ] [i, j] [i,j]取不同值时,根据此公式计算的结果与上图中的例子是否一致。

其它说明:

在卷积神经网络中,一个卷积算子除了上面描述的卷积过程之外,还包括加上偏置项的操作。例如假设偏置为1,则上面卷积计算的结果为:

0 × 1 + 1 × 2 + 2 × 4 + 3 × 5   + 1 = 26 0\times1 + 1\times2 + 2\times4 + 3\times5 \mathbf{\ + 1} = 26 0×1+1×2+2×4+3×5 +1=26
0 × 2 + 1 × 3 + 2 × 5 + 3 × 6   + 1 = 32 0\times2 + 1\times3 + 2\times5 + 3\times6 \mathbf{\ + 1} = 32 0×2+1×3+2×5+3×6 +1=32
0 × 4 + 1 × 5 + 2 × 7 + 3 × 8   + 1 = 44 0\times4 + 1\times5 + 2\times7 + 3\times8 \mathbf{\ + 1} = 44 0×4+1×5+2×7+3×8 +1=44
0 × 5 + 1 × 6 + 2 × 8 + 3 × 9   + 1 = 50 0\times5 + 1\times6 + 2\times8 + 3\times9 \mathbf{\ + 1} = 50 0×5+1×6+2×8+3×9 +1=50


填充(padding)

在上面的例子中,输入图片尺寸为 3 × 3 3\times3 3×3,输出图片尺寸为 2 × 2 2\times2 2×2,经过一次卷积之后,图片尺寸变小。卷积输出特征图的尺寸计算方法如下(卷积核的高和宽分别为 k h k_h kh k w k_w kw):

H o u t = H − k h + 1 H_{out} = H - k_h + 1 Hout=Hkh+1
W o u t = W − k w + 1 W_{out} = W - k_w + 1 Wout=Wkw+1

如果输入尺寸为4,卷积核大小为3时,输出尺寸为 4 − 3 + 1 = 2 4-3+1=2 43+1=2。读者可以自行检查当输入图片和卷积核为其他尺寸时,上述计算式是否成立。当卷积核尺寸大于1时,输出特征图的尺寸会小于输入图片尺寸。如果经过多次卷积,输出图片尺寸会不断减小。为了避免卷积之后图片尺寸变小,通常会在图片的外围进行填充(padding),如 图8 所示。


图8:图形填充

  • 如图8(a)所示:填充的大小为1,填充值为0。填充之后,输入图片尺寸从 4 × 4 4\times4 4×4变成了 6 × 6 6\times6 6×6,使用 3 × 3 3\times3 3×3的卷积核,输出图片尺寸为 4 × 4 4\times4 4×4

  • 如图8(b)所示:填充的大小为2,填充值为0。填充之后,输入图片尺寸从 4 × 4 4\times4 4×4变成了 8 × 8 8\times8 8×8,使用 3 × 3 3\times3 3×3的卷积核,输出图片尺寸为 6 × 6 6\times6 6×6

如果在图片高度方向,在第一行之前填充 p h 1 p_{h1} ph1行,在最后一行之后填充 p h 2 p_{h2} ph2行;在图片的宽度方向,在第1列之前填充 p w 1 p_{w1} pw1列,在最后1列之后填充 p w 2 p_{w2} pw2列;则填充之后的图片尺寸为 ( H + p h 1 + p h 2 ) × ( W + p w 1 + p w 2 ) (H + p_{h1} + p_{h2})\times(W + p_{w1} + p_{w2}) (H+ph1+ph2)×(W+pw1+pw2)。经过大小为 k h × k w k_h\times k_w kh×kw的卷积核操作之后,输出图片的尺寸为:
H o u t = H + p h 1 + p h 2 − k h + 1 H_{out} = H + p_{h1} + p_{h2} - k_h + 1 Hout=H+ph1+ph2kh+1
W o u t = W + p w 1 + p w 2 − k w + 1 W_{out} = W + p_{w1} + p_{w2} - k_w + 1 Wout=W+pw1+pw2kw+1

在卷积计算过程中,通常会在高度或者宽度的两侧采取等量填充,即 p h 1 = p h 2 = p h ,    p w 1 = p w 2 = p w p_{h1} = p_{h2} = p_h,\ \ p_{w1} = p_{w2} = p_w ph1=ph2=ph,  pw1=pw2=pw,上面计算公式也就变为:
H o u t = H + 2 p h − k h + 1 H_{out} = H + 2p_h - k_h + 1 Hout=H+2phkh+1
W o u t = W + 2 p w − k w + 1 W_{out} = W + 2p_w - k_w + 1 Wout=W+2pwkw+1
卷积核大小通常使用1,3,5,7这样的奇数,如果使用的填充大小为 p h = ( k h − 1 ) / 2 , p w = ( k w − 1 ) / 2 p_h=(k_h-1)/2 ,p_w=(k_w-1)/2 ph=(kh1)/2pw=(kw1)/2,则卷积之后图像尺寸不变。例如当卷积核大小为3时,padding大小为1,卷积之后图像尺寸不变;同理,如果卷积核大小为5,padding大小为2,也能保持图像尺寸不变。

步幅(stride)

图8 中卷积核每次滑动一个像素点,这是步幅为1的特殊情况。图9 是步幅为2的卷积过程,卷积核在图片上移动时,每次移动大小为2个像素点。


图9:步幅为2的卷积过程

当宽和高方向的步幅分别为 s h s_h sh s w s_w sw时,输出特征图尺寸的计算公式是:

H o u t = H + 2 p h − k h s h + 1 H_{out} = \frac{H + 2p_h - k_h}{s_h} + 1 Hout=shH+2phkh+1

W o u t = W + 2 p w − k w s w + 1 W_{out} = \frac{W + 2p_w - k_w}{s_w} + 1 Wout=swW+2pwkw+1

假设输入图片尺寸是 H × W = 100 × 100 H\times W = 100 \times 100 H×W=100×100,卷积核大小 k h × k w = 3 × 3 k_h \times k_w = 3 \times 3 kh×kw=3×3,填充 p h = p w = 1 p_h = p_w = 1 ph=pw=1,步幅为 s h = s w = 2 s_h = s_w = 2 sh=sw=2,则输出特征图的尺寸为:

H o u t = 100 + 2 − 3 2 + 1 = 50 H_{out} = \frac{100 + 2 - 3}{2} + 1 = 50 Hout=2100+23+1=50

W o u t = 100 + 2 − 3 2 + 1 = 50 W_{out} = \frac{100 + 2 - 3}{2} + 1 = 50 Wout=2100+23+1=50

感受野(Receptive Field)

输出特征图上每个点的数值,是由输入图片上大小为 k h × k w k_h\times k_w kh×kw的区域的元素与卷积核每个元素相乘再相加得到的,所以输入图像上 k h × k w k_h\times k_w kh×kw区域内每个元素数值的改变,都会影响输出点的像素值。我们将这个区域叫做输出特征图上对应点的感受野。感受野内每个元素数值的变动,都会影响输出点的数值变化。比如 3 × 3 3\times3 3×3卷积对应的感受野大小就是 3 × 3 3\times3 3×3,如 图10 所示。



图10:感受野为3×3的卷积

而当通过两层 3 × 3 3\times3 3×3的卷积之后,感受野的大小将会增加到 5 × 5 5\times5 5×5,如 图11 所示。



图11:感受野为5×5的卷积

因此,当增加卷积网络深度的同时,感受野将会增大,输出特征图中的一个像素点将会包含更多的图像语义信息。

多输入通道、多输出通道和批量操作

前面介绍的卷积计算过程比较简单,实际应用时,处理的问题要复杂的多。例如:对于彩色图片有RGB三个通道,需要处理多输入通道的场景。输出特征图往往也会具有多个通道,而且在神经网络的计算中常常是把一个批次的样本放在一起计算,所以卷积算子需要具有批量处理多输入和多输出通道数据的功能,下面将分别介绍这几种场景的操作方式。

  • 多输入通道场景

上面的例子中,卷积层的数据是一个2维数组,但实际上一张图片往往含有RGB三个通道,要计算卷积的输出结果,卷积核的形式也会发生变化。假设输入图片的通道数为 C i n C_{in} Cin,输入数据的形状是 C i n × H i n × W i n C_{in}\times{H_{in}}\times{W_{in}} Cin×Hin×Win,计算过程如 图12 所示。

  1. 对每个通道分别设计一个2维数组作为卷积核,卷积核数组的形状是 C i n × k h × k w C_{in}\times{k_h}\times{k_w} Cin×kh×kw

  2. 对任一通道 C i n ∈ [ 0 , C i n ) C_{in} \in [0, C_{in}) Cin[0,Cin),分别用大小为 k h × k w k_h\times{k_w} kh×kw的卷积核在大小为 H i n × W i n H_{in}\times{W_{in}} Hin×Win的二维数组上做卷积。

  3. 将这 C i n C_{in} Cin个通道的计算结果相加,得到的是一个形状为 H o u t × W o u t H_{out}\times{W_{out}} Hout×Wout的二维数组。


图12:多输入通道计算过程

- **多输出通道场景**

一般来说,卷积操作的输出特征图也会具有多个通道 C o u t C_{out} Cout,这时我们需要设计 C o u t C_{out} Cout个维度为 C i n × k h × k w C_{in}\times{k_h}\times{k_w} Cin×kh×kw的卷积核,卷积核数组的维度是 C o u t × C i n × k h × k w C_{out}\times C_{in}\times{k_h}\times{k_w} Cout×Cin×kh×kw,如 图13 所示。

  1. 对任一输出通道 c o u t ∈ [ 0 , C o u t ) c_{out} \in [0, C_{out}) cout[0,Cout),分别使用上面描述的形状为 C i n × k h × k w C_{in}\times{k_h}\times{k_w} Cin×kh×kw的卷积核对输入图片做卷积。
  2. 将这 C o u t C_{out} Cout个形状为 H o u t × W o u t H_{out}\times{W_{out}} Hout×Wout的二维数组拼接在一起,形成维度为 C o u t × H o u t × W o u t C_{out}\times{H_{out}}\times{W_{out}} Cout×Hout×Wout的三维数组。

说明:

通常将卷积核的输出通道数叫做卷积核的个数。



图13:多输出通道计算过程

  • 批量操作

在卷积神经网络的计算中,通常将多个样本放在一起形成一个mini-batch进行批量操作,即输入数据的维度是 N × C i n × H i n × W i n N\times{C_{in}}\times{H_{in}}\times{W_{in}} N×Cin×Hin×Win。由于会对每张图片使用同样的卷积核进行卷积操作,卷积核的维度与上面多输出通道的情况一样,仍然是 C o u t × C i n × k h × k w C_{out}\times C_{in}\times{k_h}\times{k_w} Cout×Cin×kh×kw,输出特征图的维度是 N × C o u t × H o u t × W o u t N\times{C_{out}}\times{H_{out}}\times{W_{out}} N×Cout×Hout×Wout,如 图14 所示。



图14:批量操作

池化(Pooling)

池化是使用某一位置的相邻输出的总体统计特征代替网络在该位置的输出,其好处是当输入数据做出少量平移时,经过池化函数后的大多数输出还能保持不变。比如:当识别一张图像是否是人脸时,我们需要知道人脸左边有一只眼睛,右边也有一只眼睛,而不需要知道眼睛的精确位置,这时候通过池化某一片区域的像素点来得到总体统计特征会显得很有用。由于池化之后特征图会变得更小,如果后面连接的是全连接层,能有效的减小神经元的个数,节省存储空间并提高计算效率。
图15 所示,将一个 2 × 2 2\times 2 2×2的区域池化成一个像素点。通常有两种方法,平均池化和最大池化。


图15:池化

  • 如图15(a):平均池化。这里使用大小为 2 × 2 2\times2 2×2的池化窗口,每次移动的步幅为2,对池化窗口覆盖区域内的像素取平均值,得到相应的输出特征图的像素值。
  • 如图15(b):最大池化。对池化窗口覆盖区域内的像素取最大值,得到输出特征图的像素值。当池化窗口在图片上滑动时,会得到整张输出特征图。池化窗口的大小称为池化大小,用 k h × k w k_h \times k_w kh×kw表示。在卷积神经网络中用的比较多的是窗口大小为 2 × 2 2 \times 2 2×2,步幅为2的池化。

与卷积核类似,池化窗口在图片上滑动时,每次移动的步长称为步幅,当宽和高方向的移动大小不一样时,分别用 s w s_w sw s h s_h sh表示。也可以对需要进行池化的图片进行填充,填充方式与卷积类似,假设在第一行之前填充 p h 1 p_{h1} ph1行,在最后一行后面填充 p h 2 p_{h2} ph2行。在第一列之前填充 p w 1 p_{w1} pw1列,在最后一列之后填充 p w 2 p_{w2} pw2列,则池化层的输出特征图大小为:

H o u t = H + p h 1 + p h 2 − k h s h + 1 H_{out} = \frac{H + p_{h1} + p_{h2} - k_h}{s_h} + 1 Hout=shH+ph1+ph2kh+1

W o u t = W + p w 1 + p w 2 − k w s w + 1 W_{out} = \frac{W + p_{w1} + p_{w2} - k_w}{s_w} + 1 Wout=swW+pw1+pw2kw+1

在卷积神经网络中,通常使用 2 × 2 2\times2 2×2大小的池化窗口,步幅也使用2,填充为0,则输出特征图的尺寸为:

H o u t = H 2 H_{out} = \frac{H}{2} Hout=2H

W o u t = W 2 W_{out} = \frac{W}{2} Wout=2W

通过这种方式的池化,输出特征图的高和宽都减半,但通道数不会改变。

ReLU激活函数

前面介绍的网络结构中,普遍使用Sigmoid函数做激活函数。在神经网络发展的早期,Sigmoid函数用的比较多,而目前用的较多的激活函数是ReLU。这是因为Sigmoid函数在反向传播过程中,容易造成梯度的衰减。让我们仔细观察Sigmoid函数的形式,就能发现这一问题。

Sigmoid激活函数定义如下:

y = 1 1 + e − x y = \frac{1}{1 + e^{-x}} y=1+ex1

ReLU激活函数的定义如下:

y = { 0 , ( x < 0 ) x , ( x ≥ 0 ) y=\left\{ \begin{aligned} 0 & , & (x<0) \\ x & , & (x\ge 0) \end{aligned} \right. y={0x,,(x<0)(x0)

下面的程序画出了Sigmoid和ReLU函数的曲线图:

# ReLU和Sigmoid激活函数示意图
import numpy as np
import matplotlib.pyplot as plt
import matplotlib.patches as patches
plt.figure(figsize=(10, 5))

# 创建数据x
x = np.arange(-10, 10, 0.1)

# 计算Sigmoid函数
s = 1.0 / (1 + np.exp(0. - x))

# 计算ReLU函数
y = np.clip(x, a_min=0., a_max=None)

#####################################
# 以下部分为画图代码
f = plt.subplot(121)
plt.plot(x, s, color='r')
currentAxis=plt.gca()
plt.text(-9.0, 0.9, r'$y=Sigmoid(x)$', fontsize=13)
currentAxis.xaxis.set_label_text('x', fontsize=15)
currentAxis.yaxis.set_label_text('y', fontsize=15)

f = plt.subplot(122)
plt.plot(x, y, color='g')
plt.text(-3.0, 9, r'$y=ReLU(x)$', fontsize=13)
currentAxis=plt.gca()
currentAxis.xaxis.set_label_text('x', fontsize=15)
currentAxis.yaxis.set_label_text('y', fontsize=15)

plt.show()

在这里插入图片描述
梯度消失现象

在神经网络里,将经过反向传播之后,梯度值衰减到接近于零的现象称作梯度消失现象。

从上面的函数曲线可以看出,当 x x x为较大的正数的时候,Sigmoid函数数值非常接近于1,函数曲线变得很平滑,在这些区域Sigmoid函数的导数接近于零。当 x x x为较小的负数时,Sigmoid函数值也非常接近于0,函数曲线也很平滑,在这些区域Sigmoid函数的导数也接近于0。只有当 x x x的取值在0附近时,Sigmoid函数的导数才比较大。对Sigmoid函数求导数,结果如下所示:

d y d x = − 1 ( 1 + e − x ) 2 ⋅ d ( e − x ) d x = 1 2 + e x + e − x \frac{dy}{dx} = -\frac{1}{(1+e^{-x})^2} \cdot \frac{d(e^{-x})}{dx} = \frac{1}{2 + e^x + e^{-x}} dxdy=(1+ex)21dxd(ex)=2+ex+ex1

从上面的式子可以看出,Sigmoid函数的导数 d y d x \frac{dy}{dx} dxdy最大值为 1 4 \frac{1}{4} 41。前向传播时, y = S i g m o i d ( x ) y=Sigmoid(x) y=Sigmoid(x);而在反向传播过程中, x x x的梯度等于 y y y的梯度乘以Sigmoid函数的导数,如下所示:

∂ L ∂ x = ∂ L ∂ y ⋅ ∂ y ∂ x \frac{\partial{L}}{\partial{x}} = \frac{\partial{L}}{\partial{y}} \cdot \frac{\partial{y}}{\partial{x}} xL=yLxy

使得 x x x的梯度数值最大也不会超过 y y y的梯度的 1 4 \frac{1}{4} 41

由于最开始是将神经网络的参数随机初始化的, x x x的取值很有可能在很大或者很小的区域,这些地方都可能造成Sigmoid函数的导数接近于0,导致 x x x的梯度接近于0;即使 x x x取值在接近于0的地方,按上面的分析,经过Sigmoid函数反向传播之后, x x x的梯度不超过 y y y的梯度的 1 4 \frac{1}{4} 41,如果有多层网络使用了Sigmoid激活函数,则比较靠后的那些层梯度将衰减到非常小的值。

ReLU函数则不同,虽然在 x < 0 x\lt 0 x<0的地方,ReLU函数的导数为0。但是在 x ≥ 0 x\ge 0 x0的地方,ReLU函数的导数为1,能够将 y y y的梯度完整的传递给 x x x,而不会引起梯度消失。

批归一化(Batch Normalization)

批归一化方法(Batch Normalization,BatchNorm)是由Ioffe和Szegedy于2015年提出的,已被广泛应用在深度学习中,其目的是对神经网络中间层的输出进行标准化处理,使得中间层的输出更加稳定。

通常我们会对神经网络的数据进行标准化处理,处理后的样本数据集满足均值为0,方差为1的统计分布,这是因为当输入数据的分布比较固定时,有利于算法的稳定和收敛。对于深度神经网络来说,由于参数是不断更新的,即使输入数据已经做过标准化处理,但是对于比较靠后的那些层,其接收到的输入仍然是剧烈变化的,通常会导致数值不稳定,模型很难收敛。BatchNorm能够使神经网络中间层的输出变得更加稳定,并有如下三个优点:

  • 使学习快速进行(能够使用较大的学习率)

  • 降低模型对初始值的敏感性

  • 从一定程度上抑制过拟合

BatchNorm主要思路是在训练时以mini-batch为单位,对神经元的数值进行归一化,使数据的分布满足均值为0,方差为1。具体计算过程如下:

1. 计算mini-batch内样本的均值

μ B ← 1 m ∑ i = 1 m x ( i ) \mu_B \leftarrow \frac{1}{m}\sum_{i=1}^mx^{(i)} μBm1i=1mx(i)

其中 x ( i ) x^{(i)} x(i)表示mini-batch中的第 i i i个样本。

例如输入mini-batch包含3个样本,每个样本有2个特征,分别是:

x ( 1 ) = ( 1 , 2 ) ,    x ( 2 ) = ( 3 , 6 ) ,    x ( 3 ) = ( 5 , 10 ) x^{(1)} = (1,2), \ \ x^{(2)} = (3,6), \ \ x^{(3)} = (5,10) x(1)=(1,2),  x(2)=(3,6),  x(3)=(5,10)

对每个特征分别计算mini-batch内样本的均值:

μ B 0 = 1 + 3 + 5 3 = 3 ,     μ B 1 = 2 + 6 + 10 3 = 6 \mu_{B0} = \frac{1+3+5}{3} = 3, \ \ \ \mu_{B1} = \frac{2+6+10}{3} = 6 μB0=31+3+5=3,   μB1=32+6+10=6

则样本均值是:

μ B = ( μ B 0 , μ B 1 ) = ( 3 , 6 ) \mu_{B} = (\mu_{B0}, \mu_{B1}) = (3, 6) μB=(μB0,μB1)=(3,6)

2. 计算mini-batch内样本的方差

σ B 2 ← 1 m ∑ i = 1 m ( x ( i ) − μ B ) 2 \sigma_B^2 \leftarrow \frac{1}{m}\sum_{i=1}^m(x^{(i)} - \mu_B)^2 σB2m1i=1m(x(i)μB)2

上面的计算公式先计算一个批次内样本的均值 μ B \mu_B μB和方差 σ B 2 \sigma_B^2 σB2,然后再对输入数据做归一化,将其调整成均值为0,方差为1的分布。

对于上述给定的输入数据 x ( 1 ) , x ( 2 ) , x ( 3 ) x^{(1)}, x^{(2)}, x^{(3)} x(1),x(2),x(3),可以计算出每个特征对应的方差:

σ B 0 2 = 1 3 ⋅ ( ( 1 − 3 ) 2 + ( 3 − 3 ) 2 + ( 5 − 3 ) 2 ) = 8 3 \sigma_{B0}^2 = \frac{1}{3} \cdot ((1-3)^2 + (3-3)^2 + (5-3)^2) = \frac{8}{3} σB02=31((13)2+(33)2+(53)2)=38

σ B 1 2 = 1 3 ⋅ ( ( 2 − 6 ) 2 + ( 6 − 6 ) 2 + ( 10 − 6 ) 2 ) = 32 3 \sigma_{B1}^2 = \frac{1}{3} \cdot ((2-6)^2 + (6-6)^2 + (10-6)^2) = \frac{32}{3} σB12=31((26)2+(66)2+(106)2)=332

则样本方差是:

σ B 2 = ( σ B 0 2 , σ B 1 2 ) = ( 8 3 , 32 3 ) \sigma_{B}^2 = (\sigma_{B0}^2, \sigma_{B1}^2) = (\frac{8}{3}, \frac{32}{3}) σB2=(σB02,σB12)=(38,332)

3. 计算标准化之后的输出

x ^ ( i ) ← x ( i ) − μ B ( σ B 2 + ϵ ) \hat{x}^{(i)} \leftarrow \frac{x^{(i)} - \mu_B}{\sqrt{(\sigma_B^2 + \epsilon)}} x^(i)(σB2+ϵ) x(i)μB

其中 ϵ \epsilon ϵ是一个微小值(例如 1 e − 7 1e-7 1e7),其主要作用是为了防止分母为0。

对于上述给定的输入数据 x ( 1 ) , x ( 2 ) , x ( 3 ) x^{(1)}, x^{(2)}, x^{(3)} x(1),x(2),x(3),可以计算出标准化之后的输出:

x ^ ( 1 ) = ( 1 − 3 8 3 ,    2 − 6 32 3 ) = ( − 3 2 ,    − 3 2 ) \hat{x}^{(1)} = (\frac{1 - 3}{\sqrt{\frac{8}{3}}}, \ \ \frac{2 - 6}{\sqrt{\frac{32}{3}}}) = (-\sqrt{\frac{3}{2}}, \ \ -\sqrt{\frac{3}{2}}) x^(1)=(38 13,  332 26)=(23 ,  23 )

x ^ ( 2 ) = ( 3 − 3 8 3 ,    6 − 6 32 3 ) = ( 0 ,    0 )                   \hat{x}^{(2)} = (\frac{3 - 3}{\sqrt{\frac{8}{3}}}, \ \ \frac{6 - 6}{\sqrt{\frac{32}{3}}}) = (0, \ \ 0) \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ x^(2)=(38 33,  332 66)=(0,  0)                 

x ^ ( 3 ) = ( 5 − 3 8 3 ,    10 − 6 32 3 ) = ( 3 2 ,    3 2 )      \hat{x}^{(3)} = (\frac{5 - 3}{\sqrt{\frac{8}{3}}}, \ \ \frac{10 - 6}{\sqrt{\frac{32}{3}}}) = (\sqrt{\frac{3}{2}}, \ \ \sqrt{\frac{3}{2}}) \ \ \ \ x^(3)=(38 53,  332 106)=(23 ,  23 )    

  • 读者可以自行验证由 x ^ ( 1 ) , x ^ ( 2 ) , x ^ ( 3 ) \hat{x}^{(1)}, \hat{x}^{(2)}, \hat{x}^{(3)} x^(1),x^(2),x^(3)构成的mini-batch,是否满足均值为0,方差为1的分布。

如果强行限制输出层的分布是标准化的,可能会导致某些特征模式的丢失,所以在标准化之后,BatchNorm会紧接着对数据做缩放和平移。

y i ← γ x i ^ + β y_i \leftarrow \gamma \hat{x_i} + \beta yiγxi^+β

其中 γ \gamma γ β \beta β是可学习的参数,可以赋初始值 γ = 1 , β = 0 \gamma = 1, \beta = 0 γ=1,β=0,在训练过程中不断学习调整。

上面列出的是BatchNorm方法的计算逻辑,下面针对两种类型的输入数据格式分别进行举例。飞桨支持输入数据的维度大小为2、3、4、5四种情况,这里给出的是维度大小为2和4的示例。

丢弃法(Dropout)

丢弃法(Dropout)是深度学习中一种常用的抑制过拟合的方法,其做法是在神经网络学习过程中,随机删除一部分神经元。训练时,随机选出一部分神经元,将其输出设置为0,这些神经元将不对外传递信号。

图16 是Dropout示意图,左边是完整的神经网络,右边是应用了Dropout之后的网络结构。应用Dropout之后,会将标了 × \times ×的神经元从网络中删除,让它们不向后面的层传递信号。在学习过程中,丢弃哪些神经元是随机决定,因此模型不会过度依赖某些神经元,能一定程度上抑制过拟合。


图16 Dropout示意图

在预测场景时,会向前传递所有神经元的信号,可能会引出一个新的问题:训练时由于部分神经元被随机丢弃了,输出数据的总大小会变小。比如:计算其 L 1 L1 L1范数会比不使用Dropout时变小,但是预测时却没有丢弃神经元,这将导致训练和预测时数据的分布不一样。为了解决这个问题,飞桨支持如下两种方法:

  • downscale_in_infer

训练时以比例 r r r随机丢弃一部分神经元,不向后传递它们的信号;预测时向后传递所有神经元的信号,但是将每个神经元上的数值乘以 ( 1 − r ) (1 - r) (1r)

  • upscale_in_train

训练时以比例 r r r随机丢弃一部分神经元,不向后传递它们的信号,但是将那些被保留的神经元上的数值除以 ( 1 − r ) (1 - r) (1r);预测时向后传递所有神经元的信号,不做任何处理。

在飞桨Dropout API中,通过mode参数来指定用哪种方式对神经元进行操作,

paddle.nn.Dropout(p=0.5, axis=None, mode="upscale_in_train”, name=None)

主要参数如下:

  • p (float) :将输入节点置为0的概率,即丢弃概率,默认值:0.5。该参数对元素的丢弃概率是针对于每一个元素而言,而不是对所有的元素而言。举例说,假设矩阵内有12个数字,经过概率为0.5的dropout未必一定有6个零。

  • mode(str) :丢弃法的实现方式,有’downscale_in_infer’和’upscale_in_train’两种,默认是’upscale_in_train’。


说明:

不同框架对于Dropout的默认处理方式可能不同,读者可以查看API详细了解。


本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/12970.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

Nginx知识汇总

一、Nginx的简介 nginx是一款自由的、开源的、高性能的HTTP服务器和反向代理服务器&#xff1b;同时也是一个IMAP、POP3、SMTP代理服务器&#xff1b;nginx可以作为一个HTTP服务器进行网站的发布处理&#xff0c;另外nginx可以作为反向代理进行负载均衡的实现。 二、Nginx的优…

基于微信小程序的沁园健身房预约管理系统设计与实现-计算机毕业设计源码+LW文档

小程序开发说明 开发语言&#xff1a;Java 框架&#xff1a;ssm JDK版本&#xff1a;JDK1.8 服务器&#xff1a;tomcat7 数据库&#xff1a;mysql 5.7&#xff08;一定要5.7版本&#xff09; 数据库工具&#xff1a;Navicat11 开发软件&#xff1a;eclipse/myeclipse/idea Mave…

[附源码]Python计算机毕业设计 楼盘销售管理系统

项目运行 环境配置&#xff1a; Pychram社区版 python3.7.7 Mysql5.7 HBuilderXlist pipNavicat11Djangonodejs。 项目技术&#xff1a; django python Vue 等等组成&#xff0c;B/S模式 pychram管理等等。 环境需要 1.运行环境&#xff1a;最好是python3.7.7&#xff0c;…

【Linux】第十二章 多线程(线程概念+线程控制)

&#x1f3c6;个人主页&#xff1a;企鹅不叫的博客 ​ &#x1f308;专栏 C语言初阶和进阶C项目Leetcode刷题初阶数据结构与算法C初阶和进阶《深入理解计算机操作系统》《高质量C/C编程》Linux ⭐️ 博主码云gitee链接&#xff1a;代码仓库地址 ⚡若有帮助可以【关注点赞收藏】…

UNet - 训练数据train

目录 1. train 训练数据 2. Loss 值 3. 完整代码 1. train 训练数据 训练的代码只是在之前图像分类的基础上做了一些更改&#xff0c;具体的可以看下面的文章 pytorch 搭建 LeNet 网络对 CIFAR-10 图片分类https://blog.csdn.net/qq_44886601/article/details/127498256 …

EventBridge 生态实践:融合 SLS 构建一体化日志服务

作者&#xff1a; 昶风 引言 阿里云日志服务 SLS 是一款优秀的日志服务产品&#xff0c;提供一站式地数据采集、加工、查询与分析、可视化、告警、消费与投递等服务。对于使用 SLS 的用户业务而言&#xff0c;SLS 上存储的日志信息反映着业务的运行状态&#xff0c;通过适当地…

2021年认证杯SPSSPRO杯数学建模D题(第一阶段)停车的策略全过程文档及程序

2021年认证杯SPSSPRO杯数学建模 D题 停车的策略 原题再现&#xff1a; 开车前往人流集中的目的地时&#xff0c;决定在何处停车经常是一个难题。是停在距离目的地较远的地方&#xff0c;因为那里的空余车位可能较多&#xff0c;然后再走很远的路&#xff1f;或者是否应该乐观…

【C语言】程序的翻译环境和执行环境

&#x1f6a9;write in front&#x1f6a9; &#x1f50e;大家好&#xff0c;我是謓泽&#xff0c;希望你看完之后&#xff0c;能对你有所帮助&#xff0c;不足请指正&#xff01;共同学习交流&#x1f50e; &#x1f3c5;2021年度博客之星物联网与嵌入式开发TOP5&#xff5…

智慧博物馆解决方案-最新全套文件

智慧博物馆解决方案-最新全套文件一、建设背景二、思路架构三、解决方案建成5个方面1、集约化2、物联网接入3、大数据可视化分析4、室内室外地图集成5、可视化信息多元交互四、获取 - 智慧博物馆全套最新解决方案合集一、建设背景 博物馆是征集、典藏、陈列和研究代表自然和人…

【FME实战教程】002:FME完美实现CAD数据转shp案例教程(以三调土地利用现状数据为例)

FME完美实现CAD数据转shp案例教程&#xff08;以三调土地利用数据为例&#xff09; 文章目录1. cad数据预览2. 转换过程3. shp数据预览1. cad数据预览 2. 转换过程 &#xff08;1&#xff09;打开FME Desktop2020中文软件&#xff0c;点击【新建】。 &#xff08;2&#xff09…

【Spring】——2、使用@ComponentScan自动扫描组件并指定扫描规则

&#x1f4eb;作者简介&#xff1a;zhz小白 公众号&#xff1a;小白的Java进阶之路 专业技能&#xff1a; 1、Java基础&#xff0c;并精通多线程的开发&#xff0c;熟悉JVM原理 2、熟悉Java基础&#xff0c;并精通多线程的开发&#xff0c;熟悉JVM原理&#xff0c;具备⼀定的线…

微信小程序开发(九):使用扩展组件库

前端开发中离不开各种组件库&#xff0c;我最先接触的组件库还是Bootstrap&#xff0c;后来工作中又陆续使用了inoic、ng-zorro等各种不同的库。 在微信小程序开发中也有多种组件库&#xff0c;这里记录其中几种不同组件库的使用方法。 WeUI 这是微信官方推出的一款和微信原…

使用Python,Open3D对点云散点投影到面上并可视化,使用3种方法计算面的法向量及与平均法向量的夹角

使用Python&#xff0c;Open3D对点云散点投影到面上并可视化&#xff0c;使用3种方法计算面的法向量及与平均法向量的夹角 写这篇博客源于博友的提问&#xff0c;他坚定了我继续坚持学习的心&#xff0c;带给了我充实与快乐。 将介绍以下5部分&#xff1a; 随机生成点云点投影…

LaTeX学习笔记

LaTeX学习笔记 文章目录LaTeX学习笔记1. 开始的尝试2.文档类与宏包3.标题与章节4.标注5.列表6.对齐7.插入代码块8.绘制表格9.插入图片10.数学公式10.1.基础公式10.2.复杂公式10.3 常用符号11.参考文献冲鸭&#xff01;&#xff01;&#xff01; 1. 开始的尝试 先开始试一下一个…

MySQL数据库索引和事务详解

目录 前言&#xff1a; 索引 查看索引 创建索引 删除索引 索引使用 底层数据结构分析 事务 事务引出 MySQL设计事务 事务四大特性 小结&#xff1a; 前言&#xff1a; 数据库索引和事务的存在&#xff0c;对于数据库的一些性能有了显著提升。我们需掌握其底层的实现…

NUMA那些事儿

NUMA——Non Uniform Memory Access&#xff0c;中文为非统一内存访问&#xff0c;在NUMA出现之前&#xff0c;内存的控制器是包含在北桥芯片中的&#xff0c;所有内存由北桥统一管理&#xff0c;因此可以保证访问内存的一致性。随着CPU架构的不断迭代和演进&#xff0c;核数越…

Elasticsearch与Kibana安装

现有环境 windows docker ubuntu Elasticsearch安装 安装包下载 ES不同平台、版本下载路径&#xff1a;Download Elasticsearch | Elastic 本文演示用linux # 启动ubuntu环境&#xff0c;开放端口9200、9300、5601 docker run -name es -p 9200:9200 -p 9300:9300 -p 5…

指夹式血氧饱和检测仪方案分析

指夹式心率血氧饱和度方案的测量原理是根据血红蛋白(Hb)和氧合血红蛋白 (HbO2)在红光和近红光区域的吸收光谱特性为依据&#xff0c;运用Lambert Beer定律建立数据处理经验公式&#xff0c;采用光电血氧检测技术结合光电容积脉搏波描记&#xff08;PPG&#xff09;技术&#xf…

化工制造行业数字化升级案例—基于HK-Domo商业智能分析工具

案例背景导读 世伟洛克&#xff08;Swagelok&#xff09;是全球领先的流体系统解决方案的开发商和制造商&#xff0c;为包括科研、仪表、制药、油气、电力、石化、代用燃料和半导体等在内的各个行业提供产品、组装和服务。世伟洛克通过独立的销售和服务中心网站进行运营&#x…

使用 Typescript 封装 Axios

对 axios 二次封装,更加的可配置化、扩展性更加强大灵活 通过 class 类实现&#xff0c;class 具备更强封装性(封装、继承、多态)&#xff0c;通过实例化类传入自定义的配置 创建 class 严格要求实例化时传入的配置&#xff0c;拥有更好的代码提示 /*** param {AxiosInstance…