学习笔记

图像分类,我怎么学不废(填坑中)

时隔多年,我想起了我的博客,打算在博客里面写点什么,正好最近沉迷深度学习,就把深度学习这块知识进行一个整理和汇总。
这一篇文章主要是想对图像分类这个任务相关的知识进行一下梳理,不多废话直接开始

对图像数据的思考

对于人来说要想识别图像的内容非常简单,你甚至都不知道你的大脑里发生了什么,你只需要看一眼一张狗的照片,你就不会把它认成卡车。人能区分狗和卡车的本质在于狗和卡车具有不一样的特征,狗有四条腿,而卡车至少有四个轮子,卡车通常都比狗大,狗有个会动的尾巴等等。

如果类似的任务交给计算机来做会有哪些问题?首先你很难通过编写代码的方式让程序识别四条腿,四个轮子,会动的尾巴这种较为抽象的特性,你甚至都很难通过直接编程的方式告诉程序“腿”是个什么玩意儿,假设你神通广大,有办法把这种特征写进代码里,那是有四条腿的都是狗嘛?有四个轮子的都是卡车嘛?如果狗坐在一个四轮拖车里,那它究竟是狗还是卡车?

这些都是在处理图像数据中会面对的问题,特征描述困难,即使成功描述了,也可能因为特征出现位置的不确定和特征组合的不确定带来意料之外的结果。所以需要用一个方法既可以提取不确定特征或特征组合,又可以对特征进行组合判断的工具来对图像进行处理。

卷积

首先来解决第一个问题:如何提取特征,既然特征没办法用显示的程序语言描述,就可以把特征的提取交给卷积操作。

这里介绍的卷积操作并不是信号工程中的卷积,而是信号工程中的自相关(什么?你没学过信号工程?没事儿,我也没学过)。简单的用一个图解释信号工程中的卷积和自相关是什么:

信号处理中的卷积(图左)。过滤器 g 经过反转,然后再沿水平轴滑动。在每一个位置,我们都计算 f 和反转后的 g 之间相交区域的面积。这个相交区域的面积就是特定位置出的卷积值

这个图片看不懂不要紧,在看完这一小节的内容后就会对这个图片有一个直观的理解。目前为止,只需要知道深度学习-图像分类这个任务中的卷积操作是一个过滤器g沿水平轴与某个特征f计算相交的面积。也就是说,卷积操作是一个过滤器滑过某个特征并执行计算,这个操作可以理解为在f上使用g提取包含g的特征。
在我多年前写的从0开始用Python实现图像边缘检测一文中曾经介绍过卷积,重新引用里面的一些图片来加深对卷积的理解:

过滤器与特征计算的动态示意图

动图是上面示意图的补充,方便对滑动提取特征进行理解。这里面引入了一个比较重要的概念:滑动窗口(Sliding window),上图中g就可以看作一个滑动窗口。而在图像中,基本单位是像素,因此如果想在图像中使用卷积,就需要在图像的基本单位上进行滑动,如下图:

神经网络卷积示意图

这才是神经网络卷积操作的真实容貌,以像素为单位在原图像上进行滑动窗口操作。
下方的阴影部分被称为卷积核,滑动窗口的单次移动的举例称为步长,卷积核的每一个单元上都有参数,称之为卷积核的参数,卷积核上的参数与图像像素数据进行计算,生成一张新的“图片”,这张图片被称为“特征图”。具体计算结果如下:

卷积操作计算

从示意图中可以看出卷积操作主要在图像的两个方向进行,沿着图像的宽高进行。只要在卷积核中使用不同的数值(参数),就可以从图像中提取提取出不同的特征,也就完成了特征提取工作,并且特征提取后产生的feature map(特征图)的尺寸也变小了。

讲到这里,卷积的基本知识就结束了,后续所有的卷积都是在这个基础上发展而来的。当然看到这里如果你还迷糊,对卷积不太理解,也是正常的。接下来就引入一个例子来加深对卷积操作的理解。

2D/3D卷积

