从零开始学人工智能(18)--数学 · 神经网络(二)· BP(反向传播)

浏览: 703

作者:射命丸咲    Python 与 机器学习 爱好者

知乎专栏:https://zhuanlan.zhihu.com/carefree0910-pyml 

个人网站:http://www.carefree0910.com 

往期阅读:

机器学习综述

从零开始学人工智能(17)--数学 · 神经网络(一)· 前向传导

这一章要讲的就是可能最让我们头疼的 BP(反向传播)算法了。事实上,如果不是要做理论研究而只是想快速应用神经网络来干活的话,了解如何使用 tensorflow 等帮你处理梯度的成熟的框架可能会比了解算法细节要更好一些。但即使如此,了解神经网络背后的原理总是不亏的,在某种意义上它也能告诉我们应该选择怎样的神经网络结构来进行具体的训练

要想知道 BP 算法的推导,我们需要且仅需要知道两点知识:求导及其链式法则;如果想知道原理的话,还需要知道梯度相关的一些理论。同时我们可以从名字上知道,BP 算法和前向传导算法的“方向”刚好相反:前向传导是由后往前一路传导,反向传播则是由前往后一路传播

先从直观上理解一下 BP 的原理。总体上来说,BP 的目的是利用梯度来更新结构中的变量以使得损失函数最小化。这里面就涉及两个问题:

  • 如何获得梯度?

  • 如何更新?

这一章我们会讲第一个问题如何解决、并说一种第二个问题的解决方案,对第二个问题的详细讨论会放在 Optimizers 章节中

在讲如何获得梯度之前,我们先说说梯度是个什么东西。虽然梯度可以牵扯出许多理论性的东西,不过对于 BP 算法而言,我们完全可以先把梯度直观地理解为:

  • 梯度是函数f在某点x0上升最快的方向

换言之,当自变量x沿着梯度方向走时,函数的增长最快
其数学定义则是

image.png

它是向量函数 f 对 n 个变量的偏导组成的向量(顺带一提,我个人的习惯是在推导向量函数的梯度时,先把它分拆成单个的函数进行普通函数的求偏导计算、最后再把它们合成梯度)

在开始进行 BP 的推导前,我们还需要知道这么两件事:

image.png

接下来我们就可以开始进行 BP 的推导了。如前所述,我们会把求解梯度的过程化为若干个求解偏导数的问题,为此我们需要将我们的神经网络进行拆分:

image.png

其中:


代表着第 k 层第 j 个神经元的接收的输入;


代表着对应的激活值

(话说这个人图画得真的好丑

接下来先来看 BP 的思想、再来看具体的步骤

正如前面提到的,BP 是在前向传导之后进行的、从后往前传播的算法,所以我们需要时刻记住这么一个要求:每个 Layer 的梯度除了利用它自身的数据外、仅会利用到:

  • 上一层传过来的激活值和下一层传回来的梯度

  • 该层与下一层之间的线性变换矩阵w

从而我们需要定义一个仅由当前层数据和下一层传回的梯度决定的局部梯度。先给定义:image.png

我们接下来证明它符合要求。由链式法则可知:

image.png

这就是我们想要的梯度image.png。可以看到只要局部梯度符合要求、则梯度也符合要求,从而问题化为了如何求局部梯。

这里会有两种情况(不妨设我们的神经网络一共有 n 层)

  • 当前 Layer 是 CostLayer、也就是说最后一层。此时的“下一层”就Y,从而:

    image.png

    相当长的一个式子,里面涉及的定义也挺多,不过其本质只是链式法则而已 ( σ'ω')σ

  • 当前 Layer 不是最后一层,此时由:image.png

    再由链式法则可知(注:该层每个神经元对下一层所有神经元都会有影响):

    image.png

    其中image.png

    一项就是下一层传播回来的局部梯度,且:

    image.png

    从而可见,局部梯度确实符合要求这些就是求梯度的推导了。虽然有点多,但一步一步看下来的话、相信聪明的观众老爷们理解起来不难 ( σ'ω')σ(然而码公式快把我码死了 )

在得到梯度后该怎么做呢?如我提到过的,梯度当自变量x沿着梯度方向走时,函数的增长最快。现在我们的目的是减少我们的损失C*,所以就让我们的自变量image.png按梯度方向相反的方向走就行了:image.png

其中η叫做学习速率,直观上来说其大小反映的是image.png 梯度反方向走的距离

事实上,BP 算法的优点之一正在于它能利用矩阵运算这个被高度优化的计算过程。由于矩阵运算表达式的推导只是把上面的东西合起来,所以这里就只给出最终结果。为简洁,我们只考虑中间 Layer 的情况,CostLayer 的情况是几乎同理的:

image.png

其中X代表矩阵乘法,image.png代表矩阵的转置,· 代表 element wise 操作。相当简洁不是吗?如果所用的编程语言直接支持矩阵操作的话,BP 算法就可以用一行实现 ( σ'ω')σ

以上就是 BP 算法的全过程。由于 BP 算法确实有些繁复、所以我上面的过程可能会有疏漏,观众老爷们如果有什么意见的话还请多多指教 ( σ'ω')σ

此外值得一提的是,很多常用的激活函数的导函数使用函数值来定义会比使用自变量来定义要更好(所谓更好是指形式上更简单、从而计算开销会更小),具体细节可以参见这篇文章(http://www.carefree0910.com/posts/437097cd/)中间偏后的部分

下一章我们会介绍一些常用的损失函数,这些损失函数不仅在神经网络中有应用、在其它的一些机器学习算法中也会用到

希望观众老爷们能够喜欢~



公众号后台回复关键词学习

回复 人工智能          揭开人工智能的神秘面纱

回复 贝叶斯算法      贝叶斯算法与新闻分类

回复 机器学习          R&Python机器学习

回复 阿里数据          阿里数据系列课程

回复 Python            Python机器学习案例实战

回复 Spark              征服Spark第一季

回复 kaggle             机器学习kaggle案例

回复 大数据             大数据系列视频

回复 数据分析         数据分析人员的转型

回复 数据挖掘         数据挖掘与人工智能

回复 机器学习         R&Python机器学习

回复 阿里数据         阿里数据系列课程

回复 R                     R&Python机器学习入门


推荐 0
本文由 人工智能爱好者社区 创作,采用 知识共享署名-相同方式共享 3.0 中国大陆许可协议 进行许可。
转载、引用前需联系作者,并署名作者且注明文章出处。
本站文章版权归原作者及原出处所有 。内容为作者个人观点, 并不代表本站赞同其观点和对其真实性负责。本站是一个个人学习交流的平台,并不用于任何商业目的,如果有任何问题,请及时联系我们,我们将根据著作权人的要求,立即更正或者删除有关内容。本站拥有对此声明的最终解释权。

0 个评论

要回复文章请先登录注册