李宏毅深度学习笔记 https://datawhalechina.github.io/leeml-notes
李宏毅深度学习视频 https://www.bilibili.com/video/BV1JE411g7XF
背景
梯度下降
假设有很多参数\(\theta\)
选择一组初始值\(\theta^0\)
计算\(\theta^0\)对loss function的gradient,也就是计算loss function 对每个网络里面的参数\(w_1,w_2,...,b_1,b_2...\)的偏微分
更新参数为\(\theta^1\)
在神经网络里,有很多参数,比如做语音识别系统,神经网络通常有7,8层,每层1000个神经元,有上百万个参数。所以\(\Delta L(\theta)\)是个上百万长的向量。反向传播就是用来高效求解这些参数的方法,是梯度下降在神经网络里的延伸。
链式法则
反向传播使用到了链式法则
反向传播
定义一个\(y^n\) 和\(\hat{y}^n\)的距离function \(C^n\),\(C^n\)大说明loss大,参数不好
定义\(L(\theta)\)为总损失函数,对\(w\)偏微分,相当于\(C^n\)对\(w\)的偏微分之和
Forward pass
考虑一个神经元的正向传播,在计算\(z\)的同时已经可以很容易的知道对\(w\)的偏微分
把损失对参数的偏微分\(\large \frac{\partial C}{\partial w}\)看成两个部分:
- \(\large \frac{\partial z}{\partial w}\):forward pass
- \(\large \frac{\partial C}{\partial z}\):backward pass
\(\large \frac{\partial z}{\partial w}\)就是看w前面接的的是什么,\(w_1\)前面接的是\(x_1\),微分后就是\(x_1\)
第一层隐藏层对\(w\)的偏微分是输入层input
第二层隐藏层对\(w\)的偏微分是第一层的output
注意这里都是\(z\)对\(w\)的偏微分,隐藏层的output=\(\sigma(z)\)
Backward pass
z通过激活函数得到a,还要经过之后复杂的process才能得到C
通过链式法则做拆解,假设激活函数是sigmoid,那么\(a=\sigma(z)\) ,\(a\)乘以某个\(w_3\)再加上其他一大堆值得到\(z'\) ,是下一个神经元激活函数的input,同样有\(w_4,z''\)
\(\large \frac{\partial a}{\partial z}\)是sigmoid的微分
\(a\)通过\(z',z''\)去影响C,假设\(a\)后面的层只有两个神经元,则\(\large \frac{\partial C}{\partial a}\)拆解为两项,如果有1000个神经元,则拆解为1000项之和
在计算的时候我们可以先假设知道\(\large \frac{\partial C}{\partial z'},\frac{\partial C}{\partial z''}\)的值
从另外一个观点看\(\large \frac{\partial C}{\partial z}\)
想象成一个新的神经元,\(\large \frac{\partial C}{\partial z'},\frac{\partial C}{\partial z''}\) 是input,\(w_3,w_4\)是对应的权重,再加上一个常数\(\sigma'(z)\)(因为forward pass 的时候z已经算出来了)
之前假设知道\(\large \frac{\partial C}{\partial z'},\frac{\partial C}{\partial z''}\)的值,但最终还是要计算的
情况一:如果要计算的神经元层已经是output层了,通过链式法则就可以计算
\(\large \frac{\partial y_1}{\partial z'}\)只要知道红色神经元的激活函数即可
\(\large \frac{\partial C}{\partial y_1}\)则取决于cost function
情况二:要计算的神经元层不是output层,后面还有其他东西
例如
\(z'\) 通过激活函数得到\(a'\) ,乘以一个权重加上其他东西得到\(z_a,z_b\),再丢进另外两个激活函数里
如果我们知道\(\large \frac{\partial C}{\partial z_a},\frac{\partial C}{\partial z_b}\),就可以计算\(\large \frac{\partial C}{\partial z'},\frac{\partial C}{\partial z''}\)
类似之前的计算方式,但是又会出现同样的问题,要去计算\(\large \frac{\partial C}{\partial z_a},\frac{\partial C}{\partial z_b}\)
如果层数很多,会觉得这样计算很麻烦,要从第一个隐藏层算到输出层
可以转换思路,从后面output算起
先算\(z_5,z_6\)的偏微分,再去算\(z_3,z_4\)的偏微分,这样会觉得简单一点,因为算\(z_3,z_4\)的偏微分需要用到\(z_5,z_6\)的偏微分
\(z_3,z_4\)怎么用到\(z_5,z_6\)的偏微分?
像之前讨论的
\(z_5,z_6\)的偏微分乘以权重和\(\sigma'(z_3),\sigma'(z_4)\),算出\(z_3,z_4\)的偏微分,再乘以权重和\(\sigma'(z_1),\sigma'(z_2)\)算出\(z_1,z_2\)的偏微分
这个步骤就是backward pass
相当于建立了一个新的神经网络,forward pass的激活函数是sigmoid,算backward pass的时候就是建立一个反向的神经网络,激活函数就是\(\sigma'(z)\)
总结
反向传播怎么做?
1.做一个forward pass,同时可以算出\(z对w\)的偏微分
2.做一个backward pass,通过把\(C对z\)的偏微分作为input 反向做一个神经网络