李宏毅深度学习(2017)

6.计算图&反向传播(Computational Gra

2019-02-19  本文已影响29人  SpareNoEfforts

6.1 Introduction 简介

6.2 计算图 定义

  所谓计算图,就是一种语言,这个语言是用来描述一个函数,我们知道neural network就是一个函数,所以我们需要描述函数的语言。其实graph有很多种定义方法,但是我们通常使用node来表示一个变量,他可以是一个scalar,vector甚至是tensor,这里的每一个edge代表了一个operation。


  看图上的例子
这个图的好处就是,我们在这个图上算变量的梯度是很容易的。
在去根据这个图算变量的梯度之前,我们需要先了解一下链式法则:

那我们还拿刚才那个为例子,加入链式法则:



把每一个箭头的偏微分都算出来。



如果我们想同时\frac{{\partial e}}{{\partial a}}\frac{{\partial e}}{{\partial b}}计算呢(在a=3.b=2的情况下)?


  如果同时算这两者的话,我们需要一个reverse mode(反向做法),我们刚才看的都是正向的做法,从

  我们可能会有parameter sharing的状况,也就是同样的变量,他出现在这个graph多个地方。这个时候要怎么计算他的偏微分呢?
  这件事情在neural network里面是常常的发生。比如,在CNN里面就有share variable,其实RNN他其实也是share variable,他把同一个function在整个RNN上反复的使用,他也是share variable。

  有share variable要怎么去做呢?
  举一个例子,假如有一个函数y = xe^{x^{2}} ,这个式子如果我们用computational graph来描述的话,就是上面图上的样子。接下来计算 \frac {\partial y}{\partial x} ,我们要把graph上的edge上的微分都算出来,我们需要把node上的x看成是不同的x来看待,就假设这些x都是有下标的。
  那算出了edge上的所有偏微分,那\frac {\partial y}{\partial x} 的值是什么呢?我们把那三个x,当成是不同的变量来看,那实际上 \frac {\partial y}{\partial x} 是什么呢?我们这里算出了三个偏微分,它的值并不是一样的,那么实际上 \frac {\partial y}{\partial x} ,意思就是把那算个对x的偏微分都加起来。所以今天要考虑share variable的case,我们就要把同样的参数,先当做不一样的参数来看,然后算完以后再加起来

6.3 前馈网络的计算图

  那接下来就说一说neural network的东西,上面讲的都是general的东西,那如果有一个fully connected feedforward network,那用computational graph来算他的微分的话,我们需要怎么去做呢?我们先复习一下,一般的讲法:
  一般我们说要算微分就用backpropagation,这个backpropagation里面分成两个阶段,一个是forward pass,一个是back pass。


求算:\frac{{\partial C}}{{\partial w_{ij}^l}} = \frac{{\partial z_i^l}}{{\partial w_{ij}^l}}\frac{{\partial {\rm{C}}}}{{\partial z_i^l}}

  那怎么去求error signal(误差信号)呢?


补充一个我的知识盲点:在微积分里面,对多元函数的参数求∂偏导数,把求得的各个参数的偏导数以向量的形式写出来,就是梯度
  1. 首先将原来的整个network进行逆转,那这个network的input就是Cy的偏导,这个network的input是一个vector,这个vector里面存放的是Cy的梯度;
  2. 把这个vector丢进一排的neural里面,这个一排的neural他们的激活函数并不是sigmoid,而是一排OPA(放大器),放大的倍数就是原来没有逆转时候的network的那个neural的激活函数的微分值,得到一组output,这个时候的output就是最后一层的error signal,也就是\delta^{l}
  3. 然后在把这组output乘上一组weight,这一组weight是原来layer L的那组matrix weight的transpose(在forward的时候乘上的是matrix weight [Z = WX+b],在backward乘上的就是weight的transpose)。然后丢到下一组的OPA里面,然后就可以算出error signal的值。
  4. 红色框框值和绿色框框值相乘就可以得到结果。

  那接下来用computational graph来微分,当然在计算微分之前,先来看看network的computational graph,那他长什么样子呢?


  那接下来我们要算gradient descent,也就是微分,那我们算微分的对象并不是y,其实是cost function。这儿有另外一个变量
那么,接下来,我们要计算

接下来我们的问题就是我的az都是vector,那他是怎么去算微分的呢?

我们把vector对vector做微分其实就是jacobian matrix(雅可比行列式)。
我们现在就从c这个地方一路往回走:


我们算

再继续往回走:


因为z^{2}是一个vector,y也是一个vector,那么z^{2}y的偏微分所生成的jacobian matrix是一个方阵(因为他们两个vector的维度一定是相等的)。 如果i\ne j,他们之间没有关系就是0
如果今天用的不是sigmoid function使用的是softmax,那他还是diagonal matrix(对角阵)吗?
答案:不是了,因为在做softmax的时候,z的每一个dimension都会影响到y的每一个dimension,那就没有i\ne j 微分 =0的状况。

然后继续算下去,为了简单,下面把biases去掉:
我们把他们(𝜕𝑧_𝑖^2𝜕𝑎_𝑗^1)的关系写出来,如下图左下所示,因此可以求出偏微分为{W_{ij}}^2

然后我们算z^{2}W^{2}的jacobian matrix:


先假设

然后就可以得到结果:



结果就是最左边的长度是 结果的长度1,最后一个matrix宽是结果的element的数目

好像用computational graph用reverse mode算所有参数的偏微分,感觉好像只有back pass没有forward pass。右边传统的讲法有forward pass和back pass。那右边那个forward pass在哪里?你还是需要forward pass,你想想看,我们要得到这些matrix的真正的值,我们需要a是多少,需要知道节点的value是多少,所以你还是需要先算一个forward pass,把所有节点的值都算出来,你才能算出所有的edge上的偏微分,才能够把一路上的东西都算出来,所以你还是先需要forward pass才能够跑reverse mode,所以和右边那个是一样的。

你想要检查一下左边和右边是不是一样的,右边有transpose,左边没有transpose。为什么?我们算出zc的偏微分以后还要和wz的偏微分相乘。\delta 是一个vector,a也是一个vector,你把这两个vector相乘以后,要得到一个matrix,这个matrix的size和weight matrix的哪个size是一样的,这个时候你需要对backward pass得到的\delta 先做transpose,才能和左边的a乘在一起,所以做完transpose以后, \delta 里面的transpose就不见了,左边和右边算出的结果会是一样的。

6.4 循环网络的计算图(Computational Graph for Recurrent Network)

前面说的是fully connected feedforward network,接下来要说Recurrent network,其实原理都是一样的:

  1. 画出computational graph;
  2. 把偏微分都算出来;
  3. 然后reverse mode跑一把。

先看一下Recurrent network function:


那如果我们把recurrent network转换为computational graph,他会长什么样子呢?

首先有一个input xw相乘得到n(没有在式子中出现)。 这个只是一部分。

如果我们把recurrent network完整的画出来的话(简化):


这是一个时间点,在下一个时间点:


当RNN考虑的是total cost,所以你要把

我们从c开始reverse mode


1,2,3 这三个节点算的偏微分,他们其实是共用参数的,所以你需要把 \frac{\partial C}{\partial W^{h}} 都算出来,然后全部加起来,才是真正的 \frac{\partial C}{\partial W^{h}} 的偏微分。
上一篇 下一篇

猜你喜欢

热点阅读