2018年3月9日 星期五

Keras:MNIST手寫數字辨識資料集介紹

MNIST手寫數字辨識資料集


MNIST手寫數字辨識資料集,是由Yann LeCun(揚·勒丘恩)大神所蒐集,這位大神同時也是Convulution Nueral Networks(卷積神經網絡)的創始人,因此享有"卷積網絡之父"的美譽。關於這位大神的事蹟在維基百科上有詳細的介紹,再者裡就不在多做闡述。由於MNIST的資料大小適中,而且皆為單色影像(黑字白底),十分適合做為初學者第一個建立模型、訓練、與預測的資料集。




MNIST資料集是由60,000筆訓練資料、10,000筆測試資料所組成。MNIST資料集裡的每一筆資料皆由images(數字的影像)與labels(該圖片的真實數字,其實就是答案)所組成,示意圖如圖表1。

圖表1. MNIST資料集的組成


下載MNIST資料


Step1. 匯入Keras與其它需要使用的模組


首先先匯入Keras與其它模組,程式碼與相關註解如下:
#匯入Keras及相關模組
import numpy as np #匯入numpy模組,NumPy是Python語言的擴充程式庫。支援維度陣列與矩陣運算
import pandas as pd 
from keras.utils import np_utils #匯入keras.utils因為後續要將label標籤轉換為One-hotencoding
np.random.seed(10) #設定seed可以讓每次需要隨機產生的資料,都有相同的輸出

Step2. 匯入Keras模組中的mnist


在Keras中已經預設提供mnist,可以直接匯入並使用資料,在這裡先將minst匯入,程式碼與相關註解如下:
from keras.datasets import mnist #匯入Keras的mnist模組

Step3. 第一次執行程式並下載mnist資料


當執行mnist.load_data()程式碼,程式會先去檢查使用者目錄下的.keras\datasets資料夾中是否存在mnist.npz這個檔案,如果回傳值為空則會自動開始下載。檔案大小為10.9MB,因此程式需要耗費一些時間去完成。程式碼與相關註解如下:
#下載minst資料集檔案
#資料集檔案位置:C:\Users\alanjian\.keras\datasets\mnist.npz
(x_train_image, y_train_label),\
(x_test_image, y_test_label) = mnist.load_data() 

Step4. 在Windows系統中查看mnist.npz檔案

mnist.npz檔案的路徑位置為C:\Users\alanjian\.keras\datasets\mnist.npz,因為我的使用者名稱是alanjian,因此會存放在alanjian資料夾裡的.keras目錄中。檔案位置路徑示意圖如圖表2:

圖表2. mnist.npz的位置路徑

Step5. 查看mnist資料組成


在程式下載完mnist.npz檔案後,我們可以查看minst的資料集組成,輸出結果表示minst由60,000筆的train data(訓練資料)與10,000筆的test data(訓練資料)所組成,程式碼如下:
#查看mnist資料集筆數
print('train data=', len(x_train_image))
print('test data=', len(x_test_image))

顯示單筆mnist資料內容


Step1. 每一筆mnist資料的組成方式


每一筆mnist資料皆是由images(數字影像)與labels(數字真實值)所組成,images的部分為單色、28*28像素的影像檔案(圖片),label則是該張影像檔案的真實數值(解答),程式碼如下:
print('x_train_image :', x_train_image.shape) #x_train_image : (60000, 28, 28)
print('y_train_label :', y_train_label.shape) #共60000張圖片資料,圖片像素28*28

Step2. 使用matplotlib輸出images數字影像


為了能夠顯示images數字影像,我們使用matplotlib工具將images輸出首先匯入matplotlib模組,程式碼如下:
import matplotlib.pyplot as plt #匯入matplotlib.pyplot模組

Step3.建立plot_image()函式


撰寫plot_image()函式,實作將images輸出方法,程式碼如下:
#建立plot_image函數,顯示images數字影像
def plot_image(image): #定義plot_image函數,傳入image作為參數
    fig = plt.gcf() #設定顯示圖形的大小
    fig.set_size_inches(2,2)
    plt.imshow(image, cmap='binary') #傳入參數image、28*28像素的圖形,camp="binary"表示以黑白色顯示
    plt.show() #顯示圖片

Step4. 呼叫plot_image()函式顯示第1筆數字影像資料


接下來我們呼叫Step3.建立的plot_image()函式,顯示出第mnist資料及的第1筆資料,程式碼如下:
#呼叫plot_image,顯示mnist.train.images[1]的資料圖片
plot_image(x_train_image[1])

執行後的輸出結果如下圖表3:

圖表3. mnist資料集第1筆資料的圖形影像

Step5.查看第1筆的label資料內容

第1筆label資料是第1筆數字影像的真實值,所以是0,程式碼與輸出結果如圖表4:
y_train_label[1]

圖表4. mnist資料集第1筆資料的真實值

顯示多筆mnist資料內容


Step.1 匯入matplotlib模組並建立plot_images_labels()函數


