手上没有什么教材,都是听网课自学,好多东西都是学了忘忘了翻笔记,心里想着不如记一些电子笔记。纸质笔记不会全部搬运,这篇文章随缘记一些有意思的神经网络知识。
1 反向传播
1.1 概念理解
反向传播(Backpropagation
)是什么先不谈,它的作用就是一点:使Gradient Descent
的计算更快速。
首先,梯度下降的计算过程如下:
在计算过程中,类似下面的计算组成了计算的核心部分。
∂
L
(
θ
)
/
∂
w
1
\partial L(\theta) / \partial w_1
∂L(θ)/∂w1
如果不往深的想,可能这就是一个公式。但是这个公式的计算过程,正是反向传播优化的地方。
首先补充一下高数的链式法则:
我们把
L
(
θ
)
L(\theta)
L(θ) 用
C
n
C^n
Cn 代替:
这样,公式的计算核心就转移到了下面这个公式上:
∂
C
/
∂
w
\partial C / \partial w
∂C/∂w
根据链式法则:
计算z
对w
的偏导很简单,因为z = x1w1+ x2w2 + b。
但是计算C
对z
的偏导就很麻烦了。因为C
是最后的output layer
与标准答案的Loss
,这一项很难计算。所以还得对这一项进行拆解(使用链式法则):
拆解完C
对z
的偏导,我们发现永远都是拆完后的第二项偏导很难算。这样我们就得反复拆下去,直到output layer
。
对于输出层,这个第二项就很好算了,y
就是output layer
的输出值,C
就是选一个Loss
函数将y
和标准答案做运算。这些对于前面的神经元来说计算起来很麻烦,得算到最后一步。
如果我们从前往后求偏导,那每次都得从后往前推一次。既然这样我们不如建一个反向的神经网络,负责去计算每一次的第二项偏导值,且只计算一次。这就是反向传播的精髓所在。
下面两张图是一个神经元的反向,和整个网络的反向:
反向传播能够使梯度的计算更快,就是这样一个原理了。
本小节课件参考:李宏毅2020机器学习
1.2 举例
1.2.1 例1(摘自文章推荐2)
上图为网络的前向传播过程及其公式,现在求:
∂
C
∂
w
1
\frac{\partial C}{\partial w_1}
∂w1∂C
因为C
一般代表loss
,所以会先有:
∂
C
∂
w
1
=
∂
C
∂
y
4
∂
y
4
∂
w
1
\frac{\partial C}{\partial w_1} = \frac{\partial C}{\partial y_4}\frac{\partial y_4}{\partial w_1}
∂w1∂C=∂y4∂C∂w1∂y4
剩下的就按照图,从后往前写:
∂
C
∂
w
1
=
∂
C
∂
y
4
∂
y
4
∂
z
4
∂
z
4
∂
x
4
∂
x
4
∂
z
3
∂
z
3
∂
x
3
∂
x
3
∂
z
2
∂
z
2
∂
x
2
∂
x
2
∂
z
1
∂
z
1
∂
w
1
\frac{\partial C}{\partial w_1} = \frac{\partial C}{\partial y_4}\frac{\partial y_4}{\partial z_4}\frac{\partial z_4}{\partial x_4}\frac{\partial x_4}{\partial z_3}\frac{\partial z_3}{\partial x_3}\frac{\partial x_3}{\partial z_2}\frac{\partial z_2}{\partial x_2}\frac{\partial x_2}{\partial z_1}\frac{\partial z_1}{\partial w_1}
∂w1∂C=∂y4∂C∂z4∂y4∂x4∂z4∂z3∂x4∂x3∂z3∂z2∂x3∂x2∂z2∂z1∂x2∂w1∂z1
下标更整齐一些的话,可以把y4改成x5。
按照链式法则展开成上面这样,除了C
对y4的偏导(因为这个取决于output
和label
到底用了什么loss
函数),其他每一项就都是可以求解了:
∂
C
∂
w
1
=
∂
C
∂
y
4
σ
′
(
z
4
)
w
4
σ
′
(
z
3
)
w
3
σ
′
(
z
2
)
w
2
σ
′
(
z
1
)
x
1
\frac{\partial C}{\partial w_1} = \frac{\partial C}{\partial y_4} \sigma'(z_4)w_4\sigma'(z_3)w_3\sigma'(z_2)w_2\sigma'(z_1)x_1
∂w1∂C=∂y4∂Cσ′(z4)w4σ′(z3)w3σ′(z2)w2σ′(z1)x1
同理,如果要求:
∂
C
∂
b
1
\frac{\partial C}{\partial b_1}
∂b1∂C
则:
∂
C
∂
b
1
=
∂
C
∂
y
4
∂
y
4
∂
z
4
∂
z
4
∂
x
4
∂
x
4
∂
z
3
∂
z
3
∂
x
3
∂
x
3
∂
z
2
∂
z
2
∂
x
2
∂
x
2
∂
z
1
∂
z
1
∂
b
1
\frac{\partial C}{\partial b_1} = \frac{\partial C}{\partial y_4}\frac{\partial y_4}{\partial z_4}\frac{\partial z_4}{\partial x_4}\frac{\partial x_4}{\partial z_3}\frac{\partial z_3}{\partial x_3}\frac{\partial x_3}{\partial z_2}\frac{\partial z_2}{\partial x_2}\frac{\partial x_2}{\partial z_1}\frac{\partial z_1}{\partial b_1}
∂b1∂C=∂y4∂C∂z4∂y4∂x4∂z4∂z3∂x4∂x3∂z3∂z2∂x3∂x2∂z2∂z1∂x2∂b1∂z1
最终:
∂
C
∂
b
1
=
∂
C
∂
y
4
σ
′
(
z
4
)
w
4
σ
′
(
z
3
)
w
3
σ
′
(
z
2
)
w
2
σ
′
(
z
1
)
\frac{\partial C}{\partial b_1} = \frac{\partial C}{\partial y_4} \sigma'(z_4)w_4\sigma'(z_3)w_3\sigma'(z_2)w_2\sigma'(z_1)
∂b1∂C=∂y4∂Cσ′(z4)w4σ′(z3)w3σ′(z2)w2σ′(z1)
1.2.2 例2 BPTT(摘自文章推荐1)
BPTT(back-propagation through time)
是RNN
的训练方法,看到BP
就知道本质还是反向传播,只不过RNN
处理的是时间序列的数据,所以要随时间反向传播。
对标准RNN
来说,这是一个前向传播过程。具体的前向传播过程自行查阅链接。
在1.2.1的例子中,前向传播就只是1.2.2例子中的某一列(代表一个时刻)从下往上的过程,损失函数Loss也自然就是一个时刻的反向传播过程。
而1.2.2每一个时刻的Loss,需要追溯这一时刻前所有时刻的信息,由于标准RNN的权值是共享的,即图中的W, U, V都是一样的,所以:以L(t)
对W
求偏导为例
∂
L
(
t
)
∂
W
=
∑
k
=
1
t
.
.
.
\frac{\partial L^{(t)}}{\partial W} = \sum_{k=1}^t ...
∂W∂L(t)=k=1∑t...
而1.2.2例子的总Loss,即为:
L
=
∑
t
=
1
n
L
(
t
)
L = \sum_{t=1}^nL^{(t)}
L=t=1∑nL(t)
举个栗子:
如果要求在第三个时刻L
对W
的偏导,即:
∂
L
(
3
)
∂
W
\frac{\partial L^{(3)}}{\partial W}
∂W∂L(3)
L(3) 不仅会影响 h(t) 到 h(t+1) 的 W
,前面两个W
也会影响,这就是和上一个例子最大的区别。
我们按照上图的①②③可以写出:
∂
L
(
3
)
∂
W
=
∂
L
(
3
)
∂
o
(
3
)
∂
o
(
3
)
∂
h
(
3
)
∂
h
(
3
)
∂
W
+
∂
L
(
3
)
∂
o
(
3
)
∂
o
(
3
)
∂
h
(
3
)
∂
h
(
3
)
∂
h
(
2
)
∂
h
(
2
)
∂
W
+
∂
L
(
3
)
∂
o
(
3
)
∂
o
(
3
)
∂
h
(
3
)
∂
h
(
3
)
∂
h
(
2
)
∂
h
(
2
)
∂
h
(
1
)
∂
h
(
1
)
∂
W
\frac{\partial L^{(3)}}{\partial W} = \frac{\partial L^{(3)}}{\partial o^{(3)}}\frac{\partial o^{(3)}}{\partial h^{(3)}}\frac{\partial h^{(3)}}{\partial W} + \frac{\partial L^{(3)}}{\partial o^{(3)}}\frac{\partial o^{(3)}}{\partial h^{(3)}}\frac{\partial h^{(3)}}{\partial h^{(2)}} \frac{\partial h^{(2)}}{\partial W} + \frac{\partial L^{(3)}}{\partial o^{(3)}}\frac{\partial o^{(3)}}{\partial h^{(3)}}\frac{\partial h^{(3)}}{\partial h^{(2)}}\frac{\partial h^{(2)}}{\partial h^{(1)}} \frac{\partial h^{(1)}}{\partial W}
∂W∂L(3)=∂o(3)∂L(3)∂h(3)∂o(3)∂W∂h(3)+∂o(3)∂L(3)∂h(3)∂o(3)∂h(2)∂h(3)∂W∂h(2)+∂o(3)∂L(3)∂h(3)∂o(3)∂h(2)∂h(3)∂h(1)∂h(2)∂W∂h(1)
把每一个L(t)(t从1~n)表示出来,最后累加,这个偏导就求出来了。
题外话:
这样的偏导既包含了空间信息,也包含了时间信息,因此后来也被STBP方法借鉴了思路。
那么相应的,L在第三个时刻对U的偏导数为:
∂
L
(
3
)
∂
U
=
∂
L
(
3
)
∂
o
(
3
)
∂
o
(
3
)
∂
h
(
3
)
∂
h
(
3
)
∂
U
+
∂
L
(
3
)
∂
o
(
3
)
∂
o
(
3
)
∂
h
(
3
)
∂
h
(
3
)
∂
h
(
2
)
∂
h
(
2
)
∂
U
+
∂
L
(
3
)
∂
o
(
3
)
∂
o
(
3
)
∂
h
(
3
)
∂
h
(
3
)
∂
h
(
2
)
∂
h
(
2
)
∂
h
(
1
)
∂
h
(
1
)
∂
U
\frac{\partial L^{(3)}}{\partial U} = \frac{\partial L^{(3)}}{\partial o^{(3)}}\frac{\partial o^{(3)}}{\partial h^{(3)}}\frac{\partial h^{(3)}}{\partial U} + \frac{\partial L^{(3)}}{\partial o^{(3)}}\frac{\partial o^{(3)}}{\partial h^{(3)}}\frac{\partial h^{(3)}}{\partial h^{(2)}} \frac{\partial h^{(2)}}{\partial U} + \frac{\partial L^{(3)}}{\partial o^{(3)}}\frac{\partial o^{(3)}}{\partial h^{(3)}}\frac{\partial h^{(3)}}{\partial h^{(2)}}\frac{\partial h^{(2)}}{\partial h^{(1)}} \frac{\partial h^{(1)}}{\partial U}
∂U∂L(3)=∂o(3)∂L(3)∂h(3)∂o(3)∂U∂h(3)+∂o(3)∂L(3)∂h(3)∂o(3)∂h(2)∂h(3)∂U∂h(2)+∂o(3)∂L(3)∂h(3)∂o(3)∂h(2)∂h(3)∂h(1)∂h(2)∂U∂h(1)
因此,根据上面两个式子可以写出L在t时刻对W和U偏导数的通式:
∂
L
(
t
)
∂
W
=
∑
k
=
1
t
∂
L
(
t
)
∂
o
(
t
)
∂
o
(
t
)
∂
h
(
t
)
(
∏
j
=
k
+
1
t
∂
h
(
j
)
∂
h
(
j
−
1
)
)
∂
h
(
k
)
∂
W
\frac{\partial L^{(t)}}{\partial W} = \sum_{k=1}^t\frac{\partial L^{(t)}}{\partial o^{(t)}}\frac{\partial o^{(t)}}{\partial h^{(t)}}(\prod_{j=k+1}^t\frac{\partial h^{(j)}}{\partial h^{(j-1)}})\frac{\partial h^{(k)}}{\partial W}
∂W∂L(t)=k=1∑t∂o(t)∂L(t)∂h(t)∂o(t)(j=k+1∏t∂h(j−1)∂h(j))∂W∂h(k)
∂
L
(
t
)
∂
U
=
∑
k
=
1
t
∂
L
(
t
)
∂
o
(
t
)
∂
o
(
t
)
∂
h
(
t
)
(
∏
j
=
k
+
1
t
∂
h
(
j
)
∂
h
(
j
−
1
)
)
∂
h
(
k
)
∂
U
\frac{\partial L^{(t)}}{\partial U} = \sum_{k=1}^t\frac{\partial L^{(t)}}{\partial o^{(t)}}\frac{\partial o^{(t)}}{\partial h^{(t)}}(\prod_{j=k+1}^t\frac{\partial h^{(j)}}{\partial h^{(j-1)}})\frac{\partial h^{(k)}}{\partial U}
∂U∂L(t)=k=1∑t∂o(t)∂L(t)∂h(t)∂o(t)(j=k+1∏t∂h(j−1)∂h(j))∂U∂h(k)
2 ResNet
2.1 为什么需要ResNet
结合公式,由上述前向传播的过程可知:
∏
j
=
k
+
1
t
∂
h
(
j
)
∂
h
(
j
−
1
)
=
∏
j
=
k
+
1
t
ϕ
′
⋅
W
\prod_{j=k+1}^t\frac{\partial h^{(j)}}{\partial h^{(j-1)}} = \prod_{j=k+1}^t \phi'\cdot W
j=k+1∏t∂h(j−1)∂h(j)=j=k+1∏tϕ′⋅W
也就是说,整体的偏导公式是对激活函数的导数的累乘,那当累乘足够多时,会不会产生一些问题呢?下面是sigmoid
、tanh
及其对应导数的图片,其他激活函数图片可以自行查询。
可以观察到sigmoid
函数的导数范围是(0, 0.25],tanh
函数的导数范围是(0, 1]。这样的导数范围在累乘后,结果肯定会越来越小,从而造成梯度消失。
这样的话,我们在设计网络时,更深的网络不一定会带来更好的结果,也是这个原因。
2.2 ResNet解决思路
还没有彻底理解,待议。。。。
3 LSTM的理解
LSTM有很多变体,下面这张图是当时老师教的,这里记录一下:
3.1 三个门的理解
fgate:控制从cell中丢弃哪些信息
igate:确定什么样的新信息要被存放在cell中
ogate:确定输出什么样的值
h:新的候选值
三个门的作用可以理解为yes or no
,h的作用可以理解为what
。
3.2 激活函数的选择
三个σ:sigmoid函数选择更新内容
其他的act:tanh、ReLU、GeLU等,创建新的候选值
3.3 流程
首先,由fgate决定从cell中丢弃哪些信息。
其次,由igate和h决定什么样的新信息要存放在新的cell中。非要分开理解的话,可以这样理解:igate决定什么样的信息我们要更新(yes or no),h决定输入怎样的新信息(what)。
最后,fgate和igate、h对cell更新,从celli-1→celli,由ogate控制要输出哪些信息(或者说信息都给ogate,它决定输不输出)。
3.4 结合表达式理解
4 CNN的理解(参考链接2-3))
这一部分是因为写代码时想不通conv2d
的参数,所以想着记录一下。
4.1 例子
下面的例子,param
1、2、3分别代表:height
, width
, channel
。一般卷积核(kernel_size
)这个参数只用给出size
(即height
, width
),不用给出channel
。为了方便理解,先给出channel
,见eg1
:
eg1
图片样本:[6, 6, 3]
卷积核:[3, 3, 3]
output → [4, 4, 1]
如果没有卷积核的channel
,见eg2
:
eg2
图片样本:[5, 4, 1]
卷积核:[2, 3]
output → [4, 2, 未知]
(output channel取决于Conv2d的参数)
比如图片样本是[5, 4, 1]
,现在进行nn.Conv2d(1, 4, (2, 3))
操作,那么输出的图片就是[4, 2, 4]
,前两维的4
和2
是由样本size
和、kernel size
共同决定的,最后一维的4
是自己规定的,output channel
是多少,自己定义就好,torch会自动给你匹配你卷积核需要的channel
数。
5 参考文献
1)RNN训练算法-BPTT:RNN
2)梯度消失、梯度爆炸、常用激活函数对比分析:常用的激活函数(Sigmoid、Tanh、ReLU等)