TensorFlow 筆記(2): MNIST dataset

Source: Deep Learning on Medium

TensorFlow 筆記(2): MNIST dataset

為什麼要了解MNIST dataset

關於Deep Learning的教學文章,很多都是從MNIST dataset做為第一個範例,原因是它資料格式與目的很簡單,卻也有一定的難度。再加上學習Deep Learning之前一定得先瞭解手上的資料,可以用來熟練Deep Learning常用的基本操作。

MNIST dataset

MNIST是手寫數字的dataset, 裡面的每張圖片都是一個手寫數字圖片, 並且標示對應的數字。圖片的大小是28×28, 顏色格式是灰階

首先,先import會用到的function

import numpy as np
import tensorflow as tf
import matplotlib.pyplot as plt

接著下載MNIST data

(xtrain, ytrain), (xtest, ytest) = tf.keras.datasets.mnist.load_data()

這邊可以看到,下載的資料分成training data以及test data。

training data又分成xtrain, ytrain。xtrain是影像資料,ytrain是該圖片標示出對應的數字。xtest及ytest也是同樣地代表圖片以及對應的數字。

print('xtrain.shape={}'.format(xtrain.shape))
print('ytrain.shape={}'.format(ytrain.shape))
print('xtest.shape={}'.format(xtest.shape))
print('ytest.shape={}'.format(ytest.shape))
'''
xtrain.shape=(60000, 28, 28)
ytrain.shape=(60000,)
xtest.shape=(10000, 28, 28)
ytest.shape=(10000,)
'''

可以看到training data有60000筆,圖片的大小是28×28,標示的數字有60000筆。test data有10000筆, 圖片大小一樣是28×28,標示的數字有10000筆。

接著我們來看其中一筆資料的樣子,底下的function可用來繪出一張圖片

def plot_img(ndarr):
img = ndarr.copy()
img.shape = (28,28)
plt.imshow(img, cmap='gray')
plt.show()

我們來看看index 5的圖片

plot_img(xtrain[5,:])

同時我們將他的 label 印出來, 可以看到就是2

print('label of img 5= {}'.format(ytrain[5]))
# label of img 5= 2

Preprocessing

通常原始的dataset都需要一些preprocessing, reshape是常見的一個操作。

底下的操作可以將每一張圖片從2D轉成1D, 在reshape的參數裡, 第一個維度大小就是資料數量, 第二個參數是1D的大小, 這裡填-1代表讓numpy自行計算剩下的大小

xtrain = xtrain.reshape(xtrain.shape[0], -1)
xtest = xtest.reshape(xtest.shape[0], -1)
print('xtrain.shape={}'.format(xtrain.shape))
print('xtest.shape={}'.format(xtest.shape))
'''
xtrain.shape=(60000, 784)
xtest.shape=(10000, 784)
'''

Normalize

一般來說,原始資料經過normalize會讓訓練過程更有效率。我們的圖片格式是INT8的灰階格式, 所以值的範圍是0~255, 所以我們將它除以255做normalize

xtrain = xtrain.astype('float32')
xtest = xtest.astype('float32')
xtrain /= 255 # normalize
xtest /= 255 # normalize

One hot encoding

由於我們的圖片被標示的是個數字,在訓練模型時,難以計算預測的準確度如何,所以一般會將資料轉成one hot encoding。

舉例來說,原本標示的數字是 2, 轉成one hot encoding之後會變成 [0, 0, 1, 0, 0, 0, 0, 0, 0, 0] , 可以看到只有 index 2的地方被設成1, 其他都是0

這樣的好處是, 我們在預測時, 可以給出預測為每個數字的機率, 像是 [0, 0, 0.8, 0, 0, 0.2, 0, 0, 0, 0],代表預測2的機率是0.8, 預測5的機率是0.2, 然後我們可以一一比對猜測的結果如何

用底下的方式可以轉成one hot encoding

ytrain = np.eye(10)[ytrain] # one hot encoding for 10 classes
ytest = np.eye(10)[ytest] # one hot encoding for 10 classes

Batch

在訓練模型的時候,通常我們會把training data 分成一小塊一小塊做訓練,而不是一次把所有training data都丟進去訓練。底下的function可以將資料亂數排列之後取其中的batch size出來做訓練

def next_batch(batch_size, data, labels):
idx = np.arange(0 , len(data))
np.random.shuffle(idx)
idx = idx[:batch_size]
data_shuffle = [data[i] for i in idx]
labels_shuffle = [labels[i] for i in idx]
return np.asarray(data_shuffle), np.asarray(labels_shuffle)
xbatch, ybatch = next_batch(128, xtrain, ytrain) # batch size=128

結語

網路上找到使用 MNIST 的 tensorflow 文章, 大多都是早期的 tensorflow 版本, 下載資料庫的方式不太一樣, 並且不被較新的版本支援, 換成新的方式之後, 網路上的範例程式碼都要再做修改, 像是 one hot encoding的方式, 或是 batch的方式, 都是得重新寫過。

了解MNIST之後, 接著可以開始練習比較簡單的 logistic regression model