反向传播
现在有:
- 计算得分的函数
- 计算单个样本损失的函数
- 计算整体模型损失的函数和正则化
想要求W的梯度。
如果一个模型的表达式简单,当然可以直接使用微积分的方法进行计算梯度。如果模型的表达式非常复杂(深度神经网络有几百个甚至上千个神经元),该如何求梯度呢?
可以使用计算图的方式来求梯度,因为计算图的每个结点代表一种计算方式,而对每个结点进行求导的时候,只关心该节点本身。
一个SVM模型的计算图如下图所示:
一个使用计算图求梯度的例子:
计算图中绿色数字代表前向传播的结果,红色数字代表反向传播的结果。
∂f/∂f=1,∂f/∂q=z=-4,∂q/∂y=1,根据链式法则,∂f/∂y=(∂f/∂q)*(∂q/∂y)=-4*1=-4
每个结点只用关心自身的梯度(比如∂z/∂x),然后把自身的梯度和后一个结点的梯度(∂L/∂z)相乘,就得到前一个结点的梯度(∂L/∂x)。
在计算图中,可以把任意几个结点组合成一个新的结点,只要能求出该节点的梯度。
- 计算图中加结点会把后结点的梯度直接传递给所有前结点
- 计算图中最大化结点会把后结点的梯度传递给最大的前结点,其他前结点的梯度则为零
- 计算图中乘结点有点类似梯度交换器:x的梯度(-8)=y的值(-4)*后结点的梯度(2)
如果一个结点有多个后结点,那么传回来的梯度应该是所有后结点梯度的和。
向量化的例子,图中对W的梯度少了个转置。
∂f/∂W=(∂f/∂q)*(∂q/∂W)=2qxT
∂f/∂x=(∂f/∂q)*(∂q/∂x)=2WTq
对于每个计算图的结点来说,如果前向传播的时候使用了该节点,那么反向传播时也要计算该节点的梯度。
- 神经网络的结点会非常多,不可能直接写出梯度的公式
- 可以递归调用链式法则求所有输入、参数和中间值的梯度
- 构造计算图的结构,每个结点都实现前向和反向传播的API
- 在前向传播的API中,计算该操作的结果,并保存必要的中间值
- 在反向传播的API中,根据链式法则求出关于该节点输入的梯度
神经网络
两层的神经网络,第二层的输入只用到了第一层输出中大于0的值。
全连接层的计算图:
- 把神经元排列成全连接层
- 对层的抽象可以使用向量化的计算方法
- 神经网络与大脑中的神经元还是有很大差别的
- 一般来说,神经网络中的神经元越多越好,但是也要加强正则化,否则容易产生过拟合