- 作者:韩信子@ShowMeAI
- 教程地址:http://www.showmeai.tech/tutorials/37
- 本文地址:http://www.showmeai.tech/article-detail/263
- 声明:所有版权,请联系平台和作者,注明来源
本系列为 计算机视觉深度学习(Deep Learning for Computer Vision)》全套学习笔记,相应的课程视频可以在 查看。获取更多信息的方法见文末。
引言
在上一篇 内容中,我们给大家介绍了线性模型的损失函数构建与梯度下降等优化算法,【本篇内容】ShowMeAI切入神经网络,讲解神经网络计算图、反向传播、神经网络结构等相关知识。
本篇重点
- 神经网络计算图
- 反向传播
- 神经网络结构
1.反向传播算法
神经网络训练、梯度下降等方法需要计算损失函数的梯度,核心知识之一是,它利用数学复杂函数梯度的递归求解方法。tensorflow、pytorch等主流AI工具库的核心智能也可以自动微分,在本节中ShowMeAI就结合cs231n第释神经网络的计算图和反向传播。
神经网络反向传播的解释也可以参考ShowMeAI的 中的文章 、、 解释不同深度的网络前向计算和反向传播
1.1 反向传播的标量形式
1) 引例
我们来看一个简单的例子,函数是 f ( x , y , z ) = ( x y ) z f(x,y,z) = (x y) z f(x,y,z)=(x y)z。初值 x = ? 2 x = -2 x=?2, y = 5 y = 5 y=5, z = ? 4 z = -4 z=?/span>4。这是一个可以直接微分的表达式,但是我们使用一种有助于直观理解反向传播的方法来辅助理解。
下图是整个计算的线路图,绿字部分是函数值,红字是梯度。(梯度是一个向量,但通常将对 x x x 的偏导数称为 x x x 上的梯度。)
上述公式可以分为2部分, q = x + y q = x + y q=x+y 和 f = q z f = q z f=qz。它们都很简单可以直接写出梯度表达式:
- f f f 是 q q q 和 z z z 的乘积, 所以 ∂ f ∂ q = z = − 4 \frac{\partial f}{\partial q} = z=-4 ∂q∂f=z=−4, ∂ f ∂ z = q = 3 \frac{\partial f}{\partial z} = q=3 ∂z∂f=q=3
- q q q 是 x x x 和 y y y 相加,所以 ∂ q ∂ x = 1 \frac{\partial q}{\partial x} = 1 ∂x∂q=1, ∂ q ∂ y = 1 \frac{\partial q}{\partial y} = 1 ∂y∂q=1
我们对 q q q 上的梯度不关心( ∂ f ∂ q \frac{\partial f}{\partial q} ∂q∂f 没有用处)。我们关心 f f f 对于 x , y , z x,y,z x,y,z 的梯度。告诉我们可以用「乘法」将这些梯度表达式链接起来,比如
∂ f ∂ x = ∂ f ∂ q ∂ q ∂ x = − 4 \frac{\partial f}{\partial x} = \frac{\partial f}{\partial q} \frac{\partial q}{\partial x} =-4 ∂x∂f=∂q∂f∂x∂q=−4
- 同理, ∂ f ∂ y = − 4 \frac{\partial f}{\partial y} =-4 ∂y∂f=−4,还有一点是 ∂ f ∂ f = 1 \frac{\partial f}{\partial f}=1 ∂f∂f=1
从输入计算到输出(绿色),从尾部开始,根据递归地向前计算梯度(显示为红色),一直到网络的输入端。可以认为,。
上述计算的参考 python 实现代码如下:
# 设置输入值
x = -2; y = 5; z = -4
# 进行前向传播
q = x + y # q 是 3
f = q * z # f 是 -12
# 进行反向传播:
# 首先回传到 f = q * z
dfdz = q # df/dz = q, 所以关于z的梯度是3
dfdq = z # df/dq = z, 所以关于q的梯度是-4
# 现在回传到q = x + y
dfdx = 1.0 * dfdq # dq/dx = 1. 这里的乘法是因为链式法则。所以df/dx是-4
dfdy = 1.0 * dfdq # dq/dy = 1.所以df/dy是-4
'''一般可以省略df'''
2) 直观理解反向传播
反向传播是一个优美的局部过程。
以下图为例,在整个计算线路图中,会给每个门单元(也就是 f f f 结点)一些输入值 x x x , y y y 并立即计算这个门单元的输出值 z z z ,和当前节点输出值关于输入值的(local gradient) ∂ z ∂ x \frac{\partial z}{\partial x} ∂x∂z 和 ∂ z ∂ y \frac{\partial z}{\partial y} ∂y∂z 。
门单元的这两个计算在前向传播中是完全独立的,它无需知道计算线路中的其他单元的计算细节。但在反向传播的过程中,门单元将获得整个网络的最终输出值在自己的输出值上的梯度 ∂ L ∂ z \frac{\partial L}{\partial z} ∂z∂L 。
根据链式法则,整个网络的输出对该门单元的每个输入值的梯度,要用,得到 ∂ L ∂ x \frac{\partial L}{\partial x} ∂x∂L 和 ∂ L ∂ y \frac{\partial L}{\partial y} ∂y∂L 。这两个值又可以作为前面门单元的回传梯度。
因此,反向传播可以看做是门单元之间在通过梯度信号相互通信,只要让它们的输入沿着梯度方向变化,无论它们自己的输出值在何种程度上升或降低,都是为了让整个网络的输出值更高。
比如引例中 x , y x,y x,y 梯度都是 − 4 -4 −4,所以让 x , y x,y x,y 减小后, q q q 的值虽然也会减小,但最终的输出值 f f f 会增大(当然损失函数要的是最小)。
3) 加法门、乘法门和max门
引例中用到了两种门单元:加法和乘法。
- 加法求偏导: f ( x , y ) = x + y → ∂ f ∂ x = 1 ∂ f ∂ y = 1 f(x,y) = x + y \rightarrow \frac{\partial f}{\partial x} = 1 \frac{\partial f}{\partial y} = 1 f(x,y)=x+y→∂x∂f=1∂y∂f=1
- 乘法求偏导: f ( x , y ) = x y → ∂ f ∂ x = y ∂ f ∂ y = x f(x,y) = x y \rightarrow \frac{\partial f}{\partial x} = y \frac{\partial f}{\partial y} = x f(x,y)=xy→∂x∂f=y∂y∂f=x
除此之外,常用的操作还包括取最大值:
f ( x , y ) = max ( x , y ) → ∂ f ∂ x = 1 ( x ≥ y ) ∂ f ∂ y 1 ( y ≥ x ) \begin{aligned} f(x,y) &= \max(x, y) \\ \rightarrow \frac{\partial f}{\partial x} &= \mathbb{1}(x \ge y)\\ \frac{\partial f}{\partial y} &\mathbb{1}(y \ge x) \end{aligned} f(x,y)→∂x∂f∂y∂f=max(x,y)=1(x≥y)1(y≥x)
上式含义为:若该变量比另一个变量大,那么梯度是 1 1 1,反之为 0 0 0。
- 加法门单元是梯度分配器,输入的梯度都等于输出的梯度,这一行为与输入值在前向传播时的值无关;
- 乘法门单元是梯度转换器,输入的梯度等于输出梯度乘以另一个输入的值,或者乘以倍数 a a a( a x ax ax 的形式乘法门单元);max 门单元是梯度路由器,输入值大的梯度等于输出梯度,小的为 0 0 0。
乘法门单元的局部梯度就是输入值,但是是相互交换之后的,然后根据链式法则乘以输出值的梯度。基于此,如果乘法门单元的其中一个输入非常小,而另一个输入非常大,那么乘法门会把大的梯度分配给小的输入,把小的梯度分配给大的输入。
以我们之前讲到的线性分类器为例,权重和输入进行点积 w T x i w^Tx_i wTxi ,这说明输入数据的大小对于权重梯度的大小有影响。具体的,如在计算过程中对所有输入数据样本 x i x_i xi 乘以 100,那么权重的梯度将会增大 100 倍,这样就必须降低学习率来弥补。
。
对于梯度在计算线路中是如何流动的有一个直观的理解,可以帮助调试神经网络。
4) 复杂示例
我们来看一个复杂一点的例子:
f ( w , x ) = 1 1 + e − ( w 0 x 0 + w 1 x 1 + w 2 ) f(w,x) = \frac{1}{1+e^{-(w_0x_0 + w_1x_1 + w_2)}} f(w,x)=1+e−(w 标签: eak系列连接器的分类1fa0连接器撕裂传感器限位开关zwnj95组合式连接器