為了能夠重複的察看minst資料集中的數字影像、真實值與預測結果,我們建立plot_images_labels()以供未來可以直接呼叫,程式碼與註解如下:
#匯入matplotlib.pyplot模組內容
import matplotlib.pylot as plt
#顯示資料集內容
def plot_images_labels(images, labels, idx, num = 10): #定義plot_images_labels_prediction()函式
    fig = plt.gcf() #設定顯示圖形的大小
    fig.set_size_inches(12, 14)
    if num > 25: num = 25 #如果顯示筆數參數大於25鎖定在25,避免輸出時發生錯誤
    for i in range(0, num): 
        ax = plt.subplot(5, 5, 1+i) #建立subgraph子圖形為5行5列
        ax.imshow(images[idx], cmap='binary') #劃出subgraph子圖形
        title = "label=" + str(labels[idx]) #設定子圖形的title,顯示標籤欄
        ax.set_title(title, fontsize = 10) #子圖形的標題tilte與大小
        ax.set_xticks([]);ax.set_yticks([]) #設定不顯示刻度
        idx += 1 #讀取下一筆
    plt.show() #開始繪圖

Step2. 查看訓練資料集前10筆資料


執行plot_images_labels()函式,將訓練資料集的前10筆。輸入x_test_image, y_test_label,由第0筆開始顯示至第9筆,程式碼如下:
#顯示第0到第9訓練資料
plot_images_labels(x_train_image, 
                   y_train_label,
                   idx=0)

Step3.查看測試資料集前10筆資料

同樣使用plot_images_labels()顯示第0到第9共10筆資料,程式碼如下:
#顯示第0到第9筆測試資料
plot_images_labels(x_test_image, 
                   y_test_label,
                   idx=0)

MINST資料預處理---features(數字影像的特徵值)


對features的資料預處理可以分為下列2部分:

1. 將原本28*28的2維數字影像,以reshape函式轉換為1維的向量。並且以float(浮點數)的型態儲存於向量中。

2. 將一維向量裡的數值正規化(Normalization)。

Step1. 將image以reshape()函式轉換

我們使用reshape()函式將原本28*28的二維數字影像,轉換維1維的向量,接著使用astype()函示轉換為float(浮點數)後儲存,程式碼如下:
#將image以reshape()轉換
#先將原本28*28的2維數字影像,以reshape()轉換成1維向量,再以astype()轉換為float,共784個float數字
x_Train = x_train_image.reshape(60000, 28*28).astype('float32') 
x_Test = x_test_image.reshape(10000, 28*28).astype('float32')

Step2. 查看轉換為1維向量的內容


我們可以使用print()函式來查看每個數字影像的內容,shape函数是numpy.core.fromnumeric中的函数,它的功能是查看矩阵或者数组的维数。輸出結果如圖表5.,程式碼如下:
#查看轉換為1維向量的shape
print('x_train:', x_Train.shape)
print('x_train:', x_Test.shape)

圖表5. 轉換為1維向量的shape

Step3. 查看每筆imgaes的影像內容


我們可以透過x_train_images[0]直接呼叫並查看images中第0筆的內容,程式碼如下:
#查看image第0筆的內容
#每個數字由0至255組成,代表圖形每一個點的灰階深淺
x_train_image[0]


Step4. 將images數字影像的特徵值正規化


透過正規化,可以提高後續訓練模型的準確率,因為images的數字位於0到255區間,因此最直接正規化方法就是除以255。程式碼如下:
#將數字影像image的數值正規化(normalization)
x_Train_normalization = x_Train / 255
x_Test_normalization = x_Test / 255

Step5. 查看正規化後的image內容


如同Step3.,直接透過x_Train_normalize[0]可以查看正規化後的內容:
#查看標準化後的image第0筆的內容
x_Train_normalization[0]

MINST資料預處理---labels(數字影像的真實值)


label標籤欄位原本是0~9的數字,必須透過One-hot encoding模組轉換為10個0到1的組合,例如:數字5經由One-hot encoding轉換後為0000010000。10個位數正好對應到輸出層10個神經元。

Step1. 查看原本的label標籤欄位


透過y_train_label[:5]指令,可以查看訓練資料label欄位的前五筆資料,我們可以看到目前顯示的是0~9的數字。輸出如圖表6.,程式碼如下:
#查看訓練資料label標籤欄位的前五筆訓練資料
y_train_label[:5]

圖表6. One-hot encoding的轉換結果


Step2. 對label標籤欄位執行One-hot encoding轉換


我們使用np_utils.to_categorical分別傳入參數y_train_label(訓練資料)與y_test_label(測試資料)的label標籤欄位,並執行One-hot encoding轉換,程式碼如下:
#使用np_utils.to_categorical()分別傳入y_train_label與y_test_label的label標籤欄位,執行One-hot encoding轉換
y_TrainOneHot = np_utils.to_categorical(y_train_label)
y_TestOneHot = np_utils.to_categorical(y_test_label)

Step3. 查看label 欄位經One-hot encoding轉換後的結果


