Tensorflow學習筆記:基礎篇(6)——Mnist手寫集改進版(Optimizer與Tensorboard)

Tensorflow學習筆記(6)——Mnist手寫集改進版(Optimizer優化器與Tensorboard)


前序

— 前文中,我們將三層全連接神經網絡的方差代價函數(二次代價函數)替換成交叉熵函數來完成MNIST數據的分類問題,最終迭代計算20次,準確率接近0.97,離我們預期的0.98甚至0.99依舊有差距。
— 本文我們在此基礎上繼續修改,主要有兩個目標:
(1)選用合適的優化器進行梯度下降,觀察準確率的變化~~
(2)開始使用Tensorboard
Reference:Tensorflow優化器比較


Tensorflow的優化器

Tensorflow中包含如下幾個優化器:
tf.train.GradientDescentOptimizer
tf.train.AdadeltaOptimizer
tf.train.AdagradOptimizer
tf.train.AdagradDAOptimizer
tf.train.MomentumOptimizer
tf.train.AdamOptimizer
tf.train.FtrlOptimizer
tf.train.ProximalGradientDescentOptimizer
tf.train.ProximalAdagradOptimizer
tf.train.RMSPropOptimizer
這裏寫圖片描述
Momentum:當前權值的改變會受到上一次權值改變的影響,類似於小球向下滾動的時候帶上了慣性。這樣可以加快小球的向下的速度。

NAG:在TF中跟Momentum合併在同一個函數tf.train.MomentumOptimizer中,可以通過參數配置啓用。在Momentun中小球會盲目地跟從下坡的梯度,容易發生錯誤,所以我們需要一個更聰明的小球,這個小球提前知道它要去哪裏,它還要知道走到坡底的時候速度慢下來而不是又衝上另一個坡,知道下一個位置大概在哪裏。從而我們可以提前計算下一個位置的梯度,然後使用到當前位置。

Adagrad:它是基於SGD的一種算法,它的核心思想是對比較常見的數據給予它比較小的學習率去調整參數,對於比較罕見的數據給予它比較大的學習率去調整參數。它很適合應用於數據稀疏的數據集(比如一個圖片數據集,有10000張狗的照片,10000張貓的照片,只有100張大象的照片)。Adagrad主要的優勢在於不需要人爲的調節學習率,它可以自動調節。它的缺點在於,隨着迭代次數的增多,學習率也會越來越低,最終會趨向於0。

RMSprop:借鑑了一些Adagrad的思想,不過這裏RMSprop只用到了前t-1次梯度平方的平均值加上當前梯度的平方的和的開平方作爲學習率的分母。這樣RMSprop不會出現學習率越來越低的問題,而且也能自己調節學習率,並且可以有一個比較好的效果。

Adadelta:我們甚至不需要設置一個默認學習率,在Adadelta不需要使用學習率也可以達到一個非常好的效果。

Adam:像Adadelta和RMSprop一樣,Adam會存儲之前衰減的平方梯度,同時它也會保存之前衰減的梯度。經過一些處理之後再使用類似Adadelta和RMSprop的方式更新參數。

本文采用的AdamOptimizer,同時會控制學習率的衰減,一開始速度很快,當越接近終點時,速度越來越慢。


Tensorboard

— 可視化是深度學習神經網絡開發、調試、應用中極爲重要的手段。當我們使用TensorFlow搭建深層神經網絡時,我們希望能夠了解整個網絡的結構,信息是如何傳遞,想了解每次訓練後權重值W與偏置值B是如何變化的,損失值、準確率的變化趨勢,等等。如果有一個工具能夠將這些數據直觀的表現出來,是不是方便我們進行觀察與調試呢,對模型有更深的理解呢~~
— Google推出的可視化工具Tensorboard,可以幫助我們實現以上功能,它可以將模型訓練過程中的各種數據彙總起來保存在日誌文件中,然後在指定的web端可視化地展現這些信息。
— 本文將帶領大家完成日誌文件的保存與成功打開Tensorboard。


代碼示例

1、數據準備

