



本书的第1个步骤是创建DeZero的组成元素——变量。变量是DeZero最重要的组成部分。在这个步骤中,我们将思考变量是如何工作的,并实现变量的功能。
首先来看一下什么是变量。打开编程入门类图书,你会发现这些图书大多用类似于 图1-1 的示意图来解释变量。
图1-1 变量的示意图
然后这些图书会告诉你,“箱子”就是变量,里面可以存放数据。这种把变量比作“箱子”的说法(在一定程度上)很好地解释了变量的特点。变量的要点可以总结如下。
下面来实现DeZero的变量,使它具有示意图中“箱子”的特点。
变量的英语是variable。这里我们把DeZero的变量以 Variable 类的形式实现。补充一句,类名首字母大写是Python的一条常见的编码规则。这条规则记载在Python的PEP8编码规范中。
下面编写代码,让 Variable 类具备“箱子”的功能。实现这个功能的最简代码如下所示。
steps/step01.py
class Variable:
def__init__(self, data):
self.data=data
上面的代码所做的是在初始化时,将传来的参数设置为实例变量 data 。虽然这段代码很简单,但它可以让 Variable 类作为“箱子”使用,因为实际的数据被保存在 Variable 的 data 里。结合下面的使用示例,我们能更清晰地看出这一点。
steps/step01.py
import numpy as np data=np.array(1.0) x=Variable(data) print(x.data)
1.0
这个例子使用了NumPy的多维数组来保存放入“箱子”里的数据。例子中的 x 是一个 Variable 实例,实际的数据在 x 里面。换言之, x 不是数据,而是存放数据的实体,也就是一个存放数据的“箱子”。
本书在展示代码时,会在代码的右上角标明它出自哪个文件。在上面的示例代码中,代码的右上角写着
steps/step01.py
,这表示你可以在本书的随书下载文件
中的
step/step01.py
中找到这段代码。有些示例代码的右上角没有记载文件名,这种情况意味着随书下载文件里没有对应的代码文件。
机器学习系统使用多维数组作为底层数据结构。因此,DeZero的 Variable 类要设计成只能处理NumPy多维数组的形式。NumPy多维数组的类是 numpy.ndarray ( np.ndarray )。如前面的代码所示,我们可以使用 np.array 函数来创建它的实例。另外,本书后面在提到 numpy.ndarray 实例时,都将其简称为 ndarray 实例。
接下来为前面代码中的 x 赋新的数据。代码编写如下。
steps/step01.py
x.data=np.array(2.0) print(x.data)
2.0
如这段代码所示,只要按照 x.data=... 的方式编写, x 就会被赋上新的数据。这样 Variable 类就可以作为一个“箱子”使用了。
以上就是步骤1实现的所有代码。虽然现在 Variable 类只有3行代码,但我们会在此基础上将DeZero打造成一个现代框架。
最后简单介绍一下NumPy的多维数组。多维数组是一种数值等元素按照一定规则排列的数据结构。元素的排列顺序是有方向的,这个方向叫作维或轴。 图1-2 是一个多维数组的示例。
图1-2 多维数组的示例
图1-2 中从左到右依次为零维矩阵、一维矩阵、二维矩阵,它们分别叫作标量、向量和矩阵。标量就是简单的一个数。数沿着一个轴排列的是向量,数沿着两个轴排列的是矩阵。
多维数组也叫张量。
图1-2
中从左到右也可以分别叫作零阶张量、一阶张量和二阶张量。
NumPy的 ndarray 实例中有一个实例变量叫 ndim , ndim 是number of dimensions的缩写,表示多维数组的“维度”。下面我们实际用一用它。
>>> import numpy as np >>> x=np.array(1) >>> x.ndim 0 >>> x=np.array([1, 2, 3]) >>> x.ndim 1 >>> x=np.array([[1, 2, 3], ... [4, 5, 6]]) >>> x.ndim 2
上面的代码是启动了Python解释器的交互模式后,在交互模式下运行的(在交互模式下,代码前会出现 >>> 符号)。如上所述,通过实例变量 ndim ,我们可以知道数组的维度。
只有在处理向量的时候,我们才需要注意“维度”这个词。比如有一个向量
np.array([1, 2, 3])
,由于它有3个元素,所以也叫三维向量。向量的维度指的是向量中元素的数量。而在提到三维数组时,数组的维度是指轴(而不是元素)的数量是3。
如上所述, ndarray 实例可以用来创建标量、向量、矩阵,甚至更高阶的张量。不过本书暂时只涉及标量的计算。后面(从 步骤37 开始)我们将扩展DeZero,使其支持向量和矩阵的处理。