前言
3Blue1Brown 视频笔记,仅供自己参考
这个章节主要来直观地理解反向传播算法到底在做什么
1. 简介
本期我们来讲反向传播,也就是神经网络学习的核心算法
稍微回顾一下我们之前讲到哪里之后,首先我要撇开公式不提,直观地过一遍这个算法到底在做什么,然后如果你们有人想认真看里头的数学,下个章节我会解释这一切背后的微积分
2. 回顾
如果你看了前两章内容,或者你已经有足够背景直接看这一章内容的话,你一定知道神经网络是什么,以及它如何前馈信息的
这里我们考虑的经典例子就是手写数字识别,数字的像素值被输入到网络第一层的 784 个神经元里,这里我展示的是有 2 层 16 个神经元隐含层以及 10 个神经元的输出层,它代表网络最终给出的选择
我也假设你们已经理解了上期说到的梯度下降法,理解了所谓学习就是指,我们要找到特定的权重偏置从而使一个代价函数最小化
稍许提醒一下,计算一个训练样本的代价需要求出网络的输出与期待的输出之间每一项的差的平方和
然后对于成千上万个训练样本都这么算一遍,最后取平均,这就得到了整个网络的代价值
如果你嫌这还不够复杂的话,上章内容也讲到了我们要求的是代价函数的负梯度,它会告诉你如何改变所有连线上的权重偏置才好让代价下降得最快
本章的中心,反向传播算法,正是用来求这个复杂到爆的梯度的
我希望大家能够把上章中提到的一点牢牢记住,毕竟 13000 维的梯度向量说它是难以想象都不为过
所以这里大家请记住另一套思路,梯度向量每一项的大小是在告诉大家代价函数对于每个参数有多敏感
比如说,假设你已经计算好了负梯度,其中某条线上的权重一项等于 3.2,而对应另一条线上的权重等于 0.1
你可以这么来理解,第一个权重对代价函数的值有 32 倍的影响力,如果你稍微改变一下第一个权重,它对代价值造成的变化就是改变第二个权重同等大小的 32 倍
就我个人而言,我刚开始学习反向传播的时候,我觉得最容易搞混的部分就是各种符号和上标下标,不过,一旦你捋清了算法的思路,算法的每一步其实都挺直观的,其实就是把许许多多微小的调整一层接一层地进行下去而已
3. 直观的演绎示例
所以,开始讲解时,我将完全抛弃所有的符号,给大家一步步解释每一个训练样本会对权重偏置的调整造成怎样的影响
因为代价函数牵扯到对成千上万个训练样本的代价取平均值,所以我们调整每一步梯度下降用的权重偏置也会基于所有的训练样本,原理上是这么说,但为了计算效率,之后咱们会讨个巧,从而不必每一步都非得要计算所有的训练样本
还需要注意一点,我们现在只关注一个训练样本,就是上面这张 2,这一个训练样本会对调整权重和偏置造成怎样的影响呢?
现在假设网络还没完全训练好,那么输出层的激活值看起来就很随机,也许就会出现 0.5、0.8、0.2 等等数值,我们并不能直接改动这些激活值,只能改变权重和偏置值
但记住我们想要输出层出现怎样的变动还是很有用的,因为我们希望图像最终的分类结果是 2,我们希望第三个输出值变大,其他数值变小,并且变动的大小应该与现在值和目标值之间的差呈正比
举个例子,增加数字 “2” 神经元的激活值就应该比减少数字 “8” 神经元的激活值来得重要,因为后者已经很接近它的目标了
那好,我们更进一步就来关注下这一个神经元,我们要让这里面的激活值变大,还记得这个激活值是把前一层所有激活值的加权和加上一个偏置,再通过 sigmoid 或 ReLU 之类的压缩函数最后算出来的吧
所以要增加这个激活值我们有三条大路可走,一增加偏置,二增加权重,或者三改变上一层的激活值
先来看如何调整权重,各个权重它们的影响力各不相同,连接前一层最亮的神经元的权重影响力也最大,因为这些权重会与大的激活值相乘,所以至少对于这一个训练样本而言,增大了这几个权重值对最终代价函数造成的影响就比增大连接黯淡神经元的权重所造成的影响要大上好多倍
请记住当我们说到梯度下降的时候,我们并不只看每个参数是该增大还是减小,我们还看修改哪个参数的性价比最高
顺便一提,这有一点点像描述生物中神经元的网络如何学习的一个理论即 “赫布理论”(Hebbian theory),总结起来就是 “一同激活的神经元关联在一起”。这里权重的最大增长即连接变得更强的部分,就会发生在已经最活跃的神经元和想要更多激发的神经元之间,可以说看见一个 2 时激发的神经元会和 “想到一个 2” 时激发的神经元联系地更紧密,
这里解释一下,我个人对人工神经网络是否真的在模仿生物学上的大脑的工作没有什么发言权,“一同激活的神经元关联在一起” 这句话是要打星号注释的,但作为一个粗略的对照我觉得还是挺有意思的
言归正传,第三个能够增加这个神经元激活值的方法就是改变前一层的激活值,更具体地说,如果所有正权重连接的神经元更亮,所有负权重连接的神经元更暗的话,那么数字 2 的神经元就会更强烈地激发
和改变权重的时候类似,我们想造成更大的影响就要依据对应权重的大小对激活值做出呈比例的改变,当然我们并不能直接改变激活值,我们手头只能控制权重和偏置,但就光对最后一层来说,记住我们能期待的变化还是很有帮助的
不过别忘了,从全局上看这只不过是数字 2 的神经元所期待的变化,我们还需要最后一层其余的神经元的激发变弱
但这其余的每个输出神经元对于如何改变倒数第二层都有各自的想法,所以,我们会把数字 2 神经元的期待和别的输出神经元的期待全部加起来作为对如何改变倒数第二层神经元的指示,这些期待变化不仅是对应的权重的倍数,也是每个神经元激活值改变量的倍数
这其实就是在实现 “反向传播” 的理念了,我们把所有期待的改变加起来就得到了一串对倒数第二层改动的变化量,有了这些我们就可以重复这个过程,改变影响倒数第二层神经元激活值的相关参数,从后一层到前一层,把这个过程一直循环到第一层
放眼全局,还记得我们只是在讨论单个训练样本对所有权重偏置的影响吗?如果我们只关注那个 “2” 的要求,最后网络只会把所有图像都分类成是 “2”,所以你要对其他所有的训练样本同样地过一遍反向传播,记录下每个样本想怎样修改权重与偏置,最后再取一个平均值
这里一系列的权重偏置的平均微调大小,不严格地说就是上章内容提到的代价函数的负梯度,至少是其标量的倍数,这里的不严格指的是我还没有准确地解释如何量化这些微调
但如果你清楚我提到的所有改动,为什么有些数字是其他数字的好几倍以及最后要怎么全部加起来,你就懂得了反向传播的真实工作原理
4. 随机梯度下降
顺带一提,实际操作中如果梯度下降的每一步都用上每一个训练样本来计算的话,那么花的时间就太长了
所以我们一般会这么做,首先把训练样本打乱,然后分成很多组 minibatch,每个 minibatch 就当包含 100 个训练样本就好了
然后你算出这个 minibatch 下降的一步,这不是代价函数真正的梯度,毕竟计算真实梯度得用上所有的样本而非这个子集,所以这也不是下山最高效的一步,然而,每个 minibatch 都会给你一个不错的近似,而且更重要的是,你的计算量会减轻不少
你如果想把网络沿代价函数的表面下山的路径画出来的话,它看上去会有点像醉汉漫无目的地溜下山,但起码步伐很快,而不像是细致入微的人踏步之前先准确地算好下坡的方向,然后再向那个方向谨小慎微地慢慢走一步,这个技巧就叫做 “随机梯度下降”
内容挺多地,我们先小结一下,反向传播算法算的是单个训练样本想怎样修改权重与偏置,不仅是说每个权重参数应该变大还是变小,还包括了这些变化的比例是多大才能最快地降低代价
真正的梯度下降得对好几万个训练范例都这么操作,然后对这些变化值取平均
但算起来太慢了,所以你会先把所有的样本分到各个 minibatch 中去,计算一个 minibatch 来作为梯度下降的一步
计算每个 minibatch 的梯度,调整参数,不断循环,最终你就会收敛到代价函数的一个局部最小值上,此时就可以说,你的神经网络对付训练数据已经很不错了
总而言之,我们实现反向传播算法的每一句代码其实或多或少地都对应了大家已经知道的内容
但有时,了解其中的数学原理只不过是完成了一半,如何把这破玩意儿表示出来又会搞得人一头雾水,那么,在座的如果想深入探讨的话,下一章中我们会把本期的内容用微积分的形式呈现出来,希望看过以后再看其他资料时会更容易接受一些吧
收尾之前,我想着重提一点,反向传播在内,所有包括神经网络在内的机器学习要让它们工作,我们需要非常多的训练数据
我们用的手写数字的范例之所以那么方便,是因为存在着一个 MNIST 数据库,里面所有的样本都已经人为标记好了,所以机器学习领域的人最熟悉的一个难关莫过于获取标记好的训练数据了,不管是叫别人标记成千上万个图像还是去标记别的类型的数据也罢
相关资料
- http://neuralnetworksanddeeplearning.com/chap2.html
- https://github.com/mnielsen/neural-networks-and-deep-learning
- https://colah.github.io/posts/2015-08-Backprop/
结语
这个章节我们主要学习了神经网络的核心即反向传播算法,反向传播算法计算的是单个训练样本想怎样修改权重与偏置才能最快地降低代价,为了提高效率我们会把整个样本分成不同的 batch,之后计算每个 batch 的梯度来调整权重偏置参数,不断循环使代价函数收敛到一个局部最优值
OK,以上就是本章的全部内容了,下章我们来讲反向传播算法背后的微积分,敬请期待😄