import tensorflow as tf
from tensorflow.examples.tutorials.mnist import input_data

# 載入數據集
mnist = input_data.read_data_sets("MNIST_data", one_hot=True)

# 每個批次送100張圖片
batch_size = 100
# 計算一共有多少個批次
n_batch = mnist.train.num_examples // batch_size

2、準備好placeholder

這次我們在placeholder中加入name這項參數,這當然是爲Tenseorboard做準備啦~~
這裏爲了剛纔說的,實現學習率逐漸衰減的AdamOptimizer,這裏我們建一個 lr 這一變量,命名爲learning_rate,初始值設爲0.01

x = tf.placeholder(tf.float32, [None, 784], name='x_input')
y = tf.placeholder(tf.float32, [None, 10], name='y_input')
lr = tf.Variable(0.001, dtype=tf.float32, name='learning_rate')

3、初始化參數/權重

這裏我將所有的權重與偏置也都命名,可以嘗試一下,如果不命名會發生什麼~~

W1 = tf.Variable(tf.truncated_normal([784, 500], stddev=0.1), name='W1')
b1 = tf.Variable(tf.zeros([500]) + 0.1, name='b1')
L1 = tf.nn.tanh(tf.matmul(x, W1) + b1, name='L1')

W2 = tf.Variable(tf.truncated_normal([500, 300], stddev=0.1), name='W2')
b2 = tf.Variable(tf.zeros([300]) + 0.1, name='b2')
L2 = tf.nn.tanh(tf.matmul(L1, W2) + b2, name='L2')

W3 = tf.Variable(tf.truncated_normal([300, 10], stddev=0.1), name='W3')
b3 = tf.Variable(tf.zeros([10]) + 0.1, name='b3')

4、計算預測結果

prediction = tf.nn.softmax(tf.matmul(L2, W3) + b3)

5、計算損失值

# 二次代價函數
# loss = tf.reduce_mean(tf.square(y - prediction))
# 交叉熵代價函數
loss = tf.reduce_mean(tf.nn.softmax_cross_entropy_with_logits(labels=y, logits=prediction))

6、初始化optimizer

這裏我們用tf.train.AdamOptimizer() 替代tf.train.GradientDescentOptimizer()

#learning_rate = 0.2
#optimizer =  tf.train.GradientDescentOptimizer(learning_rate).minimize(loss)
optimizer = tf.train.AdamOptimizer(lr).minimize(loss)

# 結果存放在一個布爾型列表中
correct_prediction = tf.equal(tf.argmax(y, 1), tf.argmax(prediction, 1))  

# 求準確率
accuracy = tf.reduce_mean(tf.cast(correct_prediction, tf.float32))

7、指定迭代次數,並在session執行graph

Tensorboard的可視化需要建立一個graph,你想從這個graph中獲取某些數據的信息,之後,我們使用tf.summary.FileWriter()將運行後輸出的數據文件都保存到本地磁盤(自己設定的文件路徑)中,我這裏選擇的是在這個程序文件的同目錄下,生成一個graphs文件夾,其中又會個名爲mnist的文件夾,生成的數據文件將保存在mnist文件夾中。

init = tf.global_variables_initializer()

with tf.Session() as sess:
    sess.run(init)
    writer = tf.summary.FileWriter('./graphs/mnist', sess.graph)

    for epoch in range(21):
        sess.run(tf.assign(lr, 0.001 * (0.95 ** epoch)))
        #這句語句,就是實現每次迭代後,學習率逐漸衰減,在最初開始的0.01基礎上,乘以0.95的迭代次數epoch次冪
        for batch in range(n_batch):
            batch_xs, batch_ys = mnist.train.next_batch(batch_size)
            sess.run(optimizer, feed_dict={x: batch_xs, y: batch_ys})

        test_acc = sess.run(accuracy, feed_dict={x: mnist.test.images, y: mnist.test.labels})
        learning_rate = sess.run(lr)
        if epoch % 2 == 0:
            print("Iter" + str(epoch) + ", Testing accuracy:" + str(test_acc) + ", Learning rate:" + str(learning_rate))
            #這裏我們每次輸出準確率的同時,輸出學習率

    writer.close()#最後別忘了將寫入文件操作關閉

