[NNCS]计算图求导;x=Wu+b

update@2019-06-27 06:48:33
反向传播求导,以前看的教科书比较老,公式推导写起来上标角标很多,也不好记;利用计算图来理解则容易的多。斯坦福的cs231n在Youtube上的2017课程第四节讲到了计算图,然而case简单没涉及多元函数例如residual结构f(x,conv(x))=x+conv(x),而+换成concat等操作等又如何求导,之前没想过。计算图的概念有说法是Yoshua Bengio在2009年提出https://www.iro.umontreal.ca/~lisa/pointeurs/TR1312.pdf,但小白看得懂的用计算图做BP计算的,一个是李弘毅的课程https://www.bilibili.com/video/av9770302,另一个是大学辍学然后在Google Brain工作的Christopher Olah,文章https://colah.github.io/posts/2015-08-Backprop/,中文翻译https://www.jianshu.com/p/0e9eea729476


根据斯坦福李飞飞的cs231n课程2017版第四课Introduction to Neural Networks摘取出的笔记,Serena Yeung主讲。利用计算图求导,其实就是通过直观图示和手算梯度的方式,来学习和理解Back Propogation算法。

计算图(Computation Graph)

[NNCS]计算图求导;x=Wu+b_第1张图片
计算图举例

个人觉得很容易理解,其实就是编译原理课程中的AST(Abstract Syntax Tree)的一种特定形式:神经网络可以用一系列节点和边来表示,也可以用等价的一个数学公式表示,这个公式你如果写出来写到txt文件那么它是纯文本形式,这个纯文本经过parser的转化得到结构化的表示,这种结构化的表示的可视化就是类似上图看到的这种形式。

计算图求导:例1
这里给出了很简单的一个例子:计算图(网络)前传的公式为f(x,y,z) = (x+y)z,那么在计算图(网络)反向传播时要计算梯度,问df/dx,df/dy,df/dz分别是多少?(这里的每个节点都是scalar标量因而只有一个维度,所以反传的梯度就等于导数,如果输入是多维则每个维度分别计算)

具体计算过程如下图所示:(计算图上红字表示算出来的反传梯度)


[NNCS]计算图求导;x=Wu+b_第2张图片
计算图求导:手撕反传梯度.jpg

很多教程中说关键点是链式法则,其实我觉得最重要的是直观理解计算图的流动过程,也就是所谓tensor的flow,包括前向flow和反向flow,反向flow的第一点就是f对自身的求导,等于1;然后到达中间节点(取名为q),然后从q再流入到x和y。为什么说这个直观理解的流动过程很关键?因为链式求导公式人人都会,关键是知道利用计算图这样一种工具来分析,进而才是使用链式求导公式;此外,这里虽然可以直接看出来df/dx=z但是还是引入了中间结点q,意在说明整个计算图求导的步骤,因为一旦前传公式f的表达式很复杂,那么这种中间结点就很有用了,至少能减少计算出错概率吧。

神经网络是怎样一个计算图
Neural Network既然用到Back Propagation来学习,说明它是一种有监督学习,它需要自己给出一个预测输出f,以及f和gt的比较,这个比较的结果通过loss函数(包括对应的regulartion term)来反映。也就是:我已经知道了神经网络会stacking很多layer,这个网络对应的计算图的终结节点,是Loss,因而反向传播计算梯度时候的第0步是dL/dL=1,然后才是逐渐往前面计算:

[NNCS]计算图求导;x=Wu+b_第3张图片
神经网络的反向求导过程:先算dL/dL,然后算dL/dz(也就是dL/d pred),接下来算dL/dx, dL/dy

从编程角度考虑,如何利用计算图来计算反传梯度
显然,计算图当中的每个节点(operator),代表一个计算函数,你可以理解为一个lambda;每个节点都应当是提前确定好的(否则网络建立不起来),那么求导公式应该是提前确定的,而不需要等到x,y这样的输入节点有具体取值才知道公式是什么。所以每个节点的operator就对应一个函数,分别计算dz/dx, dz/dy, ... (这个节点有几个输入节点,就计算几个dz/da,实际上应该是[dz/da],一个tensor,这个tensor整体表示梯度,它的每个分量表示导数)。

此外还因该注意到,前面给的例子中,f(x,y,z)=(x+y)z这个公式对应的计算图,每个tensor其实都是scalar。实际中在训练阶段肯定都是(N, C, H, W)形式的tensor,N往往大于1以便于GPU加速计算,C和H和W往往都不是1因为他们仨对应到一张RGB图像,并且最常见的operator应该是Convolution、ReLU、BN、SoftmaxLoss。

当然,按照(N,C,H,W)的4维tensor来想整个网络的计算过程,还是比较naive的。实际上的卷积网络计算往往使用矩阵运算库来加速,原理就是把N,C,H,W这样的一个四维生物拉伸为一个二维生物,然后和拉伸过的卷积核做矩阵乘法。那么从这个点上考虑,卷积层和全连接层在局部上都是执行乘法操作,它们都可以用抽象出来的x=Wu+b来表示:u作为本层输入,W是weight是学习设定量,b是bias也是学习设定量。

你可能感兴趣的:([NNCS]计算图求导;x=Wu+b)