執行One-hot encoding轉換之後,查看訓練資料label標籤欄位的前5筆資料。圖表7為轉換後的結果,程式碼如下:
#輸出One-hot encoding轉換結果
y_TrainOneHot[:5]

圖表7. Label經由One-hot encoding轉換後的結果

結論


在這篇文章中,我們介紹了如何下載Mnist資料集,接著說明Mnist資料集的內容與特色,並在最後的部分對Mnist資料集完成了資料預處理的工作。在這篇文章中所使用到的完整程式碼如下:
#匯入Keras及相關模組
import numpy as np #匯入numpy模組,NumPy是Python語言的擴充程式庫。支援維度陣列與矩陣運算
import pandas as pd 
from keras.utils import np_utils #匯入keras.utils因為後續要將label標籤轉換為One-hotencoding
np.random.seed(10) #設定seed可以讓每次需要隨機產生的資料,都有相同的輸出

from keras.datasets import mnist #匯入Keras的mnist模組

#下載minst資料集檔案
#資料集檔案位置:C:\Users\alanjian\.keras\datasets\mnist.npz
(x_train_image, y_train_label),\
(x_test_image, y_test_label) = mnist.load_data()

#查看mnist資料集筆數
print('train data=', len(x_train_image))
print('test data=', len(x_test_image))

print('x_train_image :', x_train_image.shape) #x_train_image : (60000, 28, 28)
print('y_train_label :', y_train_label.shape) #共60000張圖片資料,圖片像素28*28

#建立plot_image函數,顯示images數字影像
def plot_image(image): #定義plot_image函數,傳入image作為參數
    fig = plt.gcf() #設定顯示圖形的大小
    fig.set_size_inches(2,2)
    plt.imshow(image, cmap='binary') #傳入參數image、28*28像素的圖形,camp="binary"表示以黑白色顯示
    plt.show() #顯示圖片

#呼叫plot_image,顯示mnist.train.images[1]的資料圖片
plot_image(x_train_image[1])

y_train_label[1]

#匯入matplotlib.pyplot模組內容
import matplotlib.pylot as plt
#顯示資料集內容
def plot_images_labels(images, labels, idx, num = 10): #定義plot_images_labels_prediction()函式
    fig = plt.gcf() #設定顯示圖形的大小
    fig.set_size_inches(12, 14)
    if num > 25: num = 25 #如果顯示筆數參數大於25鎖定在25,避免輸出時發生錯誤
    for i in range(0, num): 
        ax = plt.subplot(5, 5, 1+i) #建立subgraph子圖形為5行5列
        ax.imshow(images[idx], cmap='binary') #劃出subgraph子圖形
        title = "label=" + str(labels[idx]) #設定子圖形的title,顯示標籤欄
        ax.set_title(title, fontsize = 10) #子圖形的標題tilte與大小
        ax.set_xticks([]);ax.set_yticks([]) #設定不顯示刻度
        idx += 1 #讀取下一筆
    plt.show() #開始繪圖

#顯示第0到第9訓練資料
plot_images_labels(x_train_image, 
                   y_train_label,
                   idx=0)

#顯示第0到第9筆資料
plot_images_labels(x_test_image, 
                   y_test_label,
                   idx=0)

#將image以reshape()轉換
#先將原本28*28的2維數字影像,以reshape()轉換成1維向量,再以astype()轉換為float,共784個float數字
x_Train = x_train_image.reshape(60000, 28*28).astype('float32') 
x_Test = x_test_image.reshape(10000, 28*28).astype('float32')

#查看轉換為1維向量的shape
print('x_train:', x_Train.shape)
print('x_train:', x_Test.shape)

#查看image第0筆的內容
#每個數字由0至255組成,代表圖形每一個點的灰階深淺
x_train_image[0]

#將數字影像image的數值正規化(normalization)
x_Train_normalization = x_Train / 255
x_Test_normalization = x_Test / 255

#查看標準化後的image第0筆的內容
x_Train_normalization[0]

#查看訓練資料label標籤欄位的前五筆訓練資料
y_train_label[:5]

#使用np_utils.to_categorical()分別傳入y_train_label與y_test_label的label標籤欄位,執行One-hot encoding轉換
y_TrainOneHot = np_utils.to_categorical(y_train_label)
y_TestOneHot = np_utils.to_categorical(y_test_label)

#輸出One-hot encoding轉換結果
y_TrainOneHot[:5]



















1 則留言:

  1. 你好,我想請問一下,在"下載MNIST資料"的STEP3的部分
    當執行mnist.load_data()程式碼時,檔案裡沒有MNIST.npz檔,它會自動下載
    可是他是從哪下載這個檔案??

    回覆刪除

Go(Golang)程式語言 設定GCC

下載MSYS2:  https://www.msys2.org/ 安裝 程式開始執行後輸入: pacman -Syu y y 在安裝目錄底下找到msys2.exe,雙擊執行 輸入指令: pacman -Su pacman -S --needed base-devel mingw-...