在前馈神经网络中,各神经元分别属于不同的层。每一层的神经元可以接收前一层神经元的信号,并产生信号输出到下一层。第 0 层叫输入层,最后一层叫输出层,其它中间层叫做隐藏层,相邻两层的神经元之间为全连接关系,也称为全连接神经网络( F N N FNN FNN),表现形式如下图所示。

  我们用下面的记号来描述一个前馈神经网络:
     L L L:表示神经网络的层数
     m ( l ) m^{(l)} m(l):表示第 l l l 层神经元的个数
     f l ( ⋅ ) f_l(·) fl​(⋅):表示 l l l 层神经元的激活函数
     W ( l ) W^{(l)} W(l):表示 l − 1 l−1 l−1 层到第 l l l 层的权重矩阵
     b ( l ) b^{(l)} b(l):表示 l − 1 l−1 l−1 层到第 l l l 层的偏置
     z ( l ) z^{(l)} z(l):表示 l l l 层神经元的净输入
     a ( l ) a^{(l)} a(l):表示 l l l 层神经元的输出

  前馈神经网络通过下面公式进行信息传播:
z ( l ) = W ( l ) ∗ a ( l − 1 ) + b ( l ) z^{(l)} = W ^{(l)} * a^{(l−1)} + b^{(l)} z(l)=W(l)∗a(l−1)+b(l)
a ( l ) = f l ( z ( l ) ) a^{(l)} = f_l(z^{(l)}) a(l)=fl​(z(l))
  上面两式也可以得到:
z ( l ) = W ( l ) ∗ f l − 1 ( z ( l − 1 ) ) + b ( l ) z^{(l)} = W^{(l)}* f_{l−1}(z^{(l−1)}) + b^{(l)} z(l)=W(l)∗fl−1​(z(l−1))+b(l)
  或者
a ( l ) = f l ( W ( l ) ∗ a ( l − 1 ) + b ( l ) ) a^{(l)} = f_l(W^{(l)}*a^{(l−1)} + b^{(l)}) a(l)=fl​(W(l)∗a(l−1)+b(l))
  这样,前馈神经网络可以通过逐层的信息传递,得到网络最后的输出 a ( l ) a^{(l)} a(l)。整个网络可以看作一个复合函数 ϕ ( x ; W , b ) ϕ(x; W, b) ϕ(x;W,b),将向量 x x x 作为第1层的输入 a ( 0 ) a(0) a(0),将第 L L L 层的输出 a ( L ) a(L) a(L) 作为整个函数的输出。
x = a ( 0 ) → z ( 1 ) → a ( 1 ) → z ( 2 ) → ⋅ ⋅ ⋅ → a ( L − 1 ) → z ( L ) → a ( L ) = φ ( x ; W , b ) ) x = a(0) → z(1) → a(1) → z(2) → · · · → a(L−1) → z(L) → a(L) = φ(x; W, b)) x=a(0)→z(1)→a(1)→z(2)→⋅⋅⋅→a(L−1)→z(L)→a(L)=φ(x;W,b))
  其中 W , b W, b W,b 表示网络中所有层的连接权重和偏置。

1. 反向传播算法

  上面简单的介绍了前馈神经网络,我们发现一个神经网络的输出好坏是由参数 W , b W,b W,b 决定的,那么训练神经网络的过程其实就是不断的更新参数来得到最好的结果,在前面的pytorch学习(一)-线性回归中使用了损失函数 f f f 来控制模型训练的结果,其本质就是需要计算出 f f f 的梯度 ∇ f \nabla f ∇f,反向传播算法就是一个有效地求解梯度的算法。

1.1 链式法则

  假设有一个函数 f ( x , y , z ) = ( x + y ) z f(x,y,z)=(x+y)z f(x,y,z)=(x+y)z,我们需要对其求微分,当然很多人一眼就可以看出 f ( x , y , z ) f(x,y,z) f(x,y,z) 对 x x x, y y y, z z z 的微分,但是如果函数复杂呢,所以我们换一种方式,假设 q = x + y q=x+y q=x+y, 那么可以求得微分:
