使用 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"文件之中讀取數據并進一步使用。