9.2_简化backward方法

9.2 简化backward方法

第2项要改进的地方是减少用户在反向传播方面所做的工作。具体来说,就是省略前面代码中的y.grad = np.array(1.0)。每次反向传播时我们都要重新编写这行代码,为了省略它,我们需要在Variable的backward方法中添加阴影部分的两行代码。

steps/step09.py

class Variable:   
def backward(self): if self.grad is None: self.grad  $=$  np.ones_like(self.data) funcs  $=$  [self creator] while funcs: f  $=$  funcs.pop() x,y  $=$  f-input,f.output x.grad  $=$  f.backup(y.grad) ifx creatorisnotNone: funcs.append(x creator)

如上所示,如果变量grad为None,则自动生成导数。代码中通过np.ones_

like(self.data)创建了一个ndarray实例,该实例的形状和数据类型与self.data的相同,元素为1。如果self.data是标量,那么self.grad也是标量。

之前的代码中输出的导数是np.array(1.0),而上面的代码使用了np.ones_like()。这么编写的原因是Variable中的data和grad的数据类型是一样的。如果data的数据类型是32位浮点数,那么grad的数据类型也是32位浮点数。顺带一提,如果编写的是np.array(1.0),它的数据类型就是64位的浮点数。

之后如果再做某个计算,只需对最终输出的变量调用backward方法就能求得导数。下面是示例代码。

steps/step09.py
$\mathbf{x} =$  Variable(np.array(0.5))   
y  $=$  square(exp(square(x)))   
y.backup()   
print(x.grad)

运行结果

3.297442541400256