31.2_创建反向传播的计算图的方法

31.2 创建反向传播的计算图的方法

在DeZero中,连接是在正向传播的计算过程中被创建的。准确来说,连接是在使用Variable实例进行普通计算(正向传播)的过程中被创建的。这意味着如果在函数的backward方法中使用Variable实例代替ndarray实例进行计算,就会创建该计算的连接。

为此,我们需要将导数(梯度)保存为Variable实例。具体来说,就是按照图31-3的方式修改Variable。


图31-3 以前的Variable类(左图)和新的Variable类(右图)

如图31-3所示,此前Variable类的grad引用了ndarray实例。这里将其改为引用Variable实例。以前面提到的y=sin(x)为例,修改好这一处后,我们可以创建如图31-4所示的计算图。


图31-4 Sin类的正向传播和反向传播完成后的计算图(省略了反向传播的计算内容)

图31-4是Sin类的正向传播和反向传播完成后的计算图。我们首次为反向传播的计算创建了计算图。由于表示导数的gy成了Variable实例,所以针对使用gy完成的计算,DeZero也能创建连接。

在计算 y=sin(x)y = \sin(x) 时,如果使用 yy .forward(),那么只有 xx 这样的终端变量会保存导数, yy 是函数创建的变量,所以不保存导数。在图31-4中, yy .grad没有引用gy。

图31-4省略了Sin类中反向传播的计算内容。在实现Sin类的backward方法时,我们将求导的代码写成 gx=gycos(x)\mathrm{gx} = \mathrm{gy} * \cos(x) 。假定所有的变量都已经改为Variable实例,这时,我们可以创建出图31-5这样的计算图来展示图31-4中省略的反向传播的计算。


图31-5 实际创建的计算图

图31-5中的计算图是通过调用y.backup()创建而成的“新”的计算图,即通过反向传播创建而成的计算图。如果创建了图31-5这样的计算图,我们就可以通过对变量gx调用gx.backup()来求y对x的二阶导数。

以上是求高阶导数的思路,在下一个步骤,我们将通过代码实现它。

步骤32

高阶导数(实现篇)

本步骤将对DeZero进行修改以实现高阶导数。我们要做的是按照上一个步骤探讨的内容为反向传播进行的计算创建计算图。因此,反向传播时进行的计算会用到Variable实例。

此前,我们已经在dezero/core/simple.py中实现了Variable类。这里我们在dezero/core.py中实现一个新的Variable类来代替它。dezero/coresimple.py中也实现了针对四则运算等的函数和运算符重载,这些也将在dezero/core.py中实现。