TensorFlow訓練MNIST數據集(3) —— 卷積神經網絡

 

  前面兩篇隨筆實現的單層神經網絡 和多層神經網絡, 在MNIST測試集上的正確率分別約爲90%和96%。在換用多層神經網絡後,正確率已有很大的提高。此次將採用卷積神經網絡繼續進行測試。html

 

一、模型基本結構git

  以下圖所示,本次採用的模型共有8層(包含dropout層)。其中卷積層和池化層各有兩層。網絡

  在整個模型中,輸入層負責數據輸入;卷積層負責提取圖片的特徵;池化層採用最大池化的方式,突出主要特徵,並減小參數維度;全鏈接層再將個特徵組合起來;dropout層能夠減小每次訓練的計算量,並能夠必定程度上避免過擬合問題;最後輸出層再綜合各特徵數據,得出最終結果。ide

  Dropout層起始並無增長訓練參數,只是隨機的將某些節點間的鏈接弧斷開,使其在本次中暫時的不參與訓練。函數

二、數據預處理測試

  首先讀取用於訓練的數據。spa

from tensorflow.examples.tutorials.mnist import input_data

mnist = input_data.read_data_sets('./data/mnist', one_hot=True)

  在前面的輸入層中,輸入的每一個樣本都是一維的數據,而卷積神經網絡的樣本數據將是多維的。所以咱們須要將讀取到的數據再reshape一下,使其符合要求。code

data.reshape([batchSize, 28, 28, 1])

 

三、輸入層orm

  輸入層的shape爲:bitchSize * 28 * 28 * 1,第一個參數表示每一個mini-batch的樣本數量,由傳入None可讓TensorFlow自動推斷;後面三個參數表示每一個樣本的高爲28,寬爲28,通道數爲1。htm

inputLayer = tf.placeholder(tf.float32, shape=[None, 28, 28, 1])

 

四、卷積層

  第一個卷積層的卷積核大小爲5 * 5,數量爲32個。padding方式採用‘SAME’。第二個卷積層相似,只是通道數,輸出維度不同。

1 convFilter1 = tf.Variable(tf.truncated_normal([5, 5, 1, 32], mean=0, stddev=0.1))
2 convBias1   = tf.Variable(tf.truncated_normal([32], mean=0, stddev=0.1))
3 convLayer1  = tf.nn.conv2d(input=inputLayer, filter=convFilter1, strides=[1, 1, 1, 1], padding='SAME')
4 convLayer1  = tf.add(convLayer1, convBias1)
5 convLayer1  = tf.nn.relu(convLayer1)

 

五、池化層

  滑動窗口的大小爲 2 * 2,在高和寬的維度上的滑動步幅也爲2,其餘維度爲1。本模型中第二個池化層與第一個池化層同樣。

poolLayer1 = tf.nn.max_pool(value=convLayer1, ksize=[1, 2, 2, 1], strides=[1, 2, 2, 1], padding='SAME')

 

 六、全鏈接層

  全鏈接層將前面在每一個樣本中提取到的多維特徵展開成一維,做爲全鏈接層的輸入。

1 fullWeight = tf.Variable(tf.truncated_normal(shape=[7 * 7 * 64, 1024], mean=0, stddev=0.1))
2 fullBias   = tf.Variable(tf.truncated_normal(shape=[1024], mean=0.0, stddev=0.1))
3 fullInput  = tf.reshape(poolLayer2, [-1, 7 * 7 * 64])
4 fullLayer  = tf.add(tf.matmul(fullInput, fullWeight), fullBias)
5 fullLayer  = tf.nn.relu(fullLayer)

 

七、Dropout層

  dropout層能夠防止過擬合問題。這裏指定的保留率爲0.8。

dropLayer = tf.nn.dropout(fullLayer, keep_prob=0.8)

 

八、輸出層

  最終輸出10個數字的分類。

1 outputWeight = tf.Variable(tf.truncated_normal(shape=[1024, 10], mean=0.0, stddev=0.1))
2 outputBias   = tf.Variable(tf.truncated_normal(shape=[10], mean=0, stddev=0.1))
3 outputLayer  = tf.add(tf.matmul(dropLayer, outputWeight), outputBias)

 

  模型的其餘部分與前面的多層神經網絡差很少,這裏再也不贅述。

 

九、模型在訓練集與測試集上的表現

  從模型圖上能夠看到,本次採用的模型的複雜度比前面的多層神經網絡高不少。正因如此,每次迭代計算也比前面的耗時的多,後者單次耗時爲前者的1500多倍。可見雖然只增長了幾層(固然除了層數的增長還有節點數的增長),但增長的計算量很是的多。

  下面兩張圖爲卷積神經網絡前面部分和後面部分迭代的輸出結果,能夠發現到最後卷積神經網絡在訓練集上已經接近100%的準確率。

 

  在測試集上的準確率也達到了 98% 99%,比多層神經網絡提供了約2個百分點。

 

附:

  完整代碼以下:

 1 import tensorflow as tf
 2 from tensorflow.examples.tutorials.mnist import input_data
 3 import time
 4 
 5 # 讀取數據
 6 mnist = input_data.read_data_sets('./data/mnist', one_hot=True)
 7 
 8 # 輸入層
 9 inputLayer = tf.placeholder(tf.float32, shape=[None, 28, 28, 1])
10 
11 # 卷積層(1)
12 convFilter1 = tf.Variable(tf.truncated_normal([5, 5, 1, 32], mean=0, stddev=0.1))
13 convBias1   = tf.Variable(tf.truncated_normal([32], mean=0, stddev=0.1))
14 convLayer1  = tf.nn.conv2d(input=inputLayer, filter=convFilter1, strides=[1, 1, 1, 1], padding='SAME')
15 convLayer1  = tf.add(convLayer1, convBias1)
16 convLayer1  = tf.nn.relu(convLayer1)
17 
18 # 池化層(1)
19 poolLayer1 = tf.nn.max_pool(value=convLayer1, ksize=[1, 2, 2, 1], strides=[1, 2, 2, 1], padding='SAME')
20 
21 # 卷積層(2)
22 convFilter2 = tf.Variable(tf.truncated_normal([5, 5, 32, 64], mean=0, stddev=0.1))
23 convBias2   = tf.Variable(tf.truncated_normal([64], mean=0, stddev=0.1))
24 convLayer2  = tf.nn.conv2d(input=poolLayer1, filter=convFilter2, strides=[1, 1, 1, 1], padding='SAME')
25 convLayer2  = tf.add(convLayer2, convBias2)
26 convLayer2  = tf.nn.relu(convLayer2)
27 
28 # 池化層(2)
29 poolLayer2 = tf.nn.max_pool(value=convLayer2, ksize=[1, 2, 2, 1], strides=[1, 2, 2, 1], padding='SAME')
30 
31 # 全鏈接層
32 fullWeight = tf.Variable(tf.truncated_normal(shape=[7 * 7 * 64, 1024], mean=0, stddev=0.1))
33 fullBias   = tf.Variable(tf.truncated_normal(shape=[1024], mean=0.0, stddev=0.1))
34 fullInput  = tf.reshape(poolLayer2, [-1, 7 * 7 * 64])
35 fullLayer  = tf.add(tf.matmul(fullInput, fullWeight), fullBias)
36 fullLayer  = tf.nn.relu(fullLayer)
37 
38 # dropout層
39 dropLayer = tf.nn.dropout(fullLayer, keep_prob=0.8)
40 
41 # 輸出層
42 outputWeight = tf.Variable(tf.truncated_normal(shape=[1024, 10], mean=0.0, stddev=0.1))
43 outputBias   = tf.Variable(tf.truncated_normal(shape=[10], mean=0, stddev=0.1))
44 outputLayer  = tf.add(tf.matmul(dropLayer, outputWeight), outputBias)
45 
46 # 標籤
47 outputLabel = tf.placeholder(tf.float32, shape=[None, 10])
48 
49 # 損失函數及目標函數
50 loss   = tf.reduce_mean(tf.nn.softmax_cross_entropy_with_logits_v2(labels=outputLabel, logits=outputLayer))
51 target = tf.train.AdamOptimizer().minimize(loss)
52 
53 # 記錄起始訓練時間
54 startTime = time.time()
55 
56 # 訓練
57 with tf.Session() as sess:
58     sess.run(tf.global_variables_initializer())
59     batchSize = 64
60     for i in range(1000):
61         batch = mnist.train.next_batch(batchSize)
62         inputData = batch[0].reshape([batchSize, 28, 28, 1])
63         labelData = batch[1]
64         sess.run([target, loss], feed_dict={inputLayer: inputData, outputLabel: labelData})
65 
66         corrected = tf.equal(tf.argmax(outputLabel, 1), tf.argmax(outputLayer, 1))
67         accuracy = tf.reduce_mean(tf.cast(corrected, tf.float32))
68         accuracyValue = sess.run(accuracy, feed_dict={inputLayer: inputData, outputLabel: labelData})
69         print(i, 'train set accuracy:', accuracyValue)
70 
71     # 打印結束時間
72     endTime = time.time()
73     print('train time:', endTime - startTime)
74 
75     # 測試
76     corrected  = tf.equal(tf.argmax(outputLabel, 1), tf.argmax(outputLayer, 1))
77     accuracy   = tf.reduce_mean(tf.cast(corrected, tf.float32))
78     testImages = mnist.test.images.reshape([-1, 28, 28, 1])
79     testLabels = mnist.test.labels
80     accuracyValue = sess.run(accuracy, feed_dict={inputLayer: testImages, outputLabel: testLabels})
81     print("accuracy on test set:", accuracyValue)
82 
83     sess.close()
View Code

 

本文地址:http://www.javashuo.com/article/p-beouisgr-cs.html

相關文章
相關標籤/搜索