7.3_增加backward方法
7.3 增加backward方法
从前面这些反向传播的代码可以看出,它们有着相同的处理流程。准确来说,是从一个变量到前一个变量的反向传播逻辑相同。为了自动完成这些重复的处理,我们在Variable类中添加一个新的方法——backward。
steps/step07.py
class Variable: def__init__(self,data): self.data $\equiv$ data self.grad $=$ None self.birth $\equiv$ None def setCreator(self,func): self.birth $\equiv$ func
def backward(self): f $\equiv$ self creator #1.获取函数 iffisnotNone: x=f-input#2.获取函数的输入 x.grad $\equiv$ f.backup(self.grad)#3.调用函数的backward方法 x.backup() #调用自己前面那个变量的backward方法(递归)backward方法和此前反复出现的流程基本相同。具体来说,它从Variable的creator获取函数,并取出该函数的输入变量,然后调用函数的backward方法。最后,它会针对自己前面的变量,调用它的backward方法。这样每个变量的backward方法就会被递归调用。

如果Variable实例的creator是None,那么反向传播就此结束。这种情况意味着Variable实例是由非函数创造的,主要来自用户提供的变量。
下面使用这个新的Variable自动进行反向传播。
steps/step07.py
A $=$ Square()
B $=$ Exp()
C $=$ Square()
$\begin{array}{rl} & {\mathrm{x} = \mathrm{Variable}(\mathrm{np.array}(0.5))}\\ & {\mathrm{a} = \mathrm{A}(\mathrm{x})}\\ & {\mathrm{b} = \mathrm{B}(\mathrm{a})}\\ & {\mathrm{y} = \mathrm{C}(\mathrm{b})} \end{array}$#反向传播
y.grad $=$ np.array(1.0)
y.backup()
print(x.grad)运行结果
3.297442541400256
只要像上面那样调用变量y的backward方法,反向传播就会自动进行。运行结果和之前的一样。这样我们就打好了对DeZero来说最重要的自动微分的基础。
步骤8
从递归到循环
在上一个步骤中,我们向Variable类添加了backward方法。考虑到处理效率的改善和今后的功能扩展,本步骤将改进backward方法的实现方式。