计算图(Computational Graph)的角度理解反向传播算法(Backpropagation)

最近在回看反向传播算法(Backpropagation,BP算法)时,注意到目前各大深度学习框架如Tensorflow,Theano,CNTK等都以计算图(Computational Graph)作为描述反向传播算法的基础。

计算图

计算图是用来描述计算的语言,是一种将计算形式化的方法。在计算图中,计算被表示成有向图,图中的每一个节点表示一个变量(variable),变量可以是标量(scalar)、向量(vector)、矩阵(matrix)、张量(tensor)等。图中的边表示操作(operation),即一个或多个变量的简单函数。如果变量x经过一个操作f计算得到变量y,那么我们画一条从xy的有向边。下图是计算图的一个简单例子:

y=f(g(h(x)))u=h(x)v=g(u)y=f(v)

计算图(Computational Graph)的角度理解反向传播算法(Backpropagation)

同样我们也可以描述多变量函数,下图展示了Logistic回归y=σ(wTx+b)的计算图

计算图(Computational Graph)的角度理解反向传播算法(Backpropagation)

在计算中,有些中间结果在代数表达式中没有名称,但是在图形中是需要的,比如上图中uvu(1)u(2)。当同一个变量多次出现在代数表达式中时,在计算图中需要将其当作不同的变量对待。例如式子y=xex2的计算图如下

计算图(Computational Graph)的角度理解反向传播算法(Backpropagation)

计算表达式的值时,我们从叶子节点开始,顺着有向边逐步归约到根节点即可得到整个表达式的值,可以看作是BP算法的前向传播过程。剩下需要解决的是计算图的求导过程,对应于BP算法的反向传播过程。
首先需要复习下求导的链式法则:
case 1

计算图(Computational Graph)的角度理解反向传播算法(Backpropagation)

因为x的变化会带来y的变化,y的变化最终影响z的变化,所以

dzdx=dzdydydx

图中一个顶点对另一个顶点的导数等于该顶点到另一个顶点的路径上所有导数的乘积。
case 2

计算图(Computational Graph)的角度理解反向传播算法(Backpropagation)

因为z=k(x,y)是一个二元函数,受到xy的影响,而s的变化又同时影响到xy,所以

dzds=dzdxdxds+dzdydyds

当存在从一个顶点到另一个顶点的多条路径时,那么这个顶点对另一个顶点的导数等于所有路径上导数的和。
下面通过两个例子直观展示下计算图求导过程:
Example 1:e=(a+b)*(b+1)

计算图(Computational Graph)的角度理解反向传播算法(Backpropagation)

首先画出表达式e=(a+b)(b+1)的计算图,然后计算出每条边的导数,最后根据求解问题,找出所有的路径。如图,我们可以轻松写出eaebea只对应了黄色箭头路径,因此ea=euua=(b+1)eb对应了两条红色箭头路径,因此eb=euub+evvb=(b+1)+(a+b)
当出现同一个变量多次出现在代数表达式中时,虽然在画计算图时我们将其当作不同的变量对待,但是计算该变量的导数值时,我们需要将图中关于该变量的所有导数值相加。仍然以y=xex2为例:

计算图(Computational Graph)的角度理解反向传播算法(Backpropagation)

因为x在表达式*出现三次x1x2x3,因此我们需要分别计算出yx1yx2yx3,然后将其相加。当计算出每一条边的导数后,就可以将出现在不同位置的相同变量同等对待了,因此

yx1=xex2xyx2=xex2xyx3=ex2yx=yx1+yx2+yx3=ex2+2xex2x2

反向传播算法的计算图

多层神经网络的表达式可以写成:

y=σ(wLσ(w2σ(w1x+b1)+b2)+bL)

对于一个双隐层神经网络,其计算图如图所示:

计算图(Computational Graph)的角度理解反向传播算法(Backpropagation)

图中x是输入数据,是一个向量,w表示层与层之间的连接权重,是一个矩阵,b表示偏置向量,y是网络的输出,C是损失值,是一个标量。为了计算出参数的梯度,首先需要出每条边的偏导数,因为存在顶点是向量和矩阵的情况,所以涉及到向量对向量的导数和向量对矩阵的导数。
向量对向量的导数
对于标量对向量的导数我们已经会求,推广到向量y对向量x的导数时,我们分步将向量y中每一个元素对向量x求偏导,然后将结果组合成一个矩阵,实际也确实是这样。具体的,假设y是m维向量,x是n维向量,将y中每一个元素对x的偏导数横排放成行,最终将形成一个mn的矩阵,这个矩阵就是Jacobian矩阵。以Sigmoid函数作为**函数为例,yz都是向量,因此az是一个方阵,

[a1a2ai]=σ([z1z2zi])

其中ai=11+ezi,因此当ij时,aizj=0,当i=j时,aizj=σ(zi),所以最终的矩阵将是一个对角阵,对角线上的值为σ(zi)

az=[σ(z1)σ(z2)]

向量对矩阵的导数
m维向量ymn维矩阵x求导也是向量中每一个元素对矩阵中每一个元素求偏导,因此将得到m个mn矩阵。这写起来将非常不方便,通常将mn矩阵变平为一个向量,因此结果是一个m(m×n)的矩阵。以u=wx+为例:

[z1z2zi]=[w11w12w21w22][a1a2ai]

对于任意一个zi,其计算结果等于

zi=wi1a1+wi2a2++winan

可以看到,zi只与矩阵w中第i有关,因此ij时,ziwjk=0;当i=j时,ziwjk=ak。所以得到的矩阵中只有第i行有值,并且其值正好等于向量a。所以zw的结果如下

zw=[a1ama1ama1am]

依次求出所有边的导数,如下图

计算图(Computational Graph)的角度理解反向传播算法(Backpropagation)

最终

Cw1=Cyyz2z2a1a1z1z1w1=[Cwij1]

参考文献

*大学李宏毅Machine Learning and having it deep and structured (2017,Spring)