9.2.20

用Keras多元感知器(MLP)辨識Mnist手寫數字影像

我是用google的Colab上的TPU跑的
Mnist是一堆灰階的手寫數字影像,利用AI來訓練圖片上的數字正不正確
利用MLP的功能把Mnist的資料來做比對,把圖片區分為點,再來抓取特徵比對


!pip install --upgrade tensorflow keras                      #更新tensorflow跟keras,更新完要登出再登入

import numpy as np                 #載入相關模組
import pandas as pd 
from keras.utils import np_utils 
np.random.seed(10)

Using TensorFlow backend. 



from keras.datasets import mnist                  #匯入mnist資料,如果沒有就下載
(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))
train data= 60000 test data= 10000               #輸出訓練資料有60000筆,測試資料有10000筆

print('train_image=', X_train_image.shape) 
print('train label=', y_train_label.shape)
train_image= (60000, 28, 28) train label= (60000,)       #28X28的圖片,60000筆數字影像,60000數字影像真實的值

import matplotlib.pyplot as plt      #利用matplotlib來畫圖,建立函數
def plot_image(image): 
      fig = plt.gcf() 
      fig.set_size_inches(2,2) 
      plt.imshow(image, cmap='binary')
      plt.show() 

plot_image(X_train_image[0])       #把函數plot_image的框架套進來輸出

y_train_label[0]                 #第0筆資料的真實值


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() 

plot_images_labels_predict(X_train_image, y_train_label, [], 0, 10)        #畫圖


print('test_image=', X_test_image.shape)          #查看測試筆數
print('test_label=', y_test_label.shape)
test_image= (10000, 28, 28) test_label= (10000,)


plot_images_labels_predict(X_test_image, y_test_label, [], 0, 10)       #畫圖

x_Train = X_train_image.reshape(60000, 784).astype('float32')      #轉換為784個32位元的浮點數
x_Test = X_test_image.reshape(10000, 784).astype('float32')
 
xTrain= (60000, 784) xTest= (10000, 784) 

X_train_image[0]         
#查看第0筆資料的內容,就是數字5,每個數字都是灰階的圖片,所以顏色由深到淺,就是255到0

x_Train_norm = x_Train/255         #再除以255,就會有小數點,差異化就會變大,特徵越明顯
x_Test_norm = x_Test/255

x_Train_norm[0]

y_train_label[:10]
array([5, 0, 4, 1, 9, 2, 1, 3, 1, 4], dtype=uint8)             

y_TrainOneHot = np_utils.to_categorical(y_train_label)
y_TestOneHot = np_utils.to_categorical(y_test_label)

y_TrainOneHot[:10]                                            #輸出前10筆資料
0000010000 =5      1對下來就是5
1000000000 =0
0123456789 

等一下要建立訓練模型
輸入層是784,就是剛剛要放進來訓練的資料。                    
隱藏層等一下要建,常理來說數值是越大越好,但是會有過度擬合                                                的問題,運算也需要時間。
輸出層是10,因為只有0到9個數字

from tensorflow.python.keras.layers import Dense
from tensorflow.python.keras import Sequential                         #匯入相關模組

model = Sequential()
#建立模型,輸入層神經元784個,隱藏層神經元256個,輸出層神經元10個

model.add(Dense(units=256, input_dim=784, kernel_initializer='normal', activation='relu'))
model.add(Dense(units=10, kernel_initializer='normal', activation='softmax'))

print(model.summary())       #查看模型摘要
                                              200960=784*256+256
                                              2570=256*10+10
                                              203530=200960+2570


model.compile(loss='categorical_crossentropy', optimizer='adam', metrics=['accuracy'])
train_history = model.fit(x=x_Train_norm, y=y_TrainOneHot, validation_split=0.2, epochs=10, batch_size=200, verbose=2)
#訓練模型,48000=60000*0.8  80%作為訓練資料
                      12000=60000*0.2  20%作為驗證資料
                      10次的訓練週期
                      每批200筆訓練資料,48000/200=240批
                       Loss誤差越小,準確率越高
                     

import matplotlib.pyplot as plt                                       #畫圖
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() 

show_train_history(train_history, 'accuracy', 'val_accuracy')

#藍線是訓練的準確率,橘線是驗證的準確率
驗證的準確率,一開始會比較高,是因為本來就是正確的資料
後來經過模型的訓練,訓練的準確率會比較高
show_train_history(train_history, 'loss', 'val_loss')

scores = model.evaluate(x_Test_norm, y_TestOneHot) 
print() 
print('accuracy=', scores[1])      #準確率是0.97

prediction = model.predict_classes(x_Test_norm)

prediction                          #預測結果

plot_images_labels_predict(X_test_image, y_test_label, prediction, idx=0)
#誤差是第8筆,真實是5,預測是6

import pandas as pd 
pd.crosstab(y_test_label, prediction, rownames=['label'], colnames=['predict'])
#誤差矩陣,數字大的對角線,是預測成功的筆數

df = pd.DataFrame({'label':y_test_label, 'predict':prediction})
df [:10]
#建立資料表框架

df[(df.label==5) & (df.predict==6)]
#真實是5預測是6,有4筆,端看誤差矩陣左5上6有4筆

plot_images_labels_predict(X_test_image, y_test_label, prediction, idx=8, num=1)
#提取第8筆觀看,真實5預測6
改善方法為提高隱藏層神經元,或改用CNN卷積神經網路辨識

沒有留言:

張貼留言