内容列表
Lecture 4 Backpropagation and Neural Networks
在讲反向传播之前,先来回顾一下损失函数的整合框架,在使用梯度下降时,我们关注的更多的是
W
W
W权重矩阵对损失
L
L
L的影响,而且这个影响可以很直观的通过权重微分来表现。
反向传播
链式法则
之前说过,在整个网络中,损失与
W
W
W权重有着很直观的关系,那么可不可以直接计算出
W
W
W每个权重变化到底对损失有着什么影响呢,这里引入了偏导数的概念,
d
f
(
x
)
d
x
=
l
i
m
h
→
0
f
(
x
+
h
)
−
f
(
x
)
h
\frac{df(x)}{dx}= lim_{h\to 0}\frac{f(x+h)-f(x)}{h}
dxdf(x)=limh→0hf(x+h)−f(x),其中函数关于每个变量的导数指明了整个表达式对于该变量的敏感程度,这个倒竖既是我们所需要梯度下降的梯度。那么如何计算这个导数呢?这里引入了链式法则:
上面的例子很简单,绿色的数字代表从前向后计算时每个参数的得数,而红色则表示最后的结果对每个参数的偏导数,这个偏导数既是此参数的变化所能影响结果的表现的直观表示,
∂
f
∂
x
=
∂
f
∂
q
∂
q
∂
x
\displaystyle\frac{\partial f}{\partial x}=\frac{\partial f}{\partial q}\frac{\partial q}{\partial x}
∂x∂f=∂q∂f∂x∂q 这个我们高中都学过的链式法则在这里有了很好的体现,其中
∂
f
∂
q
\displaystyle\frac{\partial f}{\partial q}
∂q∂f表示上游梯度,即前项对结果的偏导数也就是前项的梯度,
∂
q
∂
x
\displaystyle\frac{\partial q}{\partial x}
∂x∂q 则表示局部梯度,也就是此项内对参数的影响因子。
反向传播的直观理解
从上面公式可以看出,要想知道参数具体对结果能产生何种影响,那么就要一步一步从后向前推,如果能将此式用于损失与权重的梯度变化的话,那么对权重的梯度下降会更上一层楼!这也就是反向传播的概念。下面是针对一个门通路的链式法则直观图:
下面从一个更加直观的例子就可以看出反向传播的使用方式:
上面就是一个比之前复杂一些的例子,最后一个红色数字1是因为
∂
f
∂
f
=
1
\displaystyle\frac{\partial f}{\partial f} = 1
∂f∂f=1,然后将1看作上游梯度,对
1
x
\displaystyle\frac{1}{x}
x1求导,这之中的
x
x
x 值取上一次前向所得到的数值。最后全部结果为:
其实上面后面几项合起来就是一个常用的激活函数Sigmoid函数:
上图中下面一行是简化版的Sigmoid函数求导的公式,利用这个公式可以很快地从Sigmoid输出结果得到前项梯度,例如:
接下来讨论几个梯度传播的门电路:
- 加法门:进行梯度分配,使得每一个子门路传播后一项的梯度。
- 乘法门:相当于梯度路由,使得每一个子门路分配的梯度等同于另一方进行前向传播的得数。
- 最大值门:最大值门相当于梯度开关,具体是这样的,加入比较的是 x x x与 y y y那么,他们之中谁大,谁的导数即为1,谁小,谁的导数即为0。因为小的数对最终结果是没有任何影响的。下面是具体例子:
还有一个小tip是假如当前门路分为几个支路,那么反向传播时,几个支路的梯度相加就得到了当前的梯度。
矩阵的反向传播
以上我们讨论的一般都是数值之间的操作,而在实际情况中,我们的权重都是以矩阵形式出现的,我们来看一个例子直观展示一下反向传播的操作:
上图中可以看出整个是一个
L
2
L2
L2正则化项,矩阵里面的数也是单独来看的,而且进行权重更新时的梯度矩阵与原矩阵一定是大小相同的。
上面的公式经过简化后可以看出权重矩阵的更新只与训练数据
x
x
x和
W
∗
x
W*x
W∗x的结果相关,而
x
x
x的更新也与权重矩阵更新类似。
神经网络
非生物角度了解神经网络
在将前面的评分函数、损失函数、正则化、最优化、梯度下降、反向传播一股脑地讲完后,终于进入到了主题:神经网络,先抛开生物机制不说,从工程的角度来讲,当一个分类最后的输出结果,也就是我们的评分函数其实并不只由一个权重与一个输入得来,而是很多次评分,也就是很多层评分函数,以下面图为例子:
上图就是一个两层的神经网络,对输入
x
x
x先进行
W
1
W1
W1权重操作,得到了100个评分指标,再进行
W
2
W2
W2权重操作,最后得到10个评分指标,这是一个很浅显的网络,由此也可以加入第三层:
既然神经网络的基础框架我们了解了,那么也就没有什么能够难住我们的了!
接下来是一个很简单的二层神经网络代码:
import numpy as np
from numpy.random import randn
N, D_in, H, D_out = 64, 1000, 100, 10
x, y = randn(N, D_in), randn(N, D_out)
w1, w2 = randn(D_in, H), randn(H, D_out)
for t in range(2000):
h = 1 / (1 + np.exp(-x.dot(w1))) #dot函数为矩阵乘法
y_pred = h.dot(w2)
loss = np.square(y_pred - y).sum() #使用平方和做损失函数
print(t, loss)
grad_y_pred = 2.0 * (y_pred - y)
grad_w2 = h.T.dot(grad_y_pred)
grad_h = grad_y_pred.dot(w2.T)
grad_w1 = x.T.dot(grad_h * h * (1 - h))
w1 -= 1e-4 * grad_w1
w2 -= 1e-4 * grad_w2
如果对上述过程没看懂的话,我画了一个流程图供参考(从前向到后向,有点丑?),使用乘法门性质:
生物角度了解神经网络
接下来从生物神经角度理解神经网络,其实神经网络的一个神经结构就是模仿的大脑的一个神经元结构:
上面图中,左上角为一个神经元,包含完整的细胞体与神经突触与轴突,右下角就是一个仿照的神经元结构,包含外界输入的
w
0
x
0
,
w
1
x
1
,
w
2
x
2
w_0x_0,w_1x_1,w_2x_2
w0x0,w1x1,w2x2在细胞体进行整合操作再进行激活函数激活后输出,其中激活函数为左下角的Sigmoid函数,这个激活函数比较常见,在下节课会仔细讨论每种激活函数的作用与优缺点。
接下来就是神经元们的整合,其实每一层都可以让几个神经元进行并行操作,分别处理数据,还会让过程更加高效:
上图左边为只有一个隐藏层的2层神经网络,右侧为有两个隐藏层的3层神经网络(层数其实意思是输出层与隐藏层的个数),其中全连接层表示本层的所有神经元都与前一层的所有神经元做了连接。
神经网络还要确定网络的尺寸。用来度量神经网络的尺寸的标准主要有两个:一个是神经元的个数,另一个是参数的个数,用上面图示的两个网络举例:
第一个网络有4+2=6个神经元(输入层不算),[3x4]+[4x2]=20个权重,还有4+2=6个偏置,共26个可学习的参数。
第二个网络有4+4+1=9个神经元,[3x4]+[4x4]+[4x1]=32个权重,4+4+1=9个偏置,共41个可学习的参数。
小结
- 从链式法则出发,了解梯度的含义,知道梯度是如何在网络中反向传播的,并且它们是如何与网络的不同部分通信并控制其升高或者降低,并使得最终输出值更高的。
- 在计算反向传播梯度时,了解需要的参数,从而知道在神经网络中,一般的梯度更新是一次前馈,一次后向,一次更新,如此反复地。
- 了解神经网络的模型,还有每个神经元内的激活函数,了解隐藏层与全连接层与神经网络参数的计算。
资料来源:
- 斯坦福CS231n李飞飞计算机视觉视频课程:https://study.163.com/course/courseMain.htm?courseId=1003223001
- CS231n官方笔记授权翻译总集篇:https://zhuanlan.zhihu.com/p/21930884
- CS231n官方PPT:http://vision.stanford.edu/teaching/cs231n/syllabus.html