添加链接
link管理
链接快照平台
  • 输入网页链接,自动生成快照
  • 标签化管理网页链接

Neural Networks (三) 提昇Keras MNIST的準確率

在上文中我們首次使用Keras建立一個如下簡單的ANN架構,輸入層有784個神經元,輸出層10個神經元(1~10的數字),隱藏層有256個神經元,各層層數皆為1。

最後使用test dataset run出該模型的準確率是0.9757

接下來我們採取一些措施,看看可否提昇它的準確率。請繼續使用上一篇Jupyter的程notebook頁面上的程式碼,接續著繼續輸入就可以了。

一.混淆矩陣Confusion matrix

其實就是統計學中的「分類矩陣」(Classification matrix)。透過判斷預測值與實際值是否符合,計算模型中所有案例分類結果的總數,以矩陣方式來顯示。它是一種評估統計模型的標準工具,應用在機器學習中可以協助我們判斷所使用的演算法模型是否混淆了某兩類,將某一label預測為另一個label。除了「分類矩陣」 「混淆矩陣」,有時它也稱為「錯誤矩陣error matrix」。

以MNIST為例,y_test_label是實際的正確label,prediction是預測值,可使用panda的crosstab function來作出混淆矩陣。

import pandas as pd

pd.crosstab(y_test_label, prediction, rownames=[‘label’], colnames=[‘predict’])

矩陣中的對角線是預測正確的次數,例如,3這個數字有992次預測正確,1有1124次,較少的是5,僅有852次。以本矩陣來說,可以發現5是最容易混淆的數字,1數字則不容易混淆。

接著,將y_test_label及prediction兩個dataset載入Panda,並顯示前兩筆record。

df = pd.DataFrame( {‘label’:y_test_label, ‘predict’:prediction} )

print(df.shape)

df[:2]

接著我們找出那15筆實際值是5,卻被預測為3的資料。

df[(df.label==5)&(df.predict==3)]

看看編號2810的圖片,字跡比較潦草,可以理解為何會被歸類為3。

plot_images_labels_prediction(x_test_image, y_test_label, prediction, idx=2810, num=1)

二.增加隱藏層神經元數目

原先模型在隱藏層的神經元數目為256個,我們把它增加為1000,看看可否增加其準碓率。重新建立模型如下:

model = Sequential()

model.add(Dense(units=1000, input_dim=784, kernel_initializer=’normal’, activation=’relu’))

model.add(Dense(units=10, kernel_initializer=’normal’, activation=’softmax’))

print(model.summary())

原先模型隱藏層的超參數是200960,現把它增加至795010,約四倍之多。

執行model.complile設定,這次epoch我們設為20次,接著再用model.fit進行訓練。由於增加了神經元數目,因此每一個epoch會比之前久一點點。

model.compile(loss=’categorical_crossentropy’, optimizer=’adam’, metrics=[‘accuracy’])

train_history = model.fit(x=x_Train_normalize, y=y_TrainOneHot, validation_split=0.2, epochs=20, batch_size=200, verbose=2)

以圖表方式顯示執行這20次epoch的準確率,發現train dataset的準確率已接近100%,但是test dataset的準確率只能維持在0.98左右,無法再提昇。這是過度擬合over-fitting的現象,尤其像這類參數多而訓練樣本又太少的情況,訓練出的模型相當容易產生過擬合現象。

show_train_history(train_history, ‘acc’, ‘val_acc’)

三.使用Dropout防止過度擬合

因為模型中的參數愈小代表模型愈簡單,愈不容易產生過擬合現象,所以一般常用於防止過度擬合的方法,是在模型的損失函數中針對模型的參數進行 懲罰」,以避免參數值過大。

Dropout的原理雖簡單,對於減少過度擬合的成效卻相當不錯。該方法是由 Hinton於其2012年論文「Improving neural networks by preventing co-adaptation of feature detectors」中所提出,方式是在進行 深度學習的訓練過程中,每一次的batch都會依據機率丟棄一定比例的神經元不予計算,因此,等於每一次都是在訓練不同的神經網路。

接著我們在模型中加入Dropout功能,機率指定為0.3:

from keras.layers import Dropout

model = Sequential()

model.add(Dense(units=1000, input_dim=784, kernel_initializer=’normal’, activation=’relu’))

model.add(Dropout(0.3))

model.add(Dense(units=10, kernel_initializer=’normal’, activation=’softmax’))

可透過summary指令看到Dropout功能已加入。

print(model.summary())

一樣執行20 epochs,每批次200筆data。

model.compile(loss=’categorical_crossentropy’, optimizer=’adam’, metrics=[‘accuracy’])

train_history = model.fit(x=x_Train_normalize, y=y_TrainOneHot, validation_split=0.2, epochs=20, batch_size=200, verbose=2)

繪出準確率圖表,發現其過度擬合的情況有所改善。

show_train_history(train_history, ‘acc’, ‘val_acc’)

計算模型的準確率結果是0.982:

scores = model.evaluate(x_Test_normalize, y_TestOneHot)

print()

print(‘accuracy=’, scores[1])

四.增加神經網路的層數

我們剛剛透過增加隱藏層的神經元數目稍微提高了準確率,再加入Dropout功能減少Overfitting的現象,接著,我們試著增加此神經網路隱藏層的層數至三層(目前為一層),看看能否提高準確率。

重新建立模型,並加入輸入層和隱藏層1

model = Sequential()

model.add(Dense(units=1000, input_dim=784, kernel_initializer=’normal’, activation=’relu’))

model.add(Dropout(0.3))

加入隱藏層2

model.add(Dense(units=1000, kernel_initializer=’normal’, activation=’relu’))

model.add(Dropout(0.3))

加入輸出層

model.add(Dense(units=10, kernel_initializer=’normal’, activation=’softmax’))

檢視模型的摘要架構

print(model.summary())

繪出準確率圖表。

計算模型的準確率結果是0.9841,較之前微幅的增加:

經過上方的步驟,我們試著透過:增加隱藏層神經元數目以及增加隱藏層的層數,來提高模型的準確率,另外,針對Over-fitting的現象,則使用了Dropout功能,減少過度擬合的現象,將準確率由0.9757提高到0.9841。

如果我們再持續深入去調整模型的各個參數,是有可能再提高其準確率,但,若要真正的大幅提昇,必須使用CNN卷積神經網路才行,因為CNN是真正能去看到圖像各個細節的一種神經網路,而非僅僅依賴各像素點的最小梯度計算而已。

本文的程式碼已放置於 https://172.30.17.84:9999/notebooks/CH06.ipynb 。您可參考並執行看看或試著從https://172.30.17.84:9999開啟一個新檔案依本文的步驟來實作。