運行結果

迭代計算依舊爲20次,準確率首次踏上了0.98,同時學習率按照我們的預期想法,隨迭代次數衰減,越接近結果時,學習率越來越慢。
這裏寫圖片描述
同時我們在graphs/mnist文件夾中生成了一個數據文件,順便說一下,這次我是用Macbook寫的,之前都是windows,大家不要覺得奇怪~~
這裏寫圖片描述
接下來我們要做的就是打開Tensorboard,在Macbook中打開終端輸入tensorboard –logdir=(logdir是兩個短橫!!!,不是一長橫
隨後將數據文件拖進終端頁面中,就會自動生成文件路徑,就像這樣:
這裏寫圖片描述
之後,我們將文件名刪除,只留下文件夾路徑即可,然後敲回車,就會出現這個畫面:
這裏寫圖片描述
將其中的http://appledeMacBook-Pro-3.local:6006 複製到你的谷歌瀏覽器中即可(其他瀏覽器可能會出錯,畢竟這是google家的,你懂得~~,)
這裏寫圖片描述
恭喜你,你已經成功打開了Tensorboard,好了下一篇我將重點講述Tensorboard的使用。


完整代碼

import tensorflow as tf
from tensorflow.examples.tutorials.mnist import input_data

mnist = input_data.read_data_sets("MNIST_data", one_hot=True)

# 每個批次的大小
batch_size = 100
# 計算一共有多少個批次
n_batch = mnist.train.num_examples // batch_size

x = tf.placeholder(tf.float32, [None, 784], name='x_input')
y = tf.placeholder(tf.float32, [None, 10], name='y_input')
lr = tf.Variable(0.001, dtype=tf.float32, name='learning_rate')


W1 = tf.Variable(tf.truncated_normal([784, 500], stddev=0.1), name='W1')
b1 = tf.Variable(tf.zeros([500]) + 0.1, name='b1')
L1 = tf.nn.tanh(tf.matmul(x, W1) + b1, name='L1')

W2 = tf.Variable(tf.truncated_normal([500, 300], stddev=0.1), name='W2')
b2 = tf.Variable(tf.zeros([300]) + 0.1, name='b2')
L2 = tf.nn.tanh(tf.matmul(L1, W2) + b2, name='L2')

W3 = tf.Variable(tf.truncated_normal([300, 10], stddev=0.1), name='W3')
b3 = tf.Variable(tf.zeros([10]) + 0.1, name='b3')
prediction = tf.nn.softmax(tf.matmul(L2, W3) + b3)

loss = tf.reduce_mean(tf.nn.softmax_cross_entropy_with_logits(labels=y, logits=prediction))


# 梯度下降
#optimizer = tf.train.GradientDescentOptimizer(0.2).minimize(loss)
optimizer = tf.train.AdamOptimizer(lr).minimize(loss)


correct_prediction = tf.equal(tf.argmax(y, 1), tf.argmax(prediction, 1))

accuracy = tf.reduce_mean(tf.cast(correct_prediction, tf.float32))

init = tf.global_variables_initializer()

with tf.Session() as sess:
    sess.run(init)
    writer = tf.summary.FileWriter('./graphs/mnist', sess.graph)

    for epoch in range(21):
        sess.run(tf.assign(lr, 0.001 * (0.95 ** epoch)))

        for batch in range(n_batch):
            batch_xs, batch_ys = mnist.train.next_batch(batch_size)
            sess.run(optimizer, feed_dict={x: batch_xs, y: batch_ys})

        test_acc = sess.run(accuracy, feed_dict={x: mnist.test.images, y: mnist.test.labels})
        learning_rate = sess.run(lr)

        if epoch % 2 == 0:
            print("Iter" + str(epoch) + ", Testing accuracy:" + str(test_acc) + ", Learning rate:" + str(learning_rate))

    writer.close()

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