CS231N-Lecture4 Backpropagation&Neural Network
一、概述
上一集结束之后,学到了score function
,可以用SVM
或者Softmax
计算loss
,可以在loss
中增加regularization
来获取更加合理的W
,并且最后可以用Analytic Gradient
(微积分)的方式计算loss function
相对于W
的gradient
来更新W
。如下图。
这一集讲了如何使用链式法则
来反向传播gradients
,来更新W
和b
,这个gradients
反向传播的过程叫做Backpropagation
。
Backpropagation
之后,进入了Neural Network
的介绍。
二、Backpropagation
-
Computational Graph
在计算
gradient
并进行backpropagate(bp)
的时候,借助computational graphs(cg)
可以让整个过程更加清晰(对于新手来说更是这样)。在学习的起步阶段,可以借助它来理解bp
的原理。但是当神经网络复杂了之后,再转换成cg
看起来就很头疼了。就像这样。tensorboard
是cg
可视化的一个很强大的工具。一个
computational graph
是对整个神经网络的直观图形表述。上图中,每一个矩形代表着
input x
和W
;每一个圆代表着一个操作;箭头指明了元素在这个神经网络中的流向,从输入开始,一直到最终的loss
输出。其中,圆被称为一个门
gate
。数据每流经一个门,都会经过相应的数学变换。 -
bp
如何实现上图已经完成了
forward pass
的过程,输入从左到右,经过+
,*
,得到结果f
。上图中有三个输入,
x,y,z
;一个+ gate q
;一个* gate f
;最后得到输出f = 12
。红色框中,是
+
这个操作相对于x
,y
的求导;蓝色框中,是
*
这个操作相对于+
,z
的求导;bp
的过程,就是将运算顺序倒过来,从cg
的最右端开始,利用链式法则(Chain Rule),依次将所有前面已经计算的到的导数,和当前元素的导数相乘,就是当前元素的gradient
。从最右端开始,
f
相对于自身的导数是1
。如下图:继续往左运算,遇到了
* gate
;这个门的算式就是f = qz
,蓝色框中的算式。要求出
z
的gradient
,就是将之前已经计算出的gradient df / df = 1
,与z
本身的gradient
相乘,即(df / df) * (df / dz)
。先求
f
相对于z
的导数,df / dz = q
;由于
q = 3
,因此,z
的gradient df / dz = (df / df) * q = 3
。这个
3
意味着,z
的变化对于f
是正向的。如果z
增加任意H
个单位,那么f
相应增加3H
个单位。计算结果如图。
下面计算
q
的gradient df / dq
。蓝色框中已经写了,
df / dq = z
,并且z = -4
。因此,
df / dq = (df / df) * z = -4
。如图。接下来计算
x
的gradient
。根据
Chain Rule
,x
的gradient df / dx = (df / dq) * (dq / dx)
。因此,
df / dx = -4 * 1 = -4
。如图。点击去看
Khan Academy
对于Chain Rule
的讲解。以此类推,
y
的gradient
也就能计算出来了。下图展示了
bp
的一个简易流程。图中,
x
,y
,f
,z
各是一个节点,称之为node
,每个node
在python中是一个class
。当x
和y
流经f
的时候,f
这个node
已经知道自身相对于x
的gradient
了,这个gradient
叫做local gradient
。在这个简单的网络作forward propagate
的时候,node f
就再已经保存了df / dx
的信息,比如,存放在变量self.local_gradient
中,便于之后back propagate
的时候取出来使用。而
bp
的整个过程,就是最右边开始,把每个节点的local gradient
拿出来,与处于该节点右边的所有节点的local gradient
相乘,就是该节点的最终gradient
。z
节点右边没有节点了,因此z
节点的local gradient
就是dz / dz = 1
,存在self.local_gradient
中。x
节点的gradient
就可以根据f.local_gradient * z.local_gradient
来得到。问题:如果一个节点被多个节点使用,这个节点的
gradient
如何计算?如下图,如果一个节点被多个节点使用,这个节点的
gradient = local gradient + sum(all_previous_gradients)
左边的节点作为输入被之后的两个节点使用,那么在
back propagate
的时候,右边两个节点的gradient
要加起来,再乘以左边节点的local gradient
才能得到左边节点最终的gardient
。下图是
forward pass
和back propagate
的一个简单python实现。在实践中,在数学允许的情况下,多个
gate
可以被合并成一个gate
,那么之前多个gate
的gradient
的计算,可以合并到这一个gate
中进行计算。如下面两张图。上图中,所有的
gradient
都是一个一个依次计算的。但那是其中4
个gate
可以合并。上图中,蓝色框中的多个
gate
,可以组合成一个sigmoid gate
,那么其中4
个单独gate
的gradient
计算可以合并成一个sigmoid gate
的gradient
计算,其结果不变。 -
乐高积木
上图看的不是很清楚,大意就是,
Torch
的Git repo
中可以看到,这个框架就是一大堆神经网络的layer
集合。所以,玩深度学习,玩神经网络,就像是玩乐高积木一样,把自己需要的积木块(layer
)拿出来,拼接在一起,最后组成一个能完成任务的结构。同样的情况在
Caffe
框架中也能看到。 -
Gradients for vectorized code以及Vectorized operations
这一小节关于
Jcobian matrix
以及Vectorized operations
不是很懂,还需要再查资料体会一下。视频中说到了
Jacobian matrix
会是一个维度很高的matrix,实践中是不会去算出整个Jacobian matrix
的。Jacobian matrix
在max()
作为activation function
的时候,又有一种特殊的结构,就是只有左上到右下对角线上才有值,可能是0,可能是非0,而其他值都是0。不是很明白为什么说
Vectorized operations
效率很高,同时提到这个Jacobian matrix
是为了什么…
三、神经网络(Neural Network)
这里讨论的神经网络和大脑的神经网络有一些联系,就是计算机神经网络借鉴了一些大脑神经元的工作原理。但是其复杂度是无法相提并论的,大脑神经元的复杂度远高于计算机神经网络。
-
更加复杂的神经网络
所有之前涉及的内容,是一个最简单的一层神经网络
f = Wx
。如下图。下面,就可以再进一步,增加复杂度,构造一个
2层神经网络
。上图中,
2层神经网络
将max activation function
变成了一个hidden layer
。在这个hidden layer
之后,再和W2
作运算,得到一个Output
。上图中,
hidden layer
有100
个神经元neuron
,这会使这个神经网络比起之前简单的版本要强大很多。比如说在下图中:记得对之前简单的
Linear Classification
进行训练之后得到的这些模板,汽车和马的模板会出现不同的朝向和颜色问题。因为一层的神经网络不能处理不同的颜色,不同的朝向。这个问题在增加hidden layer
和大量的神经元之后就能得到进一步的解决。每个神经元
neuron
的作用就是细分前面输入的数据。比如说,一个神经元可以专门检测红色的,朝向前的汽车;一个神经元可以专门检测黄色的,朝向右边的汽车;以此类推。那么这个神经网络有具备了分类各种颜色和朝向汽车的能力。在
hidden layer
中的每个神经元,可以看作是一个简单的Linear Classifier
。多个神经元组合在一起,就可以学习很复杂的模型。只需要通过扩展下图中的公式,就能构造层数更多,更加复杂的神经网络。
合理的数学编排,可以解决现实生活中很复杂的问题。
-
2层神经网络的简单Python实现
上图是Andrew Trask对2层神经网络的实现,其中用的是
logistic loss
,没有使用SVM
或者Softmax
,但是原理是一样的。 -
编排神经网络
经过编排的神经网络看起来是这样的,中间的
hidden layer
和最后的output layer
被称作fully-connected layers
。问题:为什么要将神经网络编排成这个样子?
像这样将神经网络组织成层是为了更高效率的计算(
Vectorized operation
),输入只需要按照编排好的顺序一层一层流过所有的层即可,不需要额外考虑任何的顺序等因素。 -
不同的neuron数量和regularization时lambda的值
hidden layer
中的neuron数量,差不多就像regularization function
中的lambda
的值一样,被当作hyper parameter
来调整。一般来说,neuron的数量越多越好。neuron越多,这个神经网络越强大。如下图。
上图中,neuron数量越多,分类的效果越好。
但是考虑到时间成本等因素(越多的neuron训练时间相应就越长),找到一个平衡点上的neuron数量才是最好的。
另外,可以看到
regularization
时的lambda
的值,也影响着最后的分类效果。如下图。在当前情况下,
lambda
的值越小,分来效果也就越好。
四、总结
到这里,已经知道如何进行反响传播backpropagation
。
知道能将神经网络编排成层。
这些层的编排,可以让vectorized operation
很方便的进行。
知道了神经网络并不是大脑中的神经网络。
通常情况下,神经网络越复杂,越强大。但是复杂的神经网络意味着更长的训练时间和更小心的规范化(regularization
)。