深度學習基礎 - MNIST實驗(tensorflow+MLP)

採用MLP(多層感知機)模型進行mnist分類任務,嘗試Adam、Dropout等訓練策略。

本文的完整代碼託管在我的Github PnYuan - Practice-of-Machine-Learning - MNIST_tensorflow_demo,歡迎交流。

1.任務背景

在前一篇深度學習基礎 - MNIST實驗(tensorflow+Softmax)的基礎上,我們進一步引入MLP(multi-layer perceptron - 多層感知機)來進行mnist實驗,以期實現更好的識別效果。

關於mnist數據集的相關基礎信息可參考前一篇文章MNIST官網

2.實驗過程

實驗參考代碼:python + tensorflow

2.1.MLP建模

這裏,MLP用於MNIST分類實驗,輸入是x - 28×28=784的圖片灰度向量,輸出是類別標籤y ~ [0,1,2,...,9],擬構建的MLP(全連接NN)模型如下圖示:

mlp_graph

這裏我們從一個無隱含層模型(即Softmax)開始,逐漸增加神經網絡規模,來觀察效果變化情況。

爲適應任意層數和層內神經元節點數的開發需求,編寫參數初始化和前向傳播函數如下:

'''(MLP) parameter initial'''
def mlp_param_init(dim):
    """
    @note: Initializes parameters to build a multi-layer perceptron with tensorflow.
        The shapes are:
            W1: [n1, n_x]
            B1: [n1, 1]
            W2: [n2, n1]
            B2: [n2, 1]
            ...
            Wl: [n_y, nl-1]
            Bl: [n_y, 1]

    @param dim: the number of unit in each level -- dim = [n_x, n1, n2, ..., n(l-1), n_y]    
    @return: parameters -- a dictionary of tensors containing W1, b1, W2, b2, W3, b3
    """
    parameters = {}
    l = len(dim)  # the layers' count

    # parameter initializing (using xavier_initializer for weight) (from 0 - input to l-1 - output)
    for i in range(1, l):
        parameters['W'+str(i)] = tf.get_variable('W'+str(i), [dim[i], dim[i-1]], initializer = tf.contrib.layers.xavier_initializer())   
        parameters['B'+str(i)] = tf.get_variable('B'+str(i), [dim[i], 1], initializer = tf.zeros_initializer())

    return parameters

'''(MLP) forward propagation'''
def mlp_forward_propagation(X, parameters):
    """
    @note: Implements the forward propagation for the model: LINEAR -> RELU -> LINEAR -> RELU ... -> LINEAR -> (SOFTMAX)

    @param X: input dataset placeholder, of shape (input size, number of examples)
    @param parameters: python dictionary containing your parameters "W1", "B1", "W2", "B2", ... the shapes are given in initialize_parameters.

    @return: Z_l the output of the last LINEAR unit
    """

    l = int(len(parameters)/2)  # the number of layer

    # for hidden layer(linear-->relu)
    A = X
    for i in range(1, l):
        W = parameters['W'+str(i)]
        B = parameters['B'+str(i)]
        Z = tf.add(tf.matmul(W, A), B)  # Z = np.dot(W, X) + B
        A = tf.nn.relu(Z)               # A = relu(Z)

    # for output layer(linear-->softmax) softmax is canceled here
    W = parameters['W'+str(l)]
    B = parameters['B'+str(l)]
    Z_l = tf.add(tf.matmul(W, A), B)

    return Z_l

這樣,通過輸入神經網絡維度變量dim,可構建出相應的MLP計算圖。

2.2.訓練與測試

設置超參數(如learning rate=0.05、mini-batch size=128、optimizer=GD等),加載MNIST數據集,然後通過在Session下運行Optimizer來進行訓練。得出不同神經網絡規模下效果如下,這裏的模型效果由分類準確率(Accuracy)來衡量。

dim NN層數 參數規模 訓練時耗 Accuracy (Train/Valid/Test)
[784,10] 1 7850 1’38” 90.5% / 91.0% / 91.0%
[784,20,10] 2 15910 1’34” 92.6% / 92.9% / 92.7%
[784,30,100,30,10] 4 29990 1’57” 95.3% / 95.4% / 95.0%

對比上表三次訓練可看出,隨着神經網絡規模的擴大,模型效果越來越好。截取tensorboard監視器上關於accuracy指標的變化曲線,進一步可對比如下圖:

acc_compare_size

2.3.改進

2.3.1.優化策略-Adam

採用MomentumAdam等優化策略替代原始的Gradient Descent,可以促進優化收斂,下面開展實驗對比了幾種優化策略的訓練效果:

訓練策略 Accuracy (Train/Valid/Test)
Gradient Descent 95.3% / 95.4% / 95.0%
Momentum 97.1% / 96.4% / 96.4%
Adagrad 96.7% / 96.4% / 96.0%
Adam 97.5% / 96.8% / 96.7%

各accuracy指標的變化曲線如下圖所示:

acc_compare_scheme

可以看出,優化策略調整之後,accuracy上升趨勢提早(收斂加快),這說明達到相同的指標,新策略比舊策略所需的訓練迭代次數更少,這對於提高深度學習訓練效率具有極其重要的意義。接下來,在Adam的基礎上,進一步調整learning_rate,num_epochs等超參數,經過一定時間的學習(≈10min),得出最終的預測結果爲:

train accuracy: 0.9851
valid accuracy: 0.9684
test accuracy: 0.9679

2.3.2.正則化-Dropout

對上面的最後預測結果進行bias-variance分析,假設bayes_optimal=human_level=0.99,則:

avoidable bais --> 1 - train accuracy = 0.005
variance --> train accuracy - valid accuracy = 0.017

於是,要進一步改進模型效果,需要從Variance入手,解決所出現的輕微Overfitting。這裏擬採用[Dropout](https://en.wikipedia.org/wiki/Dropout_(neural_networks)來進行模型優化。Dropout機制下,每次所訓練的神經網絡會以一定概率去掉一些節點,其示意圖如下(參考原文獻):

dropout_graph

由Dropout所產生的效用可形象地概括爲以下兩點:

  • 每一次訓練時,去掉一些節點,相當於實現了shrink weight,平抑了噪聲,產生“正則化”效果,減少過擬合。
  • 節點依概率隨機去除,使得多次訓練間的模型存在差異,產生“集成學習”的效果,提高整體精度。

這裏採用tf.nn.dropout()函數實現針對於隱層的Dropout,經過較長時間的訓練(≈20min),得出最終的結果爲:

train accuracy: 0.997
valid accuracy: 0.968
test accuracy: 0.969

實驗結果看來,經過更長時間的訓練,MLP訓練精度已經達到99.7%,這是一個很不錯的結果,而測試精度徘徊於97%左右,要做進一步提升或還需從其他改進策略入手。

3.實驗小結

本文通過搭建多層全連接神經網絡(MLP),開展了MNIST分類實驗。在該實驗中,我們對比了不同優化策略(GD、Adam等)對於訓練過程快慢的影響,嘗試了Dropout策略以應對過擬合問題。任務最終取得了不錯的效果。

此外我們還注意到,爲達到較高的精度,MLP需要較長的時間訓練,初步猜想其原因之一爲所需訓練的參數量大而導致的單次迭代計算耗時較長,這是由於MLP全連接模式所導致的。接下來,我們將進一步考察其他神經網絡架構(如CNN)在當前任務背景下的應用,並與MLP進行對比分析。

4.參考資料

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章