本文是学习3Blue1Brown“深度学习”系列视频之后做的学习笔记。原视频首发YouTube,我看的是B站版,下面分享的链接也是B站版。
Part1视频
Part2视频
Part3视频
本人学习这一知识点主要是为未来继续学习深度学习相关知识做铺垫。我本人有一定的机器学习基础,学过梯度下降等基本概念。本文是基于本人的背景知识所做,因此详略上可能不完全满足您的要求,如有解释不清之处可以直接评论。
其他所叙谬误也可以直接评论。我是优快云常驻居民,经常看账号的,回复飞快。
Part 1:深度学习之神经网络的结构
- 本课程中讲的是最简单的多层感知器MLP
- 神经元Neuron:可以视为装有一个数字(激活值0-1之间)的容器
在MNIST例子中,第一层神经元就是所有的像素值。
最后一层10个神经元代表0-9这十个数字(系统认为输入的图像对应着哪个数字的可能性)。 - 神经网络中信号的传递方式,是每一层数字逐渐向后传递
在示例中,就是每一层的图像(模式)逐渐向下一层传递,输出层最亮的神经元就代表神经网络的选择。-
计算第一步:对每一条边赋权,对每一个神经元,计算出其上一层与之相连的神经元的激活值和对应权的加权和
理解这个权:可以将其想象为图像像素表格中的阈值,越接近0则其连接的神经元越不影响结果,越接近1则越重要(这些接近1的神经元组成的图案,就是要识别的模式)(这种接近1的神经元被称为激发神经元),这样能在出现模式时达到加权和最大的效果 -
计算第二步:将加权和转化到0-1之间,如使用sigmoid函数
这样就会得到一个对加权和“有多正”的打分 -
为了防止过早激活(如希望加权和大于10时才为正),添加一个偏置bias
-
加权和说明下一层神经元关注什么模式,偏置说明加权和要多大时神经元的激发才有意义
-
- 整个神经网络分层,是试图将具象的任务拆分为抽象的层级,由每一层完成。
我们的理想状态是隐藏层最后一层每个神经元各能识别一种模式,到输出层就判断这些模式组合对应的输出即可。隐藏层倒数第二层则识别出组成这些模式的部分……以此类推。
(当然真实的网络不会像想象那样识别出短边→长边→整个数字这么具体清晰) - learning的过程就是学到一大堆权重和偏置的过程
- 加权和的矩阵表示(下标是神经元编号,上标是层数)
这个sigmoid函数是对每个元素取一次sigmoid
这样就能更简洁地表达网络各层间激活值的转化: - 将每个神经元看作一个函数更准确:输入是上一层神经元的激活值,输出是0-1之间的值。事实上整个神经网络就是个函数,输入输入值,输出输出层的向量
- 其实激活函数现在用sigmoid的少,ReLU(线性整流单元)的多
sigmoid学得慢
ReLU在特别深的网络上表现较好
Part 2:深度学习之梯度下降法
- 神经元之间连接的权重类似于连接的强弱,偏置值表明神经元是否容易被激活
- 在训练神经网络前先随机设置权重和偏置值,然后根据下面所讲述的方式来逐步更新参数,最终学到所需的参数
- 代价函数Cost Function:对每一个训练样本来说,是输出向量与真实向量每个元素差值求平方的总和;对整个网络来说是所有训练样本的代价的平均值(经验风险),衡量这个模型有多烂
这个代价函数的输入是全部的参数(权重和偏置),输出代价(一个标量),参数是若干训练样本
我们希望通过调整参数,使得在所有训练样本上的这个代价函数最小 - 求函数最小值的方法:通过梯度下降获得函数的局部最小值local minima(在实践中可以使每步的大小和梯度成比例,有助于防止调过头)
- 为了能够进行梯度下降,代价函数需要是平滑的(因为神经网络中的激活值是连续的)
- 对参数向量求梯度后,得到负梯度值向量。
负梯度值向量的每个值衡量对应参数改变后对代价函数结果的影响程度(改变哪些参数,代价下降更快)(代价函数对这个参数有多敏感)(修改这个参数的性价比)
Part 3:深度学习之反向传播算法
我的理解是:反向传播就是从最后一层开始,通过后一层梯度来计算前一层梯度,一直往前推,这样一个过程。
本来我们想计算一个参数的梯度,需要计算它后面网络层的相应梯度,这是一个递归问题,所以直接从最后一层开始算,这样前面的网络层梯度就可以用后面层的梯度直接计算得到结果。一层层往前推,直到算完结果。所以叫反向传播。
推出梯度后就可以根据梯度下降算法进行参数更新。
……虽然PyTorch的autograd可以自动干这件事所以其实在实践中不需要应用原理就是了。
上篇:直观理解反向传播
- 理论上,由于代价函数的计算是基于所有训练数据的,所以在梯度下降时也需要用所有训练数据来计算梯度。以下首先基于此假设进行讲解,在后文讲述具体对此问题的处理方式。
- 在一次训练后,每个训练样本都有对应的输出层神经元和真实输出。我们想要通过改变参数而使二者接近,也就是降低代价函数。
对某一希望获得高激活值的神经元来说,与它连接的前一层神经元中,激活值较高的神经元与之相连的权重如果提高,对它激活值的提高比其他权重的提高更有效。
因此这个神经元希望:偏置↑,权重↑(与对应前一层神经元激活值成比例),前一层神经元激活值↑(与对应权重成比例)
其他神经元对此的期待可能不一样。最后将同层所有神经元的期待加起来。
这样一层层反向传播,每一层都得到对上一层神经元激活值的期待 - 对所有训练样本进行反向传播,最后将所有参数的改变值求平均(得到的结果是负梯度乘一个常数)
- 随机梯度下降:将所有训练样本分成很多minibatch,对每个minibatch进行上一步所说的反向传播(能得到近似值)
- Human-in-the-loop approach:人工打标
有多少智能,背后就有多少人工
下篇:反向传播的微积分原理
- 以一个四层的、每层只有一个神经元的简化网络来举例
- 我们需要理解代价函数对各个参数有多敏感(微小扰动,导数/偏导数)
参数之间逐层影响的形式如图所示:这个链条可以往上继续延伸,循环往复其影响因素
用链式法则得到一个代价函数对参数的敏感程度(偏导数)(微小扰动沿链条传播):
∂ C 0 ∂ w ( L ) = ∂ z ( L ) ∂ w ( L ) ∂ a ( L ) ∂ z ( L ) ∂ C 0 ∂ a ( L ) \dfrac{\partial C_0}{\partial w^{(L)}}=\dfrac{\partial z^{\left( L\right) }}{\partial w^{\left( L\right)} } \dfrac{\partial a^{\left( L\right) }}{\partial z^{\left( L\right)} } \dfrac{\partial C_0}{\partial a^{\left( L\right)} } ∂w(L)∂C0=∂w(L)∂z(L)∂z(L)∂a(L)∂a(L)∂C0
原函数:
C 0 = ( a ( L ) − y ) 2 z ( L ) = w ( L ) a ( L − 1 ) + b ( L ) a ( L ) = σ ( z ( L ) ) C_0=(a^{(L)}-y)^2 \\ z^{(L)}=w^{(L)}a^{(L-1)}+b^{(L)} \\ a^{(L)}=\sigma(z^{(L)}) C0=(a(L)−y)2z(L)=w(L)a(L−1)+b(L)a(L)=σ(z(L))
通过原函数计算得到偏导数:
∂ C 0 ∂ a ( L ) = 2 ( a ( L ) − y ) ∂ a ( L ) ∂ z ( L ) = σ ′ ( z ( L ) ) ∂ z ( L ) ∂ w ( L ) = a ( L − 1 ) \dfrac{\partial C_0}{\partial a^{(L)}}=2(a^{(L)}-y) \\ \dfrac{\partial a^{(L)}}{\partial z^{(L)}}=\sigma '(z^{(L)}) \\ \dfrac{\partial z^{(L)}}{\partial w^{(L)}}=a^{(L-1)} ∂a(L)∂C0=2(a(L)−y)∂z(L)∂a(L)=σ′(z(L))∂w(L)∂z(L)=a(L−1)
代入链式法则公式,得到 ∂ C 0 ∂ w ( L ) = ∂ z ( L ) ∂ w ( L ) ∂ a ( L ) ∂ z ( L ) ∂ C 0 ∂ a ( L ) = a ( L − 1 ) σ ′ ( z ( L ) ) 2 ( a ( L ) − y ) \dfrac{\partial C_0}{\partial w^{(L)}}=\dfrac{\partial z^{\left( L\right) }}{\partial w^{\left( L\right)} } \dfrac{\partial a^{\left( L\right) }}{\partial z^{\left( L\right)} } \dfrac{\partial C_0}{\partial a^{\left( L\right)} }=a^{(L-1)}\sigma '(z^{(L)})2(a^{(L)}-y) ∂w(L)∂C0=∂w(L)∂z(L)∂z(L)∂a(L)∂a(L)∂C0=a(L−1)σ′(z(L))2(a(L)−y)
对所有的训练样本,其偏导就是求平均值: ∂ C ∂ w ( L ) = 1 n ∑ k = 0 n − 1 ∂ C k ∂ w ( L ) \dfrac{\partial C}{\partial w^{(L)}}=\frac{1}{n}\sum^{n-1}_{k=0}\dfrac{\partial C_k}{\partial w^{(L)}} ∂w(L)∂C=n1∑k=0n−1∂w(L)∂Ck
对偏置的计算过程类似: ∂ C 0 ∂ b ( L ) = ∂ z ( L ) ∂ b ( L ) ∂ a ( L ) ∂ z ( L ) ∂ C 0 ∂ a ( L ) = σ ′ ( z ( L ) ) 2 ( a ( L ) − y ) \dfrac{\partial C_0}{\partial b^{(L)}}=\dfrac{\partial z^{\left( L\right) }}{\partial b^{\left( L\right)} } \dfrac{\partial a^{\left( L\right) }}{\partial z^{\left( L\right)} } \dfrac{\partial C_0}{\partial a^{\left( L\right)} }=\sigma '(z^{(L)})2(a^{(L)}-y) ∂b(L)∂C0=∂b(L)∂z(L)∂z(L)∂a(L)∂a(L)∂C0=σ′(z(L))2(a(L)−y)
用这种方法就可以求出整个代价函数的偏导向量: ∇ C = [ ∂ C ∂ w ( 1 ) , ∂ C ∂ b ( 1 ) , ⋮ ∂ C ∂ w ( L ) , ∂ C ∂ b ( L ) , ] \nabla C=\begin{bmatrix} \dfrac{\partial C}{\partial w^{(1)}}, \\ \dfrac{\partial C}{\partial b^{(1)}}, \\ \vdots \\ \dfrac{\partial C}{\partial w^{(L)}}, \\ \dfrac{\partial C}{\partial b^{(L)}}, \end{bmatrix} ∇C= ∂w(1)∂C,∂b(1)∂C,⋮∂w(L)∂C,∂b(L)∂C,
- 每一层有多个神经元的非简化情况:
(上标是层数,下标是神经元在该层中的标号)
z j ( L ) = w j 0 ( L ) a 0 ( L − 1 ) + w j 1 ( L ) a 1 ( L − 1 ) + w j 2 ( L ) a 2 ( L − 1 ) + b j ( L ) a j ( L ) = σ ( z j ( L ) ) C 0 = ∑ j = 0 n L − 1 ( a j ( L ) − y j ) 2 z_j^{(L)}=w_{j0}^{(L)}a_0^{(L-1)}+w_{j1}^{(L)}a_1^{(L-1)}+w_{j2}^{(L)}a_2^{(L-1)}+b_j^{(L)} \\ a_j^{(L)}=\sigma(z_j^{(L)}) \\ C_0=\sum_{j=0}^{n_L-1}(a_j^{(L)}-y_j)^2 zj(L)=wj0(L)a0(L−1)+wj1(L)a1(L−1)+wj2(L)a2(L−1)+bj(L)aj(L)=σ(zj(L))C0=∑j=0nL−1(aj(L)−yj)2
∂ C 0 ∂ w j k ( L ) = ∂ z j ( L ) ∂ w j k ( L ) ∂ a j ( L ) ∂ z j ( L ) ∂ C 0 ∂ a j ( L ) \dfrac{\partial C_0}{\partial w_{jk}^{(L)}}=\dfrac{\partial z_j^{(L)}}{\partial w_{jk}^{(L)}} \dfrac{\partial a_j^{(L)}}{\partial z_j^{(L)}}\dfrac{\partial C_0}{\partial a_j^{(L)}} ∂wjk(L)∂C0=∂wjk(L)∂zj(L)∂zj(L)∂aj(L)∂aj(L)∂C0
如图所示,可以代入图中上式;最后一个偏导式子再逐层应用后面的层计算的相应下黄框里的上式(就是下式代入)(直至最后一层,应用下黄框里的下式)。
就这很明显是从最后一层开始算更方便,而且中间过程还可以存储,这样反向传播的时候就可以直接将数字代入以减少计算了。所以实际情况下,我们所做的就是反向传播:从最后一层开始算梯度。
∂ C 0 ∂ a k ( L − 1 ) = ∑ j = 0 n L − 1 ∂ z j ( L ) ∂ a k ( L − 1 ) ∂ a j ( L ) ∂ z j ( L ) ∂ C 0 ∂ a j ( L ) \dfrac{\partial C_0}{\partial a_k^{(L-1)}}=\sum_{j=0}^{n_L-1}\dfrac{\partial z_j^{(L)}}{\partial a_k^{(L-1)}} \dfrac{\partial a_j^{(L)}}{\partial z_j^{(L)}}\dfrac{\partial C_0}{\partial a_j^{(L)}} ∂ak(L−1)∂C0=∑j=0nL−1∂ak(L−1)∂zj(L)∂zj(L)∂aj(L)∂aj(L)∂C0
其他学习材料
- 我用到的参考学习材料:反向传播算法维基百科(除对反向传播这一概念进行了讲解外,其外部链接中有一些BP算法的原始材料,还有各种语言的实现等等,虽然我没仔细看,但是感觉应该挺有价值的)
- 3b1b官网
- 其他相关推荐学习材料,来自B站或油管:
- Neural Networks and Deep Learning电子书
- 博客:Home - colah’s blog
- Learning To See [Part 1: Introduction] - YouTube
- Neural Networks Demystified [Part 1: Data and Architecture] - YouTube
- 花书
- 博客:Distill — Latest articles about machine learning
- CS231N课程:含有对CNN等图像学习知识更深层次的讲解
- 深度学习工程师微专业 - 一线人工智能大师吴恩达亲研-网易云课堂 - 网易云课堂 (163.com)
- http://colah.github.io/posts/2015-08-Understanding-LSTMs/
- Stephen Boyd和Lieven Vandenberghe《Convex Optimaization(凸优化)》
- https://www.sohu.com/a/150444351_697750
- https://blog.youkuaiyun.com/aliceyangxi1987/article/details/73327378
- https://blog.youkuaiyun.com/jiangjunshow/article/details/77711593
- How the backpropagation algorithm works
- 《Neural Networks and Deep Learning》配套代码
- Calculus on Computational Graphs: Backpropagation
- 麻省理工学院公开课:人工智能-01 什么是人工智能(课程介绍)-网易公开课 (163.com)