∂ f ∂ q = z ; ∂ f ∂ z = q ; ∂ q ∂ x = 1 ; ∂ q ∂ y = 1 \frac{{\partial f}}{{\partial q}} = z;\frac{{\partial f}}{{\partial z}} = q;\frac{{\partial q}}{{\partial x}} = 1;\frac{{\partial q}}{{\partial y}} = 1 ∂q∂f​=z;∂z∂f​=q;∂x∂q​=1;∂y∂q​=1
  但是我们关心的是 ∂ f ∂ x , ∂ f ∂ y , ∂ q ∂ z \frac{{\partial f}}{{\partial x}},\frac{{\partial f}}{{\partial y}},\frac{{\partial q}}{{\partial z}} ∂x∂f​,∂y∂f​,∂z∂q​,所以可以得到:

∂ f ∂ x = ∂ f ∂ q ∂ q ∂ x \frac{{\partial f}}{{\partial x}} = \frac{{\partial f}}{{\partial q}}\frac{{\partial q}}{{\partial x}} ∂x∂f​=∂q∂f​∂x∂q​
∂ f ∂ y = ∂ f ∂ q ∂ q ∂ y \frac{{\partial f}}{{\partial y}} = \frac{{\partial f}}{{\partial q}}\frac{{\partial q}}{{\partial y}} ∂y∂f​=∂q∂f​∂y∂q​
∂ f ∂ z = q \frac{{\partial f}}{{\partial z}} = q ∂z∂f​=q
  从上面我们可以看出,如果需要对函数的元素求导,那么可以一层一层求导,然后将结果乘起来,这就是链式法则,同时也是反向传播算法的核心。

1.2 反向传播算法

  给定一个样本 ( x , y ) (x, y) (x,y),将其输入到神经网络模型中,得到网络输出为 y ′ y' y′。假设损失函数为 L ( y , y ′ ) L(y, y') L(y,y′),要进行
参数学习就需要计算损失函数关于每个参数的导数。对第 l l l 层中的参数权重 W ( l ) W^{(l)} W(l) 和偏置 b ( l ) b^{(l)} b(l) 计算偏导数。
∂ L ( y , y ′ ) ∂ W i j ( l ) = ∂ L ( y , y ′ ) ∂ z l ( ∂ z l ∂ W i j ( l ) ) \frac{{\partial L(y,y')}}{{\partial W_{ij}^{(l)}}} = \frac{{\partial L(y,y')}}{{\partial {z^l}}}(\frac{{\partial {z^l}}}{{\partial W_{ij}^{(l)}}}) ∂Wij(l)​∂L(y,y′)​=∂zl∂L(y,y′)​(∂Wij(l)​∂zl​)

∂ L ( y , y ′ ) ∂ b ( l ) = ∂ L ( y , y ′ ) ∂ z l ( ∂ z l ∂ b ( l ) ) \frac{{\partial L(y,y')}}{{\partial {b^{(l)}}}} = \frac{{\partial L(y,y')}}{{\partial {z^l}}}(\frac{{\partial {z^l}}}{{\partial {b^{(l)}}}}) ∂b(l)∂L(y,y′)​=∂zl∂L(y,y′)​(∂b(l)∂zl​)

  其中 ∂ L ( y , y ′ ) ∂ z l \frac{{\partial L(y,y')}}{{\partial {z^l}}} ∂zl∂L(y,y′)​为目标函数关于第 l l l 层的神经元 z ( l ) z^{(l)} z(l) 的偏导数,称为误差项,所以需要计算三个偏导数,分别为 ∂ L ( y , y ′ ) ∂ z l \frac{{\partial L(y,y')}}{{\partial {z^l}}} ∂zl∂L(y,y′)​, ( ∂ z l ∂ W i j ( l ) ) (\frac{{\partial {z^l}}}{{\partial W_{ij}^{(l)}}}) (∂Wij(l)​∂zl​), ( ∂ z l ∂ b ( l ) ) (\frac{{\partial {z^l}}}{{\partial {b^{(l)}}}}) (∂b(l)∂zl​),可以得到:

