在個人上一篇隨筆中,採用了單層神經網絡來對MNIST進行訓練,在測試集中只有約90%的正確率。此次換一種神經網絡(多層神經網絡)來進行訓練和測試。html
一、獲取MNIST數據git
MNIST數據集只要一行代碼就能夠獲取的到,很是方便。關於MNIST的基本信息能夠參考個人上一篇隨筆。網絡
mnist = input_data.read_data_sets('./data/mnist', one_hot=True)
二、模型基本結構dom
本次採用的訓練模型爲三層神經網絡結構,輸入層節點數與MNIST一行數據的長度一致,爲784;輸出層節點數與數字的類別數一致,爲10;隱藏層節點數爲50個;每次訓練的mini-batch數量爲64,;最大訓練週期爲50000。ide
1 inputSize = 784 2 outputSize = 10 3 hiddenSize = 50 4 batchSize = 64 5 trainCycle = 50000
三、輸入層函數
輸入層用於接收每次小批量樣本的輸入,先經過placeholder來進行佔位,在訓練時才傳入具體的數據。值得注意的是,在生成輸入層的tensor時,傳入的shape中有一個‘None’,表示每次輸入的樣本的數量,該‘None’表示先不做具體的指定,在真正輸入的時候再根據實際的數據來進行推斷。這個很方便,但也是有條件的,也就是經過該方法返回的tensor不能使用簡單的加(+)減(-)乘(*)除(/)符號來進行計算(不然將會報錯),須要用TensorFlow中的相關函數來進行代替。測試
inputLayer = tf.placeholder(tf.float32, shape=[None, inputSize])
四、隱藏層優化
在神經網絡中,隱藏層的做用主要是提取數據的特徵(feature)。這裏的權重參數採用了 tensorflow.truncated_normal() 函數來進行生成,與上次採用的 tensorflow.spa
random_normal() 不同。這二者的做用都是生成指定形狀、指望和標準差的符合正太分佈隨機變量。區別是 truncated_normal 函數對隨機變量的範圍有個限制(與指望的誤差在2個標準差以內,不然丟棄)。另外誤差項這裏也使用了變量的形式,也能夠採用常量來進行替代。 code
激活函數爲sigmoid函數。
1 hiddenWeight = tf.Variable(tf.truncated_normal([inputSize, hiddenSize], mean=0, stddev=0.1)) 2 hiddenBias = tf.Variable(tf.truncated_normal([hiddenSize])) 3 hiddenLayer = tf.add(tf.matmul(inputLayer, hiddenWeight), hiddenBias) 4 hiddenLayer = tf.nn.sigmoid(hiddenLayer)
五、輸出層
輸出層與隱藏層相似,只是節點數不同。
1 outputWeight = tf.Variable(tf.truncated_normal([hiddenSize, outputSize], mean=0, stddev=0.1)) 2 outputBias = tf.Variable(tf.truncated_normal([outputSize], mean=0, stddev=0.1)) 3 outputLayer = tf.add(tf.matmul(hiddenLayer, outputWeight), outputBias) 4 outputLayer = tf.nn.sigmoid(outputLayer)
六、輸出標籤
跟輸入層同樣,也是先佔位,在最後訓練的時候再傳入具體的數據。標籤,也就是每個樣本的正確分類。
outputLabel = tf.placeholder(tf.float32, shape=[None, outputSize])
七、損失函數
這裏採用的是交叉熵損失函數。注意用的是v2版本,第一個版本已被TensorFlow聲明爲deprecated,準備廢棄了。
loss = tf.reduce_mean(tf.nn.softmax_cross_entropy_with_logits_v2(labels=outputLabel, logits=outputLayer))
八、優化器與目標函數
優化器採用了Adam梯度降低法,我試過了普通的GradientDescentOptimizer,效果不如Adam;也用過Adadelta,結果幾乎收斂不了。
目標函數就是最小化損失函數。
optimizer = tf.train.AdamOptimizer()
target = optimizer.minimize(loss)
九、訓練過程
先建立一個會話,而後初始化tensors,最後進行迭代訓練。模型的收斂速度很快,在1000次的時候就達到了大概90%的正確率。
1 with tf.Session() as sess: 2 sess.run(tf.global_variables_initializer()) 3 4 for i in range(trainCycle): 5 batch = mnist.train.next_batch(batchSize) 6 sess.run(target, feed_dict={inputLayer: batch[0], outputLabel: batch[1]}) 7 8 if i % 1000 == 0: 9 corrected = tf.equal(tf.argmax(outputLabel, 1), tf.argmax(outputLayer, 1)) 10 accuracy = tf.reduce_mean(tf.cast(corrected, tf.float32)) 11 accuracyValue = sess.run(accuracy, feed_dict={inputLayer: batch[0], outputLabel: batch[1]}) 12 print(i, 'train set accuracy:', accuracyValue)
模型訓練輸出:
十、測試訓練結果
在測數據集上測試。準確率達到96%,比單層的神經網絡好不少。
1 corrected = tf.equal(tf.argmax(outputLabel, 1), tf.argmax(outputLayer, 1)) 2 accuracy = tf.reduce_mean(tf.cast(corrected, tf.float32)) 3 accuracyValue = sess.run(accuracy, feed_dict={inputLayer: mnist.test.images, outputLabel: mnist.test.labels}) 4 print("accuracy on test set:", accuracyValue)
測試集上的輸出:
附:
完整代碼以下:
1 import tensorflow as tf 2 from tensorflow.examples.tutorials.mnist import input_data 3 4 mnist = input_data.read_data_sets('./data/mnist', one_hot=True) 5 6 inputSize = 784 7 outputSize = 10 8 hiddenSize = 50 9 batchSize = 64 10 trainCycle = 50000 11 12 # 輸入層 13 inputLayer = tf.placeholder(tf.float32, shape=[None, inputSize]) 14 15 # 隱藏層 16 hiddenWeight = tf.Variable(tf.truncated_normal([inputSize, hiddenSize], mean=0, stddev=0.1)) 17 hiddenBias = tf.Variable(tf.truncated_normal([hiddenSize])) 18 hiddenLayer = tf.add(tf.matmul(inputLayer, hiddenWeight), hiddenBias) 19 hiddenLayer = tf.nn.sigmoid(hiddenLayer) 20 21 # 輸出層 22 outputWeight = tf.Variable(tf.truncated_normal([hiddenSize, outputSize], mean=0, stddev=0.1)) 23 outputBias = tf.Variable(tf.truncated_normal([outputSize], mean=0, stddev=0.1)) 24 outputLayer = tf.add(tf.matmul(hiddenLayer, outputWeight), outputBias) 25 outputLayer = tf.nn.sigmoid(outputLayer) 26 27 # 標籤 28 outputLabel = tf.placeholder(tf.float32, shape=[None, outputSize]) 29 30 # 損失函數 31 loss = tf.reduce_mean(tf.nn.softmax_cross_entropy_with_logits_v2(labels=outputLabel, logits=outputLayer)) 32 33 # 優化器 34 optimizer = tf.train.AdamOptimizer() 35 36 # 訓練目標 37 target = optimizer.minimize(loss) 38 39 # 訓練 40 with tf.Session() as sess: 41 sess.run(tf.global_variables_initializer()) 42 43 for i in range(trainCycle): 44 batch = mnist.train.next_batch(batchSize) 45 sess.run(target, feed_dict={inputLayer: batch[0], outputLabel: batch[1]}) 46 47 if i % 1000 == 0: 48 corrected = tf.equal(tf.argmax(outputLabel, 1), tf.argmax(outputLayer, 1)) 49 accuracy = tf.reduce_mean(tf.cast(corrected, tf.float32)) 50 accuracyValue = sess.run(accuracy, feed_dict={inputLayer: batch[0], outputLabel: batch[1]}) 51 print(i, 'train set accuracy:', accuracyValue) 52 53 # 測試 54 corrected = tf.equal(tf.argmax(outputLabel, 1), tf.argmax(outputLayer, 1)) 55 accuracy = tf.reduce_mean(tf.cast(corrected, tf.float32)) 56 accuracyValue = sess.run(accuracy, feed_dict={inputLayer: mnist.test.images, outputLabel: mnist.test.labels}) 57 print("accuracy on test set:", accuracyValue) 58 59 sess.close()