在开始本小节之前,首先需要对计算机如何表示图像进行一个介绍。计算机对颜色的表示常规情况下为RGB模式,即颜色可以由红黄蓝三色的组合表示,现代计算机采用32位真色彩表示图像,即RGB各占8位(0-255),透明通道占8位。因此在JPEG图像中一个像素点由三个最大为255的数字表示,一个像素点的shape为[3](表示一个一维向量,向量内有三个元素),而我们通常说图像的分辨率为1920×1080值得则是一幅图像的宽为1920高为1080,整幅图像共有3,471,360个像素点,所以一幅图像实际的维度是三维,shape为[1920, 1080, 3]。

让我们对这个图像应用前面提到的卷积操作,有这几个问题需要考虑清楚:
1、前面的例子中给出的图像维度为二维(可以理解成黑白图像),所以卷积核的维度也是二维,但现在输入图像维度变成了三维,卷积核应该发生什么变化?
2、卷积操作的目的是为了提取特征,如果我们使用一个卷积核对图像进行操作看起来就像是对图像进行尺寸压缩一样,能提取出特征吗?
3、前文提出,特征提取的手段是通过卷积核参数与图像本身发生计算,那卷积核的参数如何确定?
4、如果图像的尺寸不能被卷积核+步长整除怎么办?

首先来看第一个问题,当图像的维度变成了三维,很自然的想法就是卷积核也是三维就就可以了,这样就可以生成一张和前述卷积结果一样的二维特征图。也就是说一个shape为[100, 100, 3]的图像被一个[2, 2, 3]的卷积核以某种方式滑过就会产生一个shape为[50, 50]的特征图。这样的卷积就被称为2D卷积,因为他只在被卷积目标的长和宽两个维度滑动。

2D卷积

接下来,假设现在有一个shape为[100, 100, 100]的特征图,这次使用一个[2, 2, 2]的卷积核,分别从长宽高三个维度进行某种卷积操作,最后会得到一个[50, 50, 50]的特征图,这样的卷积就称为3D卷积。

3D卷积

接下来来看第二个问题,卷积操作是为了提取特征,如果我们用一个卷积核对目标图像进行卷积那么可以得到一个特征图,当我们用另外一个参数不同的卷积核进行卷积则会得到另一张特征图,假设我们同时使用128个参数不同的卷积核对图像提取特征,那么就可以得到128个含有不同特征的特征图,也就实现了特征提取,通常对这一操作的口头化表达方式为,对某某某提128个特征。

接下来看第三个问题,卷积核的参数如何确定,这个问题可能是新手想破脑袋也理解不了的一个问题,为什么卷积核能提取特征?前面不是刚说了要对这种特征进行程序编码是一件非常困难的事,当然这已经不属于程序编码的范畴了,如果我们把图像当作一个含有某种pattern(模式)的矩阵,那么我们就可以把任务目标转化为在矩阵中发现一个pattern,而pattern大多符合某种数学表达(例如高斯分布可以理解为一个pattern),我们就可以通过数学计算的方式人为设置一些已经被证明可靠的矩阵来检测某些pattern。这就是卷积核参数的一种初始化方法,常见的例子是:当我们相对一个图像做高斯模糊处理时,通常的手段就是使用高斯核对图像整体进行一遍卷积操作。然而说了这么多,深度学习中最常用的卷积核参数初始化方法并不是这个,常用方法就是随机,通常使用符合某种分布的随机数据来初始化卷积核的参数。
你可能以为就这?实际上网络中卷积核的参数是网络需要学习的一部分,会随着网络的更新对卷积核的参数进行更新,因此即使一开始被初始化成随机的,也会在后续的学习中被反向传播和梯度下降算法给修正成特征的“形状”。

最后来看第四个问题,如果特征图不能被卷积核+步长整除,这个问题就更加简单了,无非两种思路,一种是裁切特征图,一种是把特征图补到可以被整除的尺寸。当然裁切特征图这个是不可以的,因为你没有办法保证裁切掉的部分不包含重要的信息,因此常用做法是在特征图的周围补padding来扩充尺寸,通常会使用0来作为填充材料。

当然此外还有一个1D卷积,就可以进行类似的类比了。

转置卷积(反卷积)

