所谓计算图,就是一种语言,这个语言是用来描述一个函数,我们知道neuralnetwork就是一个函数,所以我们需要描述函数的语言。其实graph有很多种定义方法,但是我们通常使用node来表示一个变量,他可以是一个scalar(标量),vector(向量)甚至是tensor(张量),这里的每一个edge代表了一个operation。
y=f(g(h(x))),如何去画计算图,如上图所示,可以分布拆解。
举个具体例子,计算e=(a+b)*(b+1),令c=a+b,d=b+1,则e=c*d,则可以得到如下图计算图。
这个图的好处就是,我们在这个图上算变量的梯度是很容易的。根据这个图算变量的梯度之前,需要先了解一下链式法则。
彪了我一口老血,幸亏我还能看懂。看来这下子接下去要愉快玩耍需要重新拾起数学来了。
用上图加入链式法则。
如果想同时计算和呢?
这样做的好处就是,如果今天是computational graph,你最终的函数的输出只有一个值,你又需要算大量的不同值的偏微分的时候,用reversemode会比刚才的forwardmode还要更有效率,而在做neural network的时候,我们需要的就是reverse mode。
那为什么呢?因为我们要做neuralnetwork的时候,我们需要计算偏微分的对象其实是costfunction(loss function),我们要对costfunction算偏微分,而costfunction的输出就是一个scalar,所以如果你把costfunction用computationalgraph来描述的话,他只有一个输出,那今天我们又要同时算这个network里面所有参数对costfunction的偏微分,所以我们从root开始做reversemode,对costfunction算偏微分是比较有效率的。
那另外一个状况是有时候会有parameter sharing
这件事情在neuralnetwork里面是常常的发生。比如,在CNN里面就有sharevariable,其实RNN他其实也是sharevariable,他把同一个function在整个RNN上反复的使用,他也是sharevariable。
如有一个全连接前馈网络,如果用计算图来计算微分的话,一般的反馈传播有两个阶段,一个是前向,一个是后向。
那接下来就说一说neuralnetwork的东西,上面讲的都是general的东西,那如果有一个fullyconnected feedforward network,那用computationalgraph来算他的微分的话,我们需要怎么去做呢?我们先复习一下,一般的讲法:
一般我们说要算微分就用backpropagation,这个backpropagation里面分成两个阶段,一个是forwardpass,一个是backpass。
所有的network来说,最后costfunction的outputvalue都是一个scalar。为了计算gradient,首先,我们把每个edge上的微分都算出来,然后用reversemode逆向走回来,这样就可以把所有的参数对c的偏微分都算出来。
a和z都是vector,那怎么去算微分的呢?
把vector对vector做微分其实就是jacobian matrix(雅可比行列式)。
把recurrentnetwork转换为computational graph。
简化后如下图。
下一时刻?
计算每一个edge上的偏微分。