2.3_使用Function类

2.3 使用Function类

现在我们来实际使用一下Function类。这里将Variable实例的x输入Function实例的f中。

$\begin{array}{rl} & {\mathrm{x} = \mathrm{Variable}(\mathrm{np.array}(10))}\\ & {\mathrm{f} = \mathrm{Function()}}\\ & {\mathrm{y} = \mathrm{f(x)}} \end{array}$    
print(type(y) #使用type),获取对象的类型  
print(y.data)

运行结果

<class__main__.Variable> 100

上面的代码把Variable和Function结合起来使用了。从运行结果可以看出,y的类型是Variable,其数据存储在y.data中。

这里实现的Function类是一个“对输入值求平方”的具体函数。因此,将其命名为Square这样的具体名称比较合适。此外,今后我们还将增加各种函数(如Sin函数和Exp函数等)。考虑到这一点,最好把Function类作为基类来实现,并在这个类的内部实现所有DeZero函数都有的功能。这里,我们重新设计DeZero的函数,以满足以下两点要求。

  • Function类是基类,实现所有函数通用的功能

  • 具体函数是在继承了 Function 类的类中实现的

为了满足这两点,我们将Function类按下面的方式实现。

steps/step02.py

class Function: def__call__(self,input): x  $=$  input.data y  $=$  self.forward(x)#具体的计算在forward方法中进行 output  $=$  Variable(y) returnoutput   
defforward(self,x): raiseNotImplementedError()

本节实现了两个方法:__call__和forward。__call__方法执行两项任务:从Variable中取出数据和将计算结果保存到Variable中。其中具体的计算是通过调用forward方法完成的。forward方法的实现会在继承类中完成。

Function类的forward方法会抛出一个异常,目的是告诉使用了Function类的forward方法的人,这个方法应该通过继承来实现。

下面实现一个继承自 Function 类并对输入值进行平方的类。这个类的名字是 Square,代码如下所示。

steps/step02.py

class Square(Function): def forward(self, x): return x ** 2

Square类继承自Function类,所以也继承了__call__方法。因此,我们只需在forward方法中编写具体的计算代码,就能完成Square类的实现。接下来使用Square类对Variable进行如下处理。

steps/step02.py

$\mathbf{x} =$  Variable(np.array(10))   
f  $=$  Square()   
y  $=$  f(x)   
print(type(y))   
print(y.data)

运行结果

<class__main__.Variable'> 100

可以看出,得到的结果和之前的一样。这样我们就完成了步骤2,实现了Variable和Function类的基本功能。

我们暂时只考虑Function的输入和输出仅有一个变量的情况。从步骤11开始,我们将扩展DeZero,以支持多个变量。

步骤3

函数的连续调用

目前已经创建了DeZero的变量和函数。我们还在上一个步骤实现了一个名为Square的用于计算平方的函数类。在本步骤中,我们会实现一个新的函数,并将多个函数连结起来进行计算。