前面介绍了最常出现的卷积,既然卷积操作会缩小feature map,那转置卷积就是放大feature map了。转置卷积在生成高分辨率特征图(图像)和将低微特征映射到高维特征等方面具有应用,简单粗暴的理解就是放大了feature map。一个经典的关于转置卷积的应用就是,在早期的deepfake项目中,卷积层分别对原图(人脸)和需要被换上去的人脸进行卷积,得到一个feature map,然后用转置卷积分别对原图和需要被换上去的人脸进行原图还原,在训练到loss稳定不下降以后,交换两个网络的转置卷积部分,这样就可让两张图片的人脸互换。

转置卷积有几种计算方式,一种是通过补padding的方式,然后使用常规卷积达到扩大feature map的效果。

问题例子

这是关于转置卷积的简单理解,我们需要设计一个通用方式来实现转置卷积。首先来看普通卷积的矩阵计算是怎么发生的。

\begin{split}
input=\left[\begin{array}{ccc}
x_1 & x_2 & x_3 & x_4 \\
x_6 & x_7 & x_8 & x_9 \\
x_{10} & x_{11} & x_{12} & x_{13} \\
x_{14} & x_{15} & x_{16} & x_{17} 
\end{array}\right]
\end{split}
\qquad
\begin{split}
kernel=\left[\begin{array}{ccc}
w_{0,0} & w_{0,1} & w_{0,2} \\
w_{1,0} & w_{1,1} & w_{1,2} \\
w_{2,0} & w_{2,1} & w_{2,2}
\end{array}\right]
\end{split}
\\
\begin{split}
output=\left[\begin{array}{ccc}
y_0 & y_1 \\
y_2 & y_3
\end{array}\right]
\end{split}

上面的公式表示对input进行步长为1,padding为0的卷积,最后输出为output。如果我们想要把这个过程翻转过来,也就是以某个卷积核在output上进行某种计算生成input,那我们需要进行一些变化:

\begin{split}
output=\left[\begin{array}{ccc}
x_1 \\ x_2 \\ x_3 \\ x_4 \\
x_6 \\ x_7 \\ x_8 \\ x_9 \\
x_{10} \\ x_{11} \\ x_{12} \\ x_{13} \\
x_{14} \\ x_{15} \\ x_{16} \\ x_{17} 
\end{array}\right]
\end{split}
\qquad
\begin{split}
input=\left[\begin{array}{ccc}
y_0 \\ y_1 \\
y_2 \\ y_3
\end{array}\right]
\end{split}

我们首先将输入输出的身份交换(模拟转置卷积操作的目标),并将维度降至一维,接下来我们只要找到一个矩阵能实现其与input矩阵相乘可以得到output矩阵即可,即下面式子表示的。

output=Y
\\
input=X
\\
转置卷积计算:Y=C^TX
\qquad
标准卷积计算:X=CY
\\
\begin{split}
\scriptsize{
C=\left[\begin{array}{ccc}
w_{0,0} & w_{0,1} & w_{0,2} & 0 & w_{1,0} & w_{1,1} & w_{1,2} & 0 & w_{2,0} & w_{2,1} & w_{2,2} & 0 & 0 & 0 & 0 & 0 \\
0 & w_{0,0} & w_{0,1} & w_{0,2} & 0 & w_{1,0} & w_{1,1} & w_{1,2} & 0 & w_{2,0} & w_{2,1} & w_{2,2} & 0 & 0 & 0 & 0 \\
0 & 0 & 0 & 0 & w_{0,0} & w_{0,1} & w_{0,2} & 0 & w_{1,0} & w_{1,1} & w_{1,2} & 0 & w_{2,0} & w_{2,1} & w_{2,2} & 0 \\
0 & 0 & 0 & 0 & 0 & w_{0,0} & w_{0,1} & w_{0,2} & 0 & w_{1,0} & w_{1,1} & w_{1,2} & 0 & w_{2,0} & w_{2,1} & w_{2,2}  
\end{array}\right]
}
\end{split}
\\
\begin{split}
\scriptsize{
C^TX=
\left[\begin{array}{ccc}
w_{0,0}y_0 & w_{0,1}y_0+w_{0,0}y_1 & w_{0,2}y_0+w_{0,1}y_1 & w_{0,2}y_1 \\
w_{1,0}y_0+w_{0,0}y_2 & w_{1,1}y_0+w_{1,0}y_1+w_{0,1}y_2+w_{0,0}y_3 & w_{1,2}y_0+w_{1,1}y_1+w_{0,2}y_2+w_{0,1}y_3 & w_{1,2}y_1+w_{0,2}y_3 \\
w_{2,0}y_0+w_{1,0}y_2 & w_{2,1}y_0+w_{2,0}y_1+w_{1,1}y_2+w_{1,0}y_3 & w_{2,2}y_0+w_{2,1}y_1+w_{1,2}y_2+w_{1,1}y_3 & w_{2,2}y_1+w_{1,2}y_3 \\
w_{2,0}y_2 & w_{2,1}y_2+w_{2,0}y_3 & w_{2,2}y_2+w_{2,1}y_3 & w_{2,2}y_3
\end{array}\right]
}
\end{split}

