使用 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"文件之中读取数据并进一步使用。

图片描述