使用 TensorFlow 加载 Numpy 数据
在科学计算之中,Numpy 是一种必不可少的工具,因此我们在机器学习的过程之中难免会遇到使用 Numpy 数据的情况,所以我们有必要学习如何在 TensorFlow 之中学习如何使用 Numpy 数据。
1. 什么是 Numpy
Numpy 是 Python 的一个扩展库。支持高阶维度数组的复杂运算以及矩阵的运算。因此在进行科学计算的时候使用 Numpy 进行数据处理便会特别的方便。
在具体的使用过程之中,我们一般会遇到两种情况:
- 在内存中定义了 Numpy 数组,需要提供给 TesnorFlow 使用;
- 我们需要加载 Numpy 存放的文件的数据,也就是需要从“.npz”文件之中读取数据。
因此这节课之中我们就从两个方面来说明如何使用 Numpy 数据。
2. 在内存中使用 Numpy 数据
如果我们在内存中定义了 Numpy 数据,那么我们便可以通过 tf.convert_to_tensor() 函数来将 Numpy 数据转化为 Tensor,从而提供给 TensorFlow 使用。比如以下示例:
import tensorflow as tf
import Numpy as np
x_np = np.zeros((5, 3))
x_tensor = tf.convert_to_tensor(x_np)
print(type(x_np), type(x_tensor))
print(x_tensor)
我们可以得到结果如下,说明该函数已经成功的将 Numpy 数组转化为了 Tensor 对象:
<class 'Numpy.ndarray'> <class 'tensorflow.python.framework.ops.EagerTensor'>
tf.Tensor(
[[0. 0. 0.]
[0. 0. 0.]
[0. 0. 0.]
[0. 0. 0.]
[0. 0. 0.]], shape=(5, 3), dtype=float64)
那如果我们需要将 Tensor 转化为 Numpy 呢?我们只需要使用 Tensor 对象中的 Numpy 函数即可将其转化为 Numpy 。
比如我们接上面的例子:
......
print(type(x_np_new))
print(x_np_new)
我们可以得到输出:
<class 'Numpy.ndarray'>
[[0. 0. 0.]
[0. 0. 0.]
[0. 0. 0.]
[0. 0. 0.]
[0. 0. 0.]]
由此我们可以发现,通过 Tensor 对象的 Numpy 方法可以将 Tensor 对象转化为 Numpy 数组。
3. 从“.npz”文件之中读取数据
当我们要从 .npz 文件之中读取并使用数据的时候,我们大概要经过三个步骤:
- 打开 .npz 文件,并且其格式加载数据,要注意,不同的 .npz 文件中的格式都是由人为定义的,因此只有了解了文件中的组织格式,才能加载数据;
- 将加载的 .npz 数据转化为 tf.data.Dataset ;
- 进一步处理并使用该数据集合。
下面我们以一个简单的手写数字识别数据集(mnist)为例,来演示如何进行数据的加载与使用。
3.1 打开文件并加载数据
这里用到的npz文件大家可以从谷歌仓库中下载,大家可以通过该链接下载。
然后我们需要首先得到下载文件的本地地址,在这里我假设地址是’/root/.keras/datasets/mnist.npz’。
该数据集是由一个字典组成,这个字典由四个元素组成,他们的key分别是:
- x_train: 训练数据的图片数据;
- y_train: 训练数据的标签;
- x_test: 测试数据的图片数据;
- y_test: 测试数据的标签。
了解了数据的结构后,我们便可以通过以下操作进行数据的加载:
import Numpy as np
import tensorflow as tf
path = '/root/.keras/datasets/mnist.npz'
with np.load(path) as np_data:
train_exa = np_data['x_train']
train_labels = np_data['y_train']
test_exa = np_data['x_test']
test_labels = np_data['y_test']
这样我们便完成了数据的加载。
3.2 构建tf.data.Dataset数据集
和之前一样,我们主要是通过 tf.data.Dataset.from_tensor_slices() 函数来构建数据集。比如我们可以通过以下代码实现:
train_dataset = tf.data.Dataset.from_tensor_slices((train_exa, train_labels))
test_dataset = tf.data.Dataset.from_tensor_slices((test_exa, test_labels))
print(train_dataset, test_dataset)
我们可以得到如下输出:
<TensorSliceDataset shapes: ((28, 28), ()), types: (tf.uint8, tf.uint8)>
<TensorSliceDataset shapes: ((28, 28), ()), types: (tf.uint8, tf.uint8)>
由此,我们便通过 Numpy 数组正式构建了 tf.data.Dataset 数据集合。
3.3 进一步的处理与使用
当我们仅仅创建了数据集是远远不够的,我们还要进行进一步的处理,比如分批、打乱等基本操作。
train_dataset = train_dataset.shuffle(128).batch(64)
test_dataset = test_dataset.batch(64)
print(train_dataset, test_dataset)
我们可以得到如下输出:
<BatchDataset shapes: ((None, 28, 28), (None,)), types: (tf.uint8, tf.uint8)>
<BatchDataset shapes: ((None, 28, 28), (None,)), types: (tf.uint8, tf.uint8)>
在这里,我们对数据集合进行了乱序处理,然后将其按照 64 的大小进行批次的划分。
在接下来我们便可以使用该数据集,在这里我们可以使用一个简单的分类模型进行示例:
model = tf.keras.Sequential([
tf.keras.layers.Flatten(input_shape=(28, 28)),
tf.keras.layers.Dense(64, activation='relu'),
tf.keras.layers.Dense(10, activation='softmax')
])
model.compile(optimizer='adam',
loss=tf.keras.losses.SparseCategoricalCrossentropy(),
metrics=['accuracy'])
model.fit(train_dataset, epochs=20)
model.evaluate(test_dataset)
我们可以通过输出发现,该模型对数据进行了良好的分类:
Epoch 1/20
469/469 [==============================] - 1s 3ms/step - loss: 6.4886 - accuracy: 0.8282
Epoch 2/20
469/469 [==============================] - 1s 3ms/step - loss: 1.0750 - accuracy: 0.8630
......
Epoch 20/20
469/469 [==============================] - 1s 3ms/step - loss: 0.1222 - accuracy: 0.9657
157/157 [==============================] - 0s 1ms/step - loss: 0.2871 - accuracy: 0.9456
[0.2871202528476715, 0.9455999732017517]
4. 小结
在这节课之中,我们学习了什么是 Numpy 数据,同时一方面了解了 Numpy 数组与 Tensor 如何在内存中互相转化,另一方面我们也了解了如何从".npz"文件之中读取数据并进一步使用。