通过这样的计算就实现了上面例子图的等效通用算法,实际也是将原图的padding设为2进行常规卷积

空洞卷积(扩张卷积)

空洞卷积,顾名思义就是卷积核之间有空洞,不多废话直接上图。

空洞卷积示意图

空洞卷积通过在卷积核元素之间插入空格来使卷积核膨胀,可以设置元素间插入的空格数量来控制卷积核的膨胀程度,从而控制卷积核的感受野。空洞卷积的好处就是在不显著增加网络参数的情况下扩大感受野。主要的应用在提升形义分割系统的准确度。
PS:这个卷积我从来没使用过,因此简介几乎是从各方拼凑而来,日后有机会使用了以后再完善这块的知识。

不同规模的空洞卷积

那就引出了一个问题:什么是感受野(Receptive Field)?
在前面的卷积中我们可以看到一个卷积核(假设尺寸为3×3,步长为1)在图像上进行滑动操作后会将卷积核尺寸范围内的数据与卷积核参数进行计算,得到一个数字。这一个数字实际对应的是原来3×3区域内的信息,所以也就说经过3×3卷积核卷积过的feature map的一个单元实际上包含原图3×3个单元的信息,这样我们就称这一次卷积操作的感受野是3。
接下来我们继续使用一个2×2的卷积核,步长为1对上面的feature map再次卷积,得到的第二个feature map,第二个feature map中一个单元实际上对应原图中4×4的区域,所以第二次卷积操作的感受野是4。

可分卷积

在了解可分卷积前,首先来看一个有意思的情况:假设我们使用一个5×5的卷积核对图像进行步长为1的卷积,感受野毫无疑问是5,此时卷积核的尺寸是5×5共25个参数,如果我们使用一个3×3卷积核步长为2得到一个feature map后再对feature map同一规格(不同个)的3×3卷积核再得到一个feature map,此时我们会发现感受野依然是5,但是参数变成了3x3x2=18。这种想法最早在VGG网络中被提出,旨在保留感受野的同时减少参数。

把这一思想发挥到极致就是可分卷积,可分卷积分为两大类:空间可分卷积,深度可分卷积。

空间可分卷积

基于前面介绍的思想,一图快速了解空间可分卷积。

空间可分卷积图解

好,结束。
空间可分卷积从长宽两个方面下手对卷积计算进行拆解。但这种拆解存在问题,并非所有的卷积核都可以被等效的拆解成两个更小的核,而且拆解将固定网络可以使用的卷积核范围,因为你必须要选择可以拆解的卷积核,而有的卷积核不能被拆解但是可能也表现得很好。

深度可分卷积

深度可分卷积则要比空间可分卷积使用的更加频繁。先看之前介绍过的2D卷积,卷积核实际上是三维的形态,如果我们不对卷积的长宽进行拆解,而是对纵深进行拆解,假设原来2D卷积的卷积核shape为[2, 2, 3]经过一个[2, 2, 3]的特征图后会变成[1](一个数字),而深度可分卷积使用了三个shape为[2, 2, 1]的组成一组,对feature map进行卷积,最后得到的特征图shape为[1, 3],但是这样如果到这里就结束了那明显是不对的,不论是用什么卷积都必须要保证卷积结果符合卷积规则,因此还需要再后接一个shape为[1, 1, 3]的卷积核进行将为,这样得到的特征图的shape才会是[1]。

在常规卷积中我们会使用N个结构相同的卷积核对目标特征图进行卷积,例如上述例子中,如果我们使用例子中的卷积核对特征图提取100个特征,就需要100个卷积核对feature map进行运算。如果用深度可分卷积提取100个特征,则需要首先现在纵深上拆解卷积核使用三个shape为[2, 2, 1]的组成一组卷积核对feature map进行卷积,然后再使用100个shape为[1, 1, 3]的卷积核进行升维,得到100个特征。

