购买
下载掌阅APP,畅读海量书库
立即打开
畅读海量书库
扫码下载掌阅APP

步骤2
创建变量的函数

在上一步骤中, Variable 类可以作为一个“箱子”使用了。不过,现在的它还只是一个“普通箱子”,我们需要一个机制把这个“普通箱子”变为“魔法箱子”。要实现这一点,关键就在于函数。本步骤的主题是函数。

2.1 什么是函数

什么是函数?函数是“定义一个变量与另一个变量之间的对应关系的规则”。这个说法有些生硬,我们来看一个具体的例子。有一个计算平方的函数 。这时设 ,那么变量 之间的关系就由函数 决定。换言之,“ 的平方”的关系是由函数 决定的。

从这个例子可以看出,函数具有定义变量之间对应关系的作用。 图2-1 是变量与函数的关系示意图。

图2-1 变量和函数的关系示意图

图2-1 直观地展示了变量 与函数 之间的关系。这种用节点和箭头来表示计算的图叫作计算图。本书用圆框表示变量,用方框表示函数。

提到图,大家可能会想到柱状图、饼状图等。不过在计算机科学领域,图是由节点和边组成的数据结构。

2.2 Function类的实现

下面我们从编程的角度思考 图2-1 表示的函数。具体来说,就是假设变量 是之前实现的 Variable 实例,然后以 Function 类的形式实现可以处理它们的函数 。这里有两点需要注意。

在满足这两点的基础上,将 Function 类按以下方式实现。

class Function:
    def__call__(self, input):
        x=input.data  # 取出数据
        y=x ** 2  # 实际的计算
        output=Variable(y)  # 作为Variable返回
        return output

上面的代码实现了 __call__ 方法。 __call__ 方法接收 input 参数,这里假定传来的 input Variable 实例。因此,实际数据存放在 input.data 中。取出数据后,方法会执行相应的计算(在这个例子中是求平方),然后将结果放到 Variable “箱子”里并返回。

__call__ 方法是一个特殊的Python方法。定义了这个方法后,当 f=Function() 时,就可以通过编写 f(...) 来调用 __call__ 方法了。

2.3 使用Function类

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

x=Variable(np.array(10))
f=Function()
y=f(x)

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 类按下面的方式实现。

steps/step02.py

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

    def forward(self, x):
        raise NotImplementedError()

本节实现了两个方法: __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

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,以支持多个变量。 YJRoy4xybFtG5dej/ksDLyKJha0waKKrKIpd+yBxmk2fd4sMhH58G8SmuXOO7aLd

点击中间区域
呼出菜单
上一章
目录
下一章
×