http://blog.itpub.net/31077337/viewspace-2156393/web
本文主要是学习BP神经网络的一个总结,其自己也是机器学习中比较基础、适合入门的模型。算法
目前本人对于机器学习也还只是入门状态,对于不少名词仍然是只知其一;不知其二(感受机器学习中的不少术语自己也是模棱两可的),对于不少公式也是不求甚解,所以这篇文章是尝试用本身的语言和理解来复述所学习到的知识,若是有错误之处还望大牛们不吝斧正。网络
霍金说过每多一个数学公式,就会少一半的读者,所以这里也会尽可能少用公式,要用也只用简单易懂的公式。并且我的以为神经网络中的不少公式是能够感性地去认识的,能彻底明白推导过程天然最好,但在不求甚解的状态下能达到感性的认知也未必不是一个快速掌握的好方法。机器学习
另外本文中用到了很多矩阵相关的知识,忘记了的同窗能够看附录中的整理。函数
神经元与激励函数工具
神经元学习
神经元是神经网络的基本组成,若是把它画出来,大概就长成下面这样:测试
图中神经元左边的x表示对神经元的多个输入,w表示每一个输入对应的权重,神经元右边的箭头表示它仅有一个输出。spa
固然神经元也有不少种,下面介绍两种比较基础的。.net
神经元1:感知器
神经网络技术起源于上世纪5、六十年代,当时叫感知机(perceptron),其中的单个神经元咱们能够叫做感知器。感知器的特色具备浓厚的时代气息:其输入输出都是二进制形式的(听说因为计算技术的落后,当时感知器传输函数是用线拉动变阻器改变电阻的方法机械实现的)。
如上图所示,感知器有多个二进制输入(值只能是0或1)X一、X2..Xn,每一个输入有对应的权值W一、W2..Wn(图中没画出来),将每一个输入值乘以对应的权值再求和( ∑XjWj ),而后与一个阈值(threshold) 比较,大于阈值则输出一、小于阈值则输出0。 写成公式的话以下:
若是把公式写成矩阵形式,再用b来表示负数的阈值(即b=-threshold),那就获得了以下公式:
举个栗子
例如你所在的城市将有一个你的偶像的演唱会,你正决定是否观看,你可能会经过如下三个方面来权衡你的决定:
天气好吗?
你的好基友是否愿意陪你去?
是否这个活动距离公共交通很近?(你本身没车)
咱们将这三个因素用对应的二进制变量x1,x2和x3表示。好比,当天气还不错时,咱们有x1=1,天气很差时x1=0;类似的,若是好基友愿意去,x2=1,不然x2=0;对于公共交通x3同理赋值。
而后根据你的意愿,好比让天气权重 w1=6,其余条件权重分别为w2=2,w3=2。权重w1值越大表示天气影响最大,比起好基友加入或者交通距离的影响都大。最后,假设你选择5作为感知器阈值(即b为-5),按照这种选择,这个感知器就能实现这个决策模型:当天气好时候输出1,天气很差时候输出0,不管你的好基友是否愿意去,或者交通是否比较近。
神经元2:Sigmoid神经元
先来认识一个函数:Sigmoid函数,这个单词在某些工具上直译是“乙状结肠”、也还真有某些资料把Sigmoid神经元叫做乙状结肠神经元的。 其实它是一个经常使用的“S”型函数,能够把变量映射到(0,1)区间内,其公式以下:
它的函数图像是以下图如示的“S”型:
那么Sigmoid神经元是什么呢?与感知器有什么区别?
首先,在Sigmoid神经元中,输入的值再也不是二进制,而是0到1之间的任意值。即Xi取值是0到1之间的任意实数。
其次,而Sigmoid神经元的输出也再也不是0或1,而是 σ(wx+b)。 注意"wx+b"是简写(矩阵)形式,请对照上面的感知器的公式。
所以咱们能够得出Sigmoid神经元的公式:
能够发现当z=w?x+b是一个大的正数时,那么σ(z)≈1,而当z=w?x+b是一个很小的负数(“绝对值很大的负数”比较好理解)时,σ(z)≈0。处于这两种状况时,Sigmoid神经元的输出跟感知器是很接近的。只有当w?x+b在一个适度的值,sigmoid神经元和感知器误差才较大。
激励函数
神经元的输入和输出之间具备函数关系,这个函数就称为激励函数。因此上面提到的Sigmoid函数就是激励函数的一种,感知器的那个函数也能够称为阈值(或阶跃)激励函数。
激励函数也叫点火规则,这使它与人脑的工做联系起来。当一个神经元的输入足够大时,就会点火,也就是从它的轴突(输出链接)发送电信号。一样,在人工神经网络中,只要输入超过必定标准时才会产生输出,这就是点火规则的思想。
神经网络的结构
神经网络简单地说就是将多个神经元链接起来、组成一个网络。 本文介绍的是最简单、历史悠久的一种:“多层感知机”(但咱们讲的这个它里面的神经元并非感知器、而是Sigmoid神经元,名词混乱+1),或称之为“多层向前神经网络(Multilayer Feed-Forward Neural Network)”,它的特色是有多层(废话),且神经元之间是全链接的,即后一层的神经元会链接到前一层的每一个神经元(这里定义下从输入层到输出层为从“后”向“前”)。
一个多层感知机的示意图以下,网络的最左边一层被称为输入层,其中的神经元被称为输入神经元。最右边及输出层包含输出神经元,在这个例子中,只有一个单一的输出神经元,但通常状况下输出层也会有多个神经元。中间层被称为隐含层,由于里面的神经元既不是输入也不是输出。
训练神经网络的意义
如今神经元有了,神经网络的结构也有了,如今回到核心的问题上来:咱们拿神经网络干什么? 要怎样使它作到?
训练的目标
按照常识、用人话来讲,神经网络的做用就是咱们预先给它大量的数据(包含输入和输出)来进行训练,训练完成后,咱们但愿它对于未来的真实环境的输入也能给出一个令咱们满意的输出。
损失函数/代价函数(Loss函数)
那么怎样用数学的方式来表示一个输出有多么令咱们满意呢? 这里咱们引入损失函数(或称代价函数、Loss函数)的概念。
现假设有n组包含了输入和真实结果(或称指望结果、指望输出)的样本数据,对于每组输入,咱们的神经网络输出的结果记为fi,真实结果(指望结果)记为yi。
使用数学工具中的MAE(Mean Absolute Error,平均绝对偏差),能够很是直观地表达出输出结果和真实结果的误差,所以咱们能够用MAE来写出一个下面这样的Loss函数,Loss值越大、说明神经网络的输出结果越远离咱们的指望。
也能够用MSE(Mean Squared Error,均方偏差)做为损失函数,MSE能更好地评价数据的变化程度,简单地说由于平方了一下、误差是会被放大的。
将Sigmoid神经元的表达式f(x)=σ(wx+b)代入上面的损失函数中,能够发现x(输入)是固定的,yi(指望结果)也是固定的,让咱们感性地想象一下:实际上影响Loss的只有w和b,而最重要的任务也就是寻找w和b使得Loss最小。
再具象一点,其实对神经网络进行训练的目的就是为每一个神经元找到最适合它的w和b的值,从而使得整个神经网络的输出最接近咱们的指望(说“最”其实有点违反广告法,神经网络最终达到的很难说是问题的最优解)。
注:下面将真正用到的损失函数
在实际中,为了方便求导,通常使用以下的Loss函数:
梯度降低
根据上面的结论,能够把损失(Loss)记做C,而C又只与w和b有关,那么能够当作C是一个关于w和b的函数,以下图所示。注意因为神经网络中其实有大量的“w”和“b”(回忆一下、每一个神经元都有多个权重和一个阈值),所以这里也须要感性的认知。
若是把图画出来,它多是下面这样的:
咱们的目标是找到w和b使C最小,固然上面这张图很容易看出来合适的w和b在哪,但当面对更复杂的状况时、好比下图这样的,应该如何快速地找到C最小的点呢?
这里咱们引入梯度降低算法,原理很简单:把上图看做是一个丘陵地带,想象咱们有一个球放在某个位置,让它“天然地向低处滚”,滚得越低,C就越小,咱们就越高兴。
那么怎样使得它往低处滚呢? (注意这里要搬出全文中第一个比较烧脑的概念了) 微分法则告诉咱们,当w移动Δw、b移动Δb时,有:
因为C表示的是损失,咱们想让球往低处滚,固然是但愿C不断变小,那ΔC应该恒为负,那么Δw、Δb应该如何取值呢? 梯度降低法是这么设计的:
能够看出如此取值可使ΔC恒为负,其中的η称为学习率。
那么如今问题变成了?C/?w、?C/?b,即 C对w 和 C对b 的偏导,这两个鬼东西要怎么求?
反向传播
反向传播(back propagation)是在这种场景下快速求解?C/?w、?C/?b的算法,用了这个算法的多层感知机--也就是这篇文章讲的神经网络--也就叫做BP神经网络(名词混乱+1)。
这一章包含了比较复杂的公式推导过程,我的认为不了解其细节也没有关系、能够跳过这一章(只看“正向传播”一节就行),只要知道有个经典的反向传播算法能够快速求解?C/?w、?C/?b,从而算出Δw和Δb,使得ΔC恒为负、即便得Loss愈来愈小便可。
正向传播
正向传播也能够叫做前馈(因此又有个前馈神经网络的词...),正向传播就是指给神经网络的输入,而后一层一层向前计算输出,最终获得一个输出,这就是正向传播了。
推导前的基本定义
w、a、b的定义
咱们使用 wljk 表示从 (l?1)th 层的 kth 个神经元到 (l)th 层的 jth 个神经元的连接上的权重。例如,下图给出了第二隐藏层的第四个神经元到第三隐藏层的第二个神经元的连接上的权重:
咱们使用 blj 表示在 lth 层 jth 个神经元的误差,使用 alj 表示 lth 层 jth 个神经元的激活值。下面的图清楚地解释了这样表示的含义:
基于上面的定义,能够写出关于单个神经元激活值alj的公式,其中sum(l-1)表示(l?1)th 层的神经元数量:
上面w的表示方法或许很奇怪,但咱们把它写成矩阵形式或许就能发现它的妙处了。用wl矩阵来表示第(l)th 层的w的值,用j做为行,k行为列,那么上面的神经网络中的w3就能够写成:
那么也能够用al矩阵来表示第(l)th 层的a的值,用j做为行,但只有一列,那么al实际上是一个列向量。那么上面的a2能够写成下面很是形象的列向量形式:
同理,b3能够也能够写成一个列向量:
那么由上面的单个神经元激活值alj的公式,能够得出al矩阵的公式:
单个神经元的带权输入zlj
从上面的公式中能够提取出一个中间量zlj:
固然也能够简写成矩阵形式:
zlj其实就是第 l 层第 j 个神经元的激活函数带权输入。
单组数据的损失
前面介绍了损失函数,那么对于某一组输入,其损失(大写的“L”表示输出层)能够写做以下公式(这里比上面的Loss公式少了个n,由于这里只考虑一组输入,而上面的Loss设定是考虑n组数据)。
这个公式一样能够写成矩阵的形式,这里用到了矩阵的模(能够看附录),模的平方即为向量各元素的平方和。
单个神经元的偏差δlj测试
定义 l 层的第 jth 个神经元上的偏差 δlj 为:
而后能够再推演两步:
推导
输出层的偏差矩阵
由上面的单个神经元偏差公式,能够得出输出层偏差矩阵公式(注意这里使用大写的“L”表示输出层,圆圈表示的Hadamard乘积能够看附录):
而因为咱们采用的损失函数很是容易求出C对aL的导,因此公式能够进一步简化成:
某一层的偏差矩阵
首先推导下单个神经元偏差δlj与下一层(l+1层)的关系:
上面推导中比较难理解的多是累加k的由来,这是由于第lth层第jth个神经元会影响到第(l+1)th层的全部神经元,因此在反向计算偏导时须要考虑第(l+1)th层的全部神经元。
而后能够得出第lth层的偏差矩阵(向量)δl的公式:
此次变换出现了矩阵转置,可能也比较难以理解其由来。仔细观察上面wkj会发现其中的j与k的顺序与w的原始定义中的顺序发生了对调,这能够理解成转置的缘由。本身拿一个示例演算一下也能发现从单个神经元偏差到某层神经元的偏差矩阵变换时的规律。
偏差与权重w的关系
在获得了单个神经元的偏差以后,再来看看偏差与w的关系:
和上节的推演同样,若写成矩阵,则是以下形式:
偏差与误差b的关系
与上面w的推导过程一致,容易获得偏差与b的关系:
这个的矩阵形式就很简单了:
总结
经过上面惨无人道的推导,能够发如今通过一次正向传播以后,能够经过输出层的偏差、快速求解出C对每一个w和b的偏导,即?C/?w、?C/?b,再对每一个w和b加上Δw、Δb,从而使得“球往下滚”,C、即Loss愈来愈小,神经网络在朝着咱们指望的方向进行调整。
BP神经网络的训练流程
基于上面的知识,咱们如今能够总结出训练一个神经网络的全流程:
初始化神经网络,对每一个神经元的w和b赋予随机值;
输入训练样本集合,对于每一个样本,将输入给到神经网络的输入层,进行一次正向传播获得输出层各个神经元的输出值;
求出输出层的偏差,再经过反向传播算法,向后求出每一层(的每一个神经元)的偏差;
经过偏差能够得出每一个神经元的?C/?w、?C/?b,再乘上负的学习率(-η),就获得了Δw、Δb,将每一个神经元的w和b更新为 w+Δw、b+Δb;
完成训练以后,通常状况下咱们都能获得一个损失比较小的神经网络。
附录
矩阵
矩阵加法、减法
要求两个矩阵大小(行数、列数)相同,而后相同位置的元素相加/相减。
矩阵乘法
这个应该都还记得,即左边矩阵的一行乘上右边矩阵的一列,所以矩阵相乘要求左边矩阵的列数等于右边矩阵的行数。
转置
把矩阵A的行和列互相交换所产生的矩阵称为A的转置矩阵(即第m行第n列元素转为第n行第m列元素),用符号T表示:
向量
只有一行的矩阵称为行向量,只有一列的矩阵称为列向量。行向量例如:
列向量例如:
PS:向量只是一种特殊的矩阵,矩阵乘法和转置都是能够用在向量上的。
Hadamard乘积:?
假设S和T是两个一样维度的向量,使用S?T来表示按元素的乘积。因此 S?T 的元素就是(S?T)j=SjTj。
向量的模(长度或大小)
在线性代数中,向量的大小用向量两边加双竖线表示,向量的大小就是向量各份量平方和的平方根。若有向量S:
则其模为:
参考资料
知乎:CNN(卷积神经网络)、RNN(循环神经网络)、DNN(深度神经网络)的内部网络结构有什么区别?