深度可分卷积完整示意图

可能会有人好奇1×1的卷积核是个什么东西,有啥作用啊?

1×1卷积和最早在Network in Network中被提出,在Inception模块和ResNet中被发扬光大(个人观点),在现在的图像相关的处理中,一般可以用在当作升降维的工具,比方说在深度可分卷积中1×1卷积起到的作用就是升降维。同时使用1×1卷积和还可以增加网络的非线性表达能力。除此之外1×1卷积核还可以被视作一种全连接,在全局平均池化这种技术中就用到了类似的特性。

分组卷积(深度可分卷积的变种)

分组卷积出现的时间要远远早于深度可分卷积,最早在AlexNet中就有应用,深度可分卷积是将每一个通道都分成一组,而AlexNet中提出的分组卷积是为了增加并行能力而设计的,因此卷积只被分成GPU个数个组。

分组卷积一方面可以发挥充分利用计算设备,高效训练、让模型变得更高效以外,另一方面分组卷积会提供比标准的2D卷积更好的效果。会提供更好的效果这一点可能听起来让人比较迷惑,在这篇文章中认为卷积核之间的关系并没有很强(过滤器之间的关系是稀疏的),但是如果将卷积核分组,组间依然没有很强的关联关系,但是组内的关联关系会加强,有利于不同卷积核学习不同的结构。例如在AlexNet中可以看到不同组的卷积核似乎学习到了完全不相同的两组特征。

AlexNet conv1卷积核示意图

文章猜测:卷积核分组的效果是在通道维度上学习块对角结构的稀疏性……在网络中,具有高相关性的卷积核是使用卷积核分组以一种更为结构化的方式学习到。从效果上看,不必学习卷积核关系就不再参数化。这样显著地减少网络中的参数数量能使其不容易过拟合,因此,一种类似正则化的效果让优化器可以学习得到更准确更高效的深度网络。
具体更多的图片可以去原文查看,包括不同分组规模组内和组间卷积核的关联性。

池化

卷积到这里就告一段落了,接下来来看另一个操作:池化。池化相对于卷积来说就要简单的多,但是作用却很重要。

在正式讨论池化之前,我们需要思考一个问题,假设我对一副1080p的照片进行卷积,那么得到的feature map肯定是很大的,为了在图像中提取更多的信息,我就需要发动更大的卷积核或者更多的卷积计算操作,来覆盖全图,这样会带来更大的计算量,浪费更多的计算资源。同时思考如果这一张1080p是一个物体的近景照片,那么卷积的步长即使设置为10,还是会检测到很多重复的特征。

因此基于以上的种种原因,引入池化层。

池化层最最最最最重要的作用就是对特征图进行下采样(down sampling),说人话就是把特征图缩小了。缩小特征图相当于浓缩了特征,去除了冗余的信息,同时降低了特征图尺寸,为后面的操作降低了计算量。
池化层还根据具体实现方式不同起到一定的增加整体网络非线性功能的作用。
同时还可以提高feature map中每个像素的感受野。
最后还可以提高网络对特征的鲁棒性,也就是实现不变性(平移,旋转等的不变性)

最大池化/平均池化

这两个池化操作是平常使用较多的池化操作。池化的具体操作和卷积非常类似,使用的是使用池化核“卷积”图像得到,常规的池化核的步长等于池化核的尺寸,即3×3的池化核的步长就为3。但是与卷积核不同的是,池化核不含任何参数,它仅仅是对池化核区域内的图像数据进行某种固定的数学处理。最大池化就是选择当前池化核区域内最大的一个数字来代表这个区域,放入池化后的feature map对应的位置上,而平均池化则是对池化核区域内的所有数字求平均来代表这个区域。

重叠池化

就是设置池化步长小于池化核的尺寸,让池化出现重叠

空间金字塔池化(Spatial Pyramid Pooling)

这是一种在SPPNET中被提出来的池化工具,是早期物体检测网络的组件之一。先来看空间金字塔池化的示意图。