∂ z l ∂ W i j ( l ) = ∂ ( W ( l ) a ( l − 1 ) + b ( l ) ) ∂ W i j ( l ) \frac{{\partial {z^l}}}{{\partial W_{ij}^{(l)}}} = \frac{{\partial ({W^{(l)}}{a^{(l - 1)}} + {b^{(l)}})}}{{\partial W_{ij}^{(l)}}} ∂Wij(l)​∂zl​=∂Wij(l)​∂(W(l)a(l−1)+b(l))​
∂ z l ∂ b ( l ) = ∂ ( W ( l ) a ( l − 1 ) + b ( l ) ) ∂ b ( l ) \frac{{\partial {z^l}}}{{\partial {b^{(l)}}}} = \frac{{\partial ({W^{(l)}}{a^{(l - 1)}} + {b^{(l)}})}}{{\partial {b^{(l)}}}} ∂b(l)∂zl​=∂b(l)∂(W(l)a(l−1)+b(l))​
  所以权重矩阵 W ( l ) W^(l) W(l) 的第 i i i 行为 a j ( l − 1 ) a_j^{(l - 1)} aj(l−1)​,偏置为 1。
  因为 z ( l + 1 ) = W ( l + 1 ) a ( l ) + b ( l + 1 ) z^{(l+1)} = W ^{(l+1)}a^{(l)} + b^{(l+1)} z(l+1)=W(l+1)a(l)+b(l+1), 且 a ( l ) = f l ( z ( l ) ) a^{(l)} = f_l(z^{(l)}) a(l)=fl​(z(l)),同时 f l ( ⋅ ) fl(·) fl(⋅) 为按位计算的函数,得到:
