在介绍神经网络之前,首先介绍一下神经元模型。
神经元模型可以描述为这样的一张图:
对于一个模型而言,我们首先要把握住四个部分:输入、输出、参数以及对应的运算关系。(这一点很重要)
在上图所示的神经元模型中:
输入为,输出为,参数为权重和偏置。
其运算关系为:
其中,被称为**函数,一般为连续的非线性函数,以增强网络的表示能力。
常见的**函数有Sigmoid函数、Relu函数、Tanh函数等等,在这里不一一赘述,有兴趣的朋友们可以自行百度。
人工神经网络就是由神经元模型组成的,具有并行分布式结构的神经网络模型。
【一】DNN
DNN,前馈神经网络,网络中神经元分属于不同的层,整个网络中无反馈,信号从输入层向输出层单向传播,可用一个有向无环图表示 。
从图中可以看出,网络的输入与神经元模型相同,是一个维向量,网络的输出是一个维向量。因此,模型中的运算关系可以看作 。
此外,模型中的参数包括每层所对应的权重和偏置。
这样,整个模型可以描述为:
其中,对于每一层而言:
即:
在上述模型中,需要经过计算得到的,就是模型中的参数值(,),对于有监督训练来讲(在这里,为了简化问题,我们仅考虑有监督训练问题),如何求得权重和偏置呢?
【二】梯度下降法
在有监督训练中,我们有给定的实例,那么很自然地,我们会想到列方程来求解参数,但是当参数个数很多时,给定的实例个数可能会小于参数个数,这样,方程法将无法求解参数。
所以,我们通过另一种方式来进行参数求解——迭代调参:通过调整参数,让模型输出递归性地逼近标准输出。
在神经网络中,我们往往用迭代调参的方法进行参数求解。
很明显,在调参的过程中会有三个最基本的问题:
1.参数的初始值是什么?
2.怎么调参数?
3.要把参数调到什么程度才算结束?
对于第一个问题,方法很简答:随便设置参数初值。
因为参数值在迭代过程中是可调的,所以初始值并不重要(实际上还是会对模型效果有些影响的,在后面的多极值点函数问题中会提到),因此,可以随意设置。
对于后两个问题,一般来说,迭代调参方式分为两个步骤:
1.定义目标函数(损失函数):将问题转化为极值问题。
2.优化目标函数:用调参的方式求目标函数的极值,以此来确定参数。
这样,我们既解决了如何调整参数的问题,也确定了调参什么时间结束。
为了反应模型输出对真实结果的拟合程度,很自然地会想到利用模型输出结果与真实结果之间的误差定义目标函数。
损失函数,也就是我们所说的目标函数,常记作 或 ,我们的问题也就定义成了:求解 ,使得模型输出与真实结果之间的误差最小。
损失函数有很多,交叉熵函数是较为常用的一种,对损失函数感兴趣的朋友可以自行百度了解~
现在,目标函数定义好了,索性将其表示为 ,我们的问题和目标都已经很清晰了:
已知 ,求
我们将其描述为“优化目标函数”过程,也就是上面所说的步骤二:利用迭代调参的方式逼近我们的目标。
这种迭代调参的方法就是大名鼎鼎的梯度下降法。
梯度下降法背后的数学原理是泰勒公式:
假如函数在附近无限可微,那么利用泰勒展开可以写为:
那么,当与无限接近时,上式可以写为:
不失一般性:
由于我们的目标是求解函数的极小值(在这里我们将看作目标函数),那么每次选取的的值要比上一次的更小,即:
带入泰勒展开式:
可以得出:
值得注意的是,和的大小犹未可知。或者说,无所谓和的大小关系如何,梯度下降法都可以很好地达到我们预期的目标,对此有疑问的朋友们可以自己画图验证一下~
到这里,我们就得到了迭代调参的方法——梯度下降法:
其中,被称为学习率,被称为梯度,整个迭代过程到梯度为0(即=0)时停止。
可以看出,梯度下降法面临着这样一个很明显的问题:
加入函数是一个具有多极值点的函数,那么如何确定梯度下降之后的结果是最优解呢?
(图片来自百度)
上图中,很明显,函数在处达到最小值。然而,如果梯度下降法找到了或者之后,是不会再继续寻找极值点的,因为此刻的梯度已经为零,迭代结束。
对于这个问题,解决方法比较佛系:设置随机的参数初值。
这个方法不能保证一定能解决这个问题,但是至少做出了一定的,成本可接受的努力。
此外,学习率的设置也是需要考虑的。
很明显,学习率过大会导致无法到达最优解,学习率过小将会导致迭代次数过多。
对于如何设置学习率,本人在另外一篇博客中有简单提及:机器学习如何进行调参
在这里要注意一点,此“调参”非彼“调参”,本文中所说的调参是调节模型训练的参数、,而在引用博客中所说的调参是调节超参数。超参数在模型训练之前预先设置,并在模型训练过程中保持不变。
最后,梯度下降法根据调节参数利用的样本个数分为:梯度下降法(一次利用所有样本)、随机梯度下降法(一次利用随机选取的一个样本)、mini-batch梯度下降法(一次利用一个batch的样本),对其感兴趣的朋友可以自行百度了解,在这里就不再赘述。
【三】反向传播算法
在梯度下降法提出过后,人们发现,调节参数仍然是一项巨大的工程,这直接导致了神经网络无法做得过深,直到反向传播(BP)算法诞生。
BP算法的核心思想很简单:将输出误差以某种形式反传给各层所有的单元,各层按本层误差修正各单元连接权值。
这样,神经网络真正地成为了深度学习,迎来了自己的春天。
你一定还记得,在DNN中有这样一组式子:
对于每一层而言:
以及:
那么,按照对网络递推关系的理解,我们可以很容易在此基础上得到下面的一组式子:
很容易理解,这意味着,某层的改变影响了之后所有层的结果。
利用梯度下降法,可以得到:
在这个式子中,我们关心的只有梯度,根据导数的链式法则,有:
其中,对于后一项我们可以利用式(1)简单求得,结果为。
那么问题的关键就转化为了求解前一项:,不妨设该误差项为。
由于误差是从最后一层反向传播,所以先对最后一层计算,这也很简单:
后一项可以由式(2)求得,结果为:。
(对最后一层而言,与相同)
而在前一项中,很明显,误差函数是输出的函数,因此也可通过简单的求导得到,在这里记为。
于是,我们可以得到
现在,我们有了最后一层的,最关键的部分就是求和之间的关系了,有了这个关系,误差就可以从最后一层反向传播至所有层。
定义第I层的第i个神经元的误差为,下图为神经网络状态:
根据网络的递推关系,我们可以得到:
由于和之间的关系是这样的:
所以,根据导数的链式法则,有:
在这个式子中,我们可以发现,所有的偏导均可求,求解结果如下:
把上式中的项写成矩阵形式:
其中,‘·’表示矩阵的点乘,。
至此,反向传播算法的全部要素都已经求得,在推导BP算法的过程中,导数的链式法则是基础,对链式法则不熟悉的朋友可以自行百度了解~
此外,最重要的一点是把握住每层之间的递推关系(这一点真的很重要),如果还有哪个地方不理解,闲暇之余自己手推一遍是比较好的一种加深理解的方法~
在反向传播的过程中,我们发现,在每一层都要乘**函数的导数,即。当**函数为sigmoid函数或者tanh函数时,由于**函数的导数小于1,会导致误差经过每一层网络时都会衰减。当网络层数很深时误差接近于0,这就是梯度消失问题。
这个问题可以将**函数改为Relu函数加以解决。
【四】CNN
CNN,卷积神经网络,在图像相关问题中得到广泛使用。
为什么呢?
在上文中所提到的DNN中,我们可以做这样一个假设:
如果第层有 个神经元,第层有 个神经元,那么,连接边有个,也就是说,权重矩阵有个参数。
如果有一张图像是的,当、很大时,权重矩阵的参数非常多,训练的效率会非常低。
假设,第一个隐藏层有1024个神经元,那么权重矩阵的参数就有102400个。
CNN就是为了解决参数过多的问题而提出的。
卷积神经网络(Convolutional Neural Networks,CNN)是一种前馈神经网络,是受生物学上感受野(Receptive Field)的机制启发而提出的。所谓感受野,就是神经元的特定区域,只有在这个区域内的刺激才可以**该神经元。
(对于感受野的概念,这里介绍得比较笼统,有兴趣的朋友们可以自行百度~)
在网络结构上,CNN是由卷积层、池化层(也叫子采样、降采样层)和全连接层交叉堆叠而成。
在卷积层,利用卷积核(filter)对图片进行卷积运算,得到的结果称为特征图(feature map)。
假设我们的图片是这样的:
卷积核是这样的:
那么我们得到的结果(特征图),是这样的:
至于具体是怎么操作的,涉及到填充(padding)、步长(stride)等等概念的组合以及卷积运算的基本概念,在这里不一一赘述,有兴趣的朋友可以自行百度或者参看本人的另外一篇博客:机器学习中的一些基本概念。
看到这里,大家会发现一件事:我们把一张的图片处理成了的图片,这从一方面减少了参数的数量。
现在,我们再来做一笔计算:
还是一个10*10的图像,第一层的神经元个数还是1024个。
如果这1024个神经元是用16个的filter卷积得到()(假设步长为1,无填充),那么参数的个数是个(16个filter,每个filter都是)。
很明显,与DNN相比,CNN在参数个数方面的优越性很强。
此外,卷积连接有这样的两个特点:局部连接、权重共享。
即,对于一张feature map来说,所用的filter是同一个,而且一个filter每次只对原图像中的一部分进行卷积操作,重复多次,得到结果。
在池化层,池化操作(pooling)的本质是采样,用于减少模型参数并保留有效信息避免过拟合,提高训练速度。
以刚刚得到的feature map为例,进行的max pooling:
可以得到如下结果:
可以看出,在每个的方格中,选取方格内最大的值,组成新的结果:
上面的描述中,pooling即为池化。
在网络训练中,卷积层和池化层作为一个整体进行训练。而且,卷积层和池化层可以进行多层堆叠。
此外,池化的方法有很多,在这里不一一介绍,有兴趣的朋友可以参看:机器学习中的一些基本概念
在全连接层,首先将最后的池化层的单元进行“平化”,组成全连接输入网:
此后,就像传统DNN结构相同啦~
CNN具有三个结构上的特性:
1.局部连接
2.权重共享
3.时间或空间上的降采样
这些特性使得卷积神经网络具有一定程度上的平移、缩放和扭曲不变性。
【五】RNN
在神经网络中,有两个RNN:Recurrent Neural Network 循环神经网络、Recursive Neural Network 递归神经网络,本节所提到的RNN均指循环神经网络。
在了解了DNN和CNN过后,我们会意识到一个问题,CNN和DNN只能处理输入、输出定长的问题,而处理变长问题效率不高,而在自然语言处理(NLP)等领域,输入、输出(语句)的长度往往不固定。
(我们将在NLP章节介绍另一种RNN:递归神经网络)
除此之外,对于时序相关问题,DNN和CNN也无法解决。因此,提出循环神经网络的概念。
循环神经网络的核心思想十分简单:将问题在时序上分解为一系列相同的“单元”,单元的神经网络可以在时序上展开,并且能将上一时刻的结果传递给下一时刻,整个网络按时间轴展开,即可处理变长和时序问题。
RNN的单元结构如下:
对于一个模型而言,最重要的是什么?
四个部分:输入、输出、参数、对应运算关系。
在RNN单元中:
输入:X,以及来自前一时刻隐藏层的结果
输出:Y,以及传递给下一时刻隐藏层的结果
参数:、、、
对应运算关系(信息传播):
其中,函数是一种特殊的函数,使得输出为一个对应的概率值,对函数感兴趣的朋友们可以自行百度进行了解~
有了这个RNN基本单元,整个RNN网络也就呼之欲出了:
这张图中告诉了我们极为关键的一点:每个RNN基本单元的对应参数值都是相同的(这一点十分重要)。
此外,对应不同的问题,RNN的输入输出结构可以不同:
同样,利用梯度下降法进行参数学习。
但是反向传播过程与DNN有所不同:
传统BP算法无法保证在参数调整的过程中对应参数相同,而RNN网络各个单元中的对应参数要求相同,这就需要对传统BP算法进行改进,这种改进后的BP算法叫做基于时间的反向传播算法(BPTT):
为了保证RNN单元对应参数相同,BPTT提出了两点要求:
1.要求所有RNN单元结构的对应参数置相同初值。
2.在参数调整的过程中,要求同时调整参数。
即:
这两点要求都很好理解,而且都很好实现,只需使得RNN单元结构中的对应参数共享同一块内存即可。
在实际应用的过程中,人们发现RNN有一个问题,这个问题也很好理解,那就是:
距离当前节点越远的节点对当前节点处理影响越小。
这也就导致了,RNN虽然可以处理变长或者时序问题,但是无法建模长时间的依赖。
为了解决这个问题,提出了RNN的变种:LSTM和GRU,GRU是对LSTM的简化。
LSTM通过引入“门”结构,实现保留信息和选择信息功能。
在此基础上,进一步提出了双向LSTM(Bi-LSTM)和双向深度LSTM(Deep Bi-LSTM),可以建模双向依赖。
这在NLP领域是十分重要的,因为这意味着可以对上下文信息同时加以利用,而不仅仅只能利用上文信息。
在这里,不对LSTM和GRU进行详细地阐述,只需要知道LSTM和GRU可以建模长时间的依赖就可以啦,有兴趣的朋友们可以自行百度~
本文主要介绍了几种基本的神经网络:DNN、CNN、RNN,以及网络训练过程中的基本方法:梯度下降法和反向传播算法(BP、BPTT)。
由于细节内容太过繁琐,所以有很多扩展内容无法全部进行介绍,比如LSTM模型、GRU模型、以及在RNN基础上大名鼎鼎的encoder-decoder架构。
对于encoder-decoder架构,将会在NLP部分进行介绍。
对这些内容感兴趣的朋友可以自行百度进行了解,同时欢迎私信进行沟通,共同进步~
如果文中有某些概念理解有误,欢迎各位大神批评指正。