当我们相对任意尺寸的图像提取特征,空间金字塔池化是一个很好的方法,在介绍空间金字塔池化以前,我们必须先看一下为什么不能随意对任意尺寸的图像提取特征。
假设我们的目标是获取shape为[5, 5, 128]的特征图,原始图像是[9, 9, 3],可以用两个卷积层卷积层设置3×3的卷积核步长为1,就可以获得但是如果把原始图像的尺寸设置为[18, 18, 3],那么经过同样的网络结构得到的特征图尺寸是[14, 14, 128]就不符合预期了。网络最后特征图的结果实际上依赖于网络结构核输入网络的图像。
空间金字塔池化可以输出固定维度的特征图,从示意图中可以看出,首先先将图片分成4×4的方格,在每个方格内应用最大池化或者平均池化,再将图像划分成2×2的放个,再在每个方格里应用最大池化或者平均池化,以此类推。这样最后生成的结果的shape实际上是[1, x],并不像最大池化或者平均池化那样会形成一个shape为三维的特征图。

一般来说SPP layer(空间金字塔池化)是作为特征提取层的最后一层出现在网络中,后面接的一般是下一小节要讲的全连接。而且在实际操作中很少使用SPP layer来让网络适应任何的输入,原因在后面会提到。

全连接

在池化结束以后,我们会得到一个包含图像特征的feature map,但是这个时候计算机还是不知道如何把这些数学特征和人类世界的特征联系起来,这个时候就需要全连接来帮忙了。

全连接层在整个图像分类的进程中真正扮演了一个分类器的作用,它负责把各类特征和最后的分类结果进行映射,决定每个特征在最后分类结果中所占的比重。下面是全连接的简图(图源来自MLP网络,在这里使用不影响):

首先来观察一下全连接的网络结构,其中的input layer可以理解成卷积层提取出来的特征,于前面理解最大的不同是,进入全连接的数据只能是一维数据shape为[1, x],前面介绍的卷积层提取的特征进入全连接层之前都需要做形状的调整。

中间蓝色两层的hidden layer才是主角全连接层,全连接层被称为全连接层就是以因为每一个神经元的输入都来自上一层所有神经元的加权。所以一层全连接层假设有1024个神经元,输入的特征向量的shape为[1, 384],那么这一层的总参数量就1024×384。

最后一层为输出层,输出网络的最后结果,示意图中的网络为二分类网络,所以输出神经元只有一个,如果要预测多类,就输出多个神经元,每一个神经元代表该类的置信度,例如需要输出三类,则最后的输出层就需要三个神经元与上一层全连接层全连接。

如果把网络中的全连接层拿出来单独看,那么这一部分也被称为多层感知机(MLP),我们可以直接对一张图片不进行任何特这个提取,直接将其变成shape为[1, x]的特征向量丢给MLP进行暴力求解,但是这样往往存在收敛满,计算量大的问题。现在的网络就变成了让MLP只处理高级特征,减缓计算压力,提升计算和收敛速度。

反向传播算法(BP)

再深度到下一部分激活函数之前,我们还需要补充一个深度学习的重要算法,BP算法,也就是反向传播算法。

其实深度神经网络的传播一共分为两个部分,一部分是前向传播,另一部分是反向传播。其中前向传播比较好理解,是网络从前到后以此计算,直接上图:

网络样例

从这个图中可以看到,h1=i1*w1+i2*w2,其中wi被称为权重或者是网络的参数,前面提到的卷积核的参数就属于一种wi,而前面提到的卷积操作的计算就属于前向传播,通过前向传播来求解出网络下一个节点的数值。这非常好理解。

接下来我们来看看反向传播。反向传播发生在前向传播以后,当我们的网络完成了一次前向传播,得到了最后的预测结果,那么我们就应该看当前的预测结果和正确结果究竟有多大差距,在这里我们用到的是损失函数(这个概念不会在这里展开,会在本文的稍后位置展开讨论,在这里只需要理解损失函数可以返回真实值和预测之间的差距就可以了),损失函数会产生一个损失,代表预测结果与真实值的整体差距。但是我们的网络是由众多神经元组成,真正需要确定的是每一个神经元具体犯了多大的错误。然后将错误合理的分配给合适的神经元,就可以达到修正网络的目的。