∂ z ( l + 1 ) ∂ a l = ( W ( l + 1 ) ) T \frac{{\partial {z^{(l + 1)}}}}{{\partial {a^l}}}=(W^{(l+1)})^T ∂al∂z(l+1)​=(W(l+1))T
∂ a l ∂ z l = d i a g ( f l ′ ( z ( l ) ) ) \frac{{\partial {a^l}}}{{\partial {z^l}}}=diag(f_l'(z^{(l)})) ∂zl∂al​=diag(fl′​(z(l)))

= ∂ L ( y l , y l ′ ) ∂ z l = ∂ ( y l − y l ′ ) ∂ z l = ∂ ( y l − W l a ( l − 1 ) + b l ) ∂ z l = ∂ ( y l − W l f l − 1 ( z ( l − 1 ) ) + b l ) ∂ z l =\frac{{\partial L({y_l},{y_l}')}}{{\partial {z^l}}} = \frac{{\partial ({y_l} - {y_l}')}}{{\partial {z^l}}} = \frac{{\partial ({y_l} - {W^l}{a^{(l - 1)}} + {b^l})}}{{\partial {z^l}}} = \frac{{\partial ({y_l} - {W^l}{f_{l - 1}}({z^{(l - 1)}}) + {b^l})}}{{\partial {z^l}}} =∂zl∂L(yl​,yl​′)​=∂zl∂(yl​−yl​′)​=∂zl∂(yl​−Wla(l−1)+bl)​=∂zl∂(yl​−Wlfl−1​(z(l−1))+bl)​

= > ∂ L ( y , y ′ ) ∂ z l = ∂ L ( y , y ′ ) ∂ z l + 1 ∂ z ( l + 1 ) ∂ a l ∂ a l ∂ z l =>\frac{{\partial L(y,y')}}{{\partial {z^l}}} = \frac{{\partial L(y,y')}}{{\partial {z^{l + 1}}}}\frac{{\partial {z^{(l + 1)}}}}{{\partial {a^l}}}\frac{{\partial {a^l}}}{{\partial {z^l}}} =>∂zl∂L(y,y′)​=∂zl+1∂L(y,y′)​∂al∂z(l+1)​∂zl∂al​
  其中 d i a g ( x ) diag(x) diag(x) 为对角矩阵,其对角线元素为 x x x,⊙ 是向量的点积运算符,表示每个元素相乘。我们用 δ l \delta^l δl来定义第 l l l 层神经元的误差项,那么 :
δ l = d i a g ( f l ′ ( z ( l ) ) ) ⋅ ( W ( l + 1 ) ) T ⋅ δ ( l + 1 ) = f l ′ ( z ( l ) ) ⊙ ( ( W ( l + 1 ) ) T ⋅ δ ( l + 1 ) ) \delta^l= diag(f_l'(z^{(l)})) · (W^{(l+1)})^T · δ^{(l+1)}=f_l'(z^{(l)})\odot ((W^{(l+1)})^T · δ^{(l+1)}) δl=diag(fl′​(z(l)))⋅(W(l+1))T⋅δ(l+1)=fl′​(z(l))⊙((W(l+1))T⋅δ(l+1))
  从上式可以看到,第 l l l 层的误差项可以通过第 l + 1 l+1 l+1 层的误差项计算得到,这就是误差的反向传播。反向传播算法的含义是:第 l l l 层的一个神经元的误差项是所有与该神经元相连的第 l + 1 l+1 l+1 层的神经元的误差项的权重和,然后再乘上该神经元激活函数的梯度。计算出三个偏导之后,重新算出参数的梯度:
∂ L ( y , y ′ ) ∂ W i j ( l ) = δ i ( l ) ∏ i ( a j ( l − 1 ) ) T = δ i ( l ) a j ( l − 1 ) = > ∂ L ( y , y ′ ) ∂ W ( l ) = δ ( l ) ( a ( l − 1 ) ) T \frac{{\partial L(y,y')}}{{\partial W_{ij}^{(l)}}} = \delta _i^{(l)}\prod\nolimits_i {{{(a_j^{(l - 1)})}^T}} = \delta _i^{(l)}a_j^{(l - 1)} = > \frac{{\partial L(y,y')}}{{\partial W_{}^{(l)}}} = \delta _{}^{(l)}{(a_{}^{(l - 1)})^T} ∂Wij(l)​∂L(y,y′)​=δi(l)​∏i​(aj(l−1)​)T=δi(l)​aj(l−1)​=>∂W(l)​∂L(y,y′)​=δ(l)​(a(l−1)​)T

∂ L ( y , y ′ ) ∂ b ( l ) = δ ( l ) \frac{{\partial L(y,y')}}{{\partial b_{}^{(l)}}} = \delta _{}^{(l)} ∂b(l)​∂L(y,y′)​=δ(l)​

2. 自动梯度计算

  神经网络的参数主要通过梯度下降来进行优化的。当确定了风险函数以及网络结构后,我们就可以手动用链式法则来计算风险函数对每个参数的梯度,并用代码进行实现。但是手动求导并转换为计算机程序的过程非常琐碎并容易出错,导致实现神经网络变得十分低效。目前,几乎所有的主流深度学习框架都包含了自动梯度计算的功能,即我们可以只考虑网络结构并用代码实现,其梯度可以自动进行计算,无需人工干预。这样开发的效率就大大提高了,常见的梯度计算有三类:数值微分、符号微分、自动微分。想深究的同学可以看看邱锡鹏老师《神经网络与深度学习》第二张第4.5小结,讲述的很清楚。

3. 梯度优化

  深度学习中主要使用的梯度下降的方法, P y t o r c h Pytorch Pytorch 中有封装 t o r c h . o p t i m torch.optim torch.optim 模块来优化梯度,我这里下降梯度都用 1e-1 代替,具体使用具体设置。主要有以下几种:

3.1 SGD

  随机梯度下降法是梯度下降法的一个小变形,就是每次使用一批数据进行梯度的计算,而不是计算全部数据的梯度。因为现在深度学习的数据量都特别大, 所以每次都计算所有数据的梯度是不现实的,这样会导致运算时间特别长,同时每次都计算全部的梯度还失去了一些随机性, 容易陷入局部误差,所以使用随机梯度下降法可能每次都不是朝着真正最小的方向.但是这样反而容易跳出局部极小点。
   p y t o r c h pytorch pytorch 表示为: t o r c h . o p t i m . S G D ( p a r a m e t e r s , 1 e − 1 ) torch.optim.SGD(parameters, 1e-1) torch.optim.SGD(parameters,1e−1)

3.2 Momentum

  在随机梯度下降的同时,增加动量,其计算基于前面梯度,也就是说参数更新不仅仅基于当前的梯度,也基于之前的梯度
   p y t o r c h pytorch pytorch 表示为: t o r c h . o p t i m . S G D ( p a r a m e t e r s , 1 e − 1 , m o m e n t u m = 0.9 ) torch.optim.SGD(parameters, 1e-1, momentum=0.9) torch.optim.SGD(parameters,1e−1,momentum=0.9)

3.3 Adagrad

  自适应学习率,表现形式为:
w t − η ∑ i = 0 t ( g i ) 2 + ε g t − > w t + 1 {w^t} - \frac{\eta }{{\sqrt {\sum\nolimits_{i = 0}^t {{{({g^i})}^2} + \varepsilon } } }}{g^t} - > {w^{t + 1}} wt−∑i=0t​(gi)2+ε ​η​gt−>wt+1
  我们可以看到学习率在不断变小, 且受每次计算出来的梯度影响 ,对于梯度比较大的参数,它的学习率就会变得相对更小 ,里面的根号特别重要,没有这个根号算法表现非常差。同时 ε \varepsilon ε 是一个平滑参数,通常设置为 1e-4~1e-8,这是为了避免分母为 0。但是自适应学习率在某些情况下一直递减的学习率并不好,这样会造成学习过早停止。
   p y t o r c h pytorch pytorch 表示为: t o r c h . o p t i m . A d a g r a d ( p a r a m e t e r s , 1 e − 1 ) torch.optim.Adagrad(parameters, 1e-1) torch.optim.Adagrad(parameters,1e−1)

3.4 RMSprop

c a c h e t = α ∗ c a c h e t − 1 + ( 1 − α ) ( g t ) 2 cach{e^t} = \alpha *cach{e^{t - 1}} + (1 - \alpha ){({g^t})^2} cachet=α∗cachet−1+(1−α)(gt)2
w t − η c a c h e t + ε g t − > w t + 1 {w^t} - \frac{\eta }{{\sqrt {cach{e^t} + \varepsilon } }}{g^t} - > {w^{t + 1}} wt−cachet+ε ​η​gt−>wt+1
   R M S p r o p RMSprop RMSprop 这里相比较 A d a g r a d Adagrad Adagrad 多了一个衰减 α \alpha α, 这样就不再会将前面所有的梯度平方求和,而是通过一个衰减率将其变小,使用了一种滑动平均的方式,越靠前面的梯度对自适应的学习率影响越小,这样就能更加有效地避免 A d a g r a d Adagrad Adagrad 学习率一直递减太多的问题,能够更快地收敛 。
   p y t o r c h pytorch pytorch 表示为: t o r c h . o p t i m . R M S p r o p ( p a r a m e t e r s , 1 e − 1 ) torch.optim.RMSprop(parameters, 1e-1) torch.optim.RMSprop(parameters,1e−1)

3.5 Adam

  这是一种综合型的学习方法,可以看成是 R M S p r o p RMSprop RMSprop 加上 M o m e n t u m Momentum Momentum 的学习方法,达到比 R M S P r o p RMSProp RMSProp 更好的效果。
   p y t o r c h pytorch pytorch 表示为: t o r c h . o p t i m . A d a m ( p a r a m e t e r s , 1 e − 1 ) torch.optim.Adam(parameters, 1e-1) torch.optim.Adam(parameters,1e−1)

参考

  1. 邱锡鹏:《神经网络与深度学习》 https://nndl.github.io/
  2. 廖星宇:《深度学习之pytorch》

深度学习(四)-前馈神经网络相关推荐

  1. 水很深的深度学习-Task03前馈神经网络

    本文参考 Datawhale:水很深的深度学习 深度学习(四)-前馈神经网络_未名湖畔的落叶-CSDN博客_前馈神经网络 神经元模型   在前馈神经网络中,各神经元分别属于不同的层.每一层的神经元可以 ...

  2. 深度学习3 前馈神经网络

    深度学习3 前馈神经网络 目录 深度学习3 前馈神经网络 1. 神经元模型(M-P) (1)公式 (2)运算 (3)结构 2. 感知机模型 (1)单层感知机 (2)多层感知器 (3)BP算法 1. 神 ...

  3. 深度学习:前馈神经网络

    对深度学习(或称神经网络)的探索通常从它在计算机视觉中的应用入手.计算机视觉属于人工智能领域,因深度学习技术而不断革新,并且计算机视觉的基础(光强度)是用实数来表示的,处理实数正是神经网络所擅长的. ...

  4. 深度学习之前馈神经网络(前向传播和误差反向传播)

    转自:https://www.cnblogs.com/Luv-GEM/p/10694471.html 这篇文章主要整理三部分内容,一是常见的三种神经网络结构:前馈神经网络.反馈神经网络和图网络:二是整 ...

  5. 深度学习入门——前馈神经网络

    前馈神经网络作为深度学习基础中的基础,是很多同学入门深度学习的必经之路.由于马上要迎来考试复习周,在这里简单记录一下学习心得. 感知机模型 感知机(perceptron)是深度学习中最基本的元素,很多 ...

  6. 【深度学习】前馈神经网络

    一.前馈神经网络 思维导图 线性问题分为两个: 1.与门 IN IN OUT 1 1 1 1 0 0 0 1 0 0 0 0 2.或门 IN IN OUT 1 1 1 1 0 1 0 1 1 0 0 ...

  7. 猿创征文|深度学习基于前馈神经网络完成鸢尾花分类

    大家我是猿童学!这次给大家带来的是基于前馈神经网络完成鸢尾花分类! 在本实验中,我们使用的损失函数为交叉熵损失:优化器为随机梯度下降法:评价指标为准确率. 一.小批量梯度下降法 在梯度下降法中,目标函 ...

  8. 日月光华深度学习(四)-计算机视觉-卷积神经网络

    日月光华深度学习-计算机视觉-卷积神经网络 计算机视觉-卷积神经网络 [4.1]--认识卷积神经网络(一) [4.2]--认识卷积神经网络-卷积层和池化层 [4.3]--卷积神经网络整体架构 [4.4 ...

  9. bp 神经网络 优点 不足_深度学习之BP神经网络--Stata和R同步实现(附Stata数据和代码)

    说明:本文原发于"计量经济圈"公众号,在此仅展示Stata的部分.R部分请移步至本人主页的"R语言与机器学习--经济学视角"专栏,或点击下方链接卡跳转. 盲区行 ...

最新文章

  1. html5圆形图片轮播,jQuery超酷响应式圆形图片轮播图特效
  2. 目标识别——SIFT算法
  3. 怎么禁止/开启Ubuntu自动更新升级_豆豆技术派的博客-CSDN博客_ubuntu 自动更新
  4. AbstractQueuedSynchronizer原理分析
  5. httpClient 超时时间设置
  6. jira 8.2.1 安装 及一些常见的坑
  7. Unity3D重要知识点
  8. 关闭 Adobe Flash 沙箱(保护模式)解决Flash崩溃及卡顿问题
  9. [HDU] 2553 N皇后问题-简单深搜
  10. vector 修改 java_java对vector动态数组中的对象排序,以下代码有何问题,如何修改?...
  11. axios跨域携带cookie_vue 本地调试跨域---带cookies(axios)
  12. QT中文乱码的解决方法,一劳永股的解决方法,如下
  13. 《Java 面经手册》PDF,全书5章29节,417页11.5万字,完稿发版!
  14. HTML转PDF问题
  15. 将图片放大如何保持图片的清晰度?
  16. Unity (三) NavMeshAgent之:分层路面导航(王者荣耀,英雄联盟中小兵分三路进攻敌方)...
  17. 请教一个能在WinPE环境下获取系统相关信息的代码
  18. 【转载】在美国找工作秘籍
  19. pdf合并成一个pdf怎么合并
  20. js对节点 属性的操作

热门文章

  1. 如何使用graphpad做柱形图_Graphpad绘制柱形图&散点图
  2. 用友U8不得不说的问题
  3. OUT指令时,就进入了I/O端口读写周期
  4. 安装win10时出现 “windows安装程序无法将windows配置为此计算机的硬件上运行” 解决方案
  5. python选择题题目_【Python测试面试题】面试问题:《我的Padd… - 看准网
  6. linux的电脑 配哪款显卡,27款AMD、NVIDIA显卡大战Linux
  7. Arduino使用点灯科技+小爱同学+WIFI,实现一个设备区分控制多个舵机/电灯
  8. 基于Matlab的各地阳光强度计算
  9. 小程序Swiper组件做日历(周历)左右滑动动态修改数据
  10. 苹果cmsv10蓝色简约响应式小鸟影视主题模板