STEP1. 卷積神經網路介紹
CNN 卷積神經網路可以分成兩大部分:
STEP2. 卷積運算 (Convolution)
卷積運算的原理是將一個影像透過卷積運算的 Filter weight(s) 產生多個影像, 在上面第一層的 Convolution 為例:
1. 先以隨機方式產生 16 個 3x3 的 filter weight(S)
2. 要轉換的影像由左而右, 由上而下透過 filter weight 產生新影像的值:
3. 使用 16 個 filter weight 產生 16 個影像
STEP3. Max-Pooling 運算說明
Max-Pool 運算可以將影像縮減取樣 (downsampling), 如下圖: 原本影像是 4x4, 經過 Max-Pool 運算後, 影像大小為 2x2:
downsampling 有以下好處:
進行資料前處理 (Preprocess)
CNN (Convolution Neural Network) 與 MLP 進行資料的前處理方式有所不同, 說明如下:
STEP1. 資料讀取與轉換
- #!/usr/bin/env python3
- from keras.datasets import mnist
- from keras.utils import np_utils
- import numpy as np
- np.random.seed(10)
- # Read MNIST data
- (X_Train, y_Train), (X_Test, y_Test) = mnist.load_data()
- # Translation of data
- X_Train40 = X_Train.reshape(X_Train.shape[0], 28, 28, 1).astype('float32')
- X_Test40 = X_Test.reshape(X_Test.shape[0], 28, 28, 1).astype('float32')
- # Standardize feature data
- X_Train40_norm = X_Train40 / 255
- X_Test40_norm = X_Test40 /255
- # Label Onehot-encoding
- y_TrainOneHot = np_utils.to_categorical(y_Train)
- y_TestOneHot = np_utils.to_categorical(y_Test)
接著會依照下面流程圖建立模型:
STEP1. 建立卷積層與池化層
- from keras.models import Sequential
- from keras.layers import Dense,Dropout,Flatten,Conv2D,MaxPooling2D
- model = Sequential()
- # Create CN layer 1
- model.add(Conv2D(filters=16,
- kernel_size=(5,5),
- padding='same',
- input_shape=(28,28,1),
- activation='relu'))
- # Create Max-Pool 1
- model.add(MaxPooling2D(pool_size=(2,2)))
- # Create CN layer 2
- model.add(Conv2D(filters=36,
- kernel_size=(5,5),
- padding='same',
- input_shape=(28,28,1),
- activation='relu'))
- # Create Max-Pool 2
- model.add(MaxPooling2D(pool_size=(2,2)))
- # Add Dropout layer
- model.add(Dropout(0.25))
- 建立平坦層
下面程式碼建立平坦層, 將之前步驟已經建立的池化層2, 共有 36 個 7x7 維度的影像轉換成 1 維向量, 長度是 36x7x7 = 1764, 也就是對應到 1764 個神經元:
- model.add(Flatten())
- model.add(Dense(128, activation='relu'))
- model.add(Dropout(0.5))
最後建立輸出層, 共有 10 個神經元, 對應到 0~9 共 10 個數字. 並使用 softmax 激活函數 進行轉換 (softmax 函數可以將神經元的輸出轉換成每一個數字的機率):
- model.add(Dense(10, activation='softmax'))
- model.summary()
- print("")
進行訓練
接著我們使用 Back Propagation 進行訓練.
STEP1. 定義訓練並進行訓練
- # 定義訓練方式
- model.compile(loss='categorical_crossentropy', optimizer='adam', metrics=['accuracy'])
- # 開始訓練
- train_history = model.fit(x=X_Train4D_norm,
- y=y_TrainOneHot, validation_split=0.2,
- epochs=10, batch_size=300, verbose=2)
訓練過程的輸出如下:
STEP2. 畫出 accuracy 執行結果
之前的訓練步驟產生的 accuracy 與 loss 都會記錄在 train_history 變數. 底下將常用的函數定義在 utils.py:
- utils.py
- import os
- def isDisplayAvl():
- return 'DISPLAY' in os.environ.keys()
- import matplotlib.pyplot as plt
- def plot_image(image):
- fig = plt.gcf()
- fig.set_size_inches(2,2)
- plt.imshow(image, cmap='binary')
- plt.show()
- def plot_images_labels_predict(images, labels, prediction, idx, num=10):
- fig = plt.gcf()
- fig.set_size_inches(12, 14)
- if num > 25: num = 25
- for i in range(0, num):
- ax=plt.subplot(5,5, 1+i)
- ax.imshow(images[idx], cmap='binary')
- title = "l=" + str(labels[idx])
- if len(prediction) > 0:
- title = "l={},p={}".format(str(labels[idx]), str(prediction[idx]))
- else:
- title = "l={}".format(str(labels[idx]))
- ax.set_title(title, fontsize=10)
- ax.set_xticks([]); ax.set_yticks([])
- idx+=1
- plt.show()
- def show_train_history(train_history, train, validation):
- plt.plot(train_history.history[train])
- plt.plot(train_history.history[validation])
- plt.title('Train History')
- plt.ylabel(train)
- plt.xlabel('Epoch')
- plt.legend(['train', 'validation'], loc='upper left')
- plt.show()
- from utils import *
- if isDisplayAvl():
- show_train_history(train_history, 'acc', 'val_acc')
- show_train_history(train_history, 'loss', 'val_loss')
- Training accuracy vs Evaluation accuracy
- Training loss vs Evaluation loss
評估模型準確率與進行預測
我們已經完成訓練, 接下來要使用 test 測試資料集來評估準確率.
STEP1. 評估模型準確率
- scores = model.evaluate(X_Test4D_norm, y_TestOneHot)
- print()
- print("\t[Info] Accuracy of testing data = {:2.1f}%".format(scores[1]*100.0))
- print("\t[Info] Making prediction of X_Test4D_norm")
- prediction = model.predict_classes(X_Test4D_norm) # Making prediction and save result to prediction
- print()
- print("\t[Info] Show 10 prediction result (From 240):")
- print("%s\n" % (prediction[240:250]))
- if isDisplayAvl():
- plot_images_labels_predict(X_Test, y_Test, prediction, idx=240)
STEP4. 顯示 Confusion Matrix
- import pandas as pd
- print("\t[Info] Display Confusion Matrix:")
- print("%s\n" % pd.crosstab(y_Test, prediction, rownames=['label'], colnames=['predict']))
完整代碼連結如下:
Supplement
* ML Lecture 10: Convolutional Neural Network
* TensorFlow : Tutorials 02 - Convolutional Neural Network
* Save and Load Your Keras Deep Learning Models