这就是BP算法的核心思想,在介绍具体操作之前,首先来看一个你可能会感兴趣的问题,神经网络为什么能学习?

梯度下降

来观察一个简单的例子:

梯度下降示意图

现在需要你找到这个函数的最(极)值点,你会怎么做。对于例子中给的这条曲线你可能直接就要求导数为0的点,就是最值点。我们假设黑点的位置可以表示为函数的最(极)值点,显然初始位置并不在真正的最值点上,我们可以借助导数来判断函数的变化方向,从而确定这个点的移动方向。

导数指的是函数在求导这一点附近的变化率,在图中我们可以看到这个点的导数为正,那么如果我们想要找到最小值点,只需要让黑点的沿着切线方向移动就可以了。

梯度下降神奇的地方在于不论这个点初始化在这个函数的哪个位置,最后都会沿着切线方向来到最小值点。不信你可以分析一下当初始化点在函数左侧曲线上时的下降情况。

那你可能会问,为什么不直接利用数学工具对函数的最(极)值点进行求解,而是需要使用这种方式来求解呢?深度学习最后的学习目标是构造出一个函数,这个函数是预定义函数簇中多种多个函数按照不同的权重组合而成的,最后的目的并不是为了求解最值,而是找到能使预测值更接近真实的一组函数权重的组合。

回到BP

神经网络的学习过程,实际上就是预测值和真实值误差最小化的过程,“最小化”看着眼熟吗?所以可以使用梯度下降方法来进行参数优化。但是网络中有这么多神经元,到底要怎么参数的更新呢,回过头来看前向传播的流程,可以将前向传播视为一个巨大的函数,对这个函数求导数需要使用链式求导法则(这是一个本文不会解释的概念,需要读者自己了解)。

—填坑位—

激活函数

OK,到目前为止我们已经把一个CNN几大基础功能和一些基础算法都介绍完了,什么?你问我什么是CNN?
CNN(Convolutional Neural Networks)主要应用在图像处理方面,CNN中的C翻译成中文就是卷积,所以CNN也被称为卷积神经网络。CNN的网络结构主要为卷积层,池化层,全连接层和激活函数,当然还存在一些其他的结构,但是所有的CNN中都一定存在这四个结构,这四个结构里面没谈到的,也就是这一小节的内容了。
来看一下什么是激活函数,试想一下一个场景:

一组数据

当我们有这么一组数据时,很明显是没办法使用y=kx+b这样的函数来拟合这个数据的,而我们的网络需要面对维度更大,特征更加复杂的非线性问题,如果使用简单函数的组合则会导致效果不佳,如果使用复杂函数的组合则会增加计算的复杂度。而根据研究,在没有激活函数的情况下每一层网络实际上都在做线性变换,而多层网络叠加在一起仍然在做线性变换,无法满足解决非线性任务的要求。
因此诞生了激活函数这个东西,激活函数通过在原来层与层之间加入一个非线性函数,让上一层模型的输出经过激活函数从而获得非线性的特性。

那么获得非线性有什么好处吗?难道原来使用线性函数不能对曲线进行模拟吗?先说后面的问题,模拟肯定是能模拟的,我们在一条曲线上取随机的两个点,根据极限的思想,只要两个点的举例趋向于0,那么两个点间的这段曲线就可以理解成一条直线,从这一点来看自然可以用无数小直线来模拟曲线,但是如果有原生的曲线为啥不用原生的曲线呢?

激活函数的引入让网络可以学习到光滑的曲面,而不是用复杂的线性组合去组合曲面,因此激活函数会增强网络的表示能力。
接下来就列举一下目前比较常见的一些激活函数

Sigmoid

老牌激活函数之一,可以算是激活函数界的老前辈了,现在基本是退休状态。

Sigmoid函数图像
Sigmoid:S(x) = \frac{1}{1+e^{-x}}

Sigmoid的数学特性都可以在图中观察到。现在Sigmoid基本退休的原因:
1、Sigmoid函数在[-2, 2]区间有较大的斜率,而在除此之外的其他区域斜率逐渐变小直至消失,也就是说Sigmoid函数在很大的区间范围内容易发生饱和致使梯度消失。
2、Sigmoid函数并不是以0为中心的函数,这一点主要影响的是收敛速度。

发表评论

您的电子邮箱地址不会被公开。