神經網路實現Mnist手寫數字識別筆記
目錄
1.Mnist手寫數字識別介紹
Mnist手寫數字識別是Kaggle上一個很經典的機器學習資料集,裡邊包括55000張訓練資料和10000張圖片的測試資料,每張圖片大小為28*28畫素的單通圖片。該任務為通過機器學習來識別圖片中的數字屬於0,1,2,3,4,5,6,7,8,9中那個,是個典型的多分類問題。
圖片長什麼樣呢?展示如下:
2.神經網路架構介紹
神經網路在設計開始前,我們只能知道多少個訓練樣本、多少個特徵和最終需要怎樣的結果,對於中間層的神經元個數都是未知的,這常常需要在訓練過程中進行大量調整。對於手寫數字識別問題,我們知道訓練樣本為28*28的單色黑白影象,訓練樣本有55000個,最終要得出每張圖片的分類到底是數字0,1,2,3,4,5,6,7,8,9中哪一類。也就是說這是一個10分類問題。
神經網路每一層的神經元個數和層數雖說有很大的經驗成分,但是神經元個數要和在輸入資料維數和輸出資料維數之間相“契合”。對於神經網路來說,輸入的一張28*28畫素的影象是將其“壓扁”為784畫素的一維向量,這784個畫素點最為784個特徵。一張影象有784個特徵,那麼將N張影象同時輸入,則相當於將N*784的資料輸入。這裡的N通常是批量處理時每一次輸入資料的批量大小,比如本例子中我們每次遍歷輸入100張圖片,那麼N就是100。
神經網路中,上一層的輸出作為下一層的輸入。計算主要包括線性計算和非線性計算,線性計算就是x*w+bias,非線性計算則是對x*w+bias的計算結果進行非線性啟用,比如sigmod(
3.程式碼實現
import numpy as np import tensorflow as tf import matplotlib.pyplot as plt from tensorflow.examples.tutorials.mnist import input_data #獲取手寫字型識別資料 mnist = input_data.read_data_sets('data/', one_hot=True) #網路架構定義 #第一個隱層有256個神經元 n_hidden_1 = 256 #第二個隱層有128個神經元 n_hidden_2 = 128 #輸入的樣本有784個特徵 n_input = 784 #手寫字分為0 1 2....9這10個類別 n_classes = 10 # 輸入和輸出 x = tf.placeholder("float", [None, n_input]) y = tf.placeholder("float", [None, n_classes]) # 各層網路引數定義 stddev = 0.1 weights = { 'w1': tf.Variable(tf.random_normal([n_input, n_hidden_1], stddev=stddev)), 'w2': tf.Variable(tf.random_normal([n_hidden_1, n_hidden_2], stddev=stddev)), 'out': tf.Variable(tf.random_normal([n_hidden_2, n_classes], stddev=stddev)) } biases = { 'b1': tf.Variable(tf.random_normal([n_hidden_1])), 'b2': tf.Variable(tf.random_normal([n_hidden_2])), 'out': tf.Variable(tf.random_normal([n_classes])) } #前向傳播計算 def multilayer_perceptron(_X, _weights, _biases): #根據輸入_X計算第一層 layer_1 = tf.nn.sigmoid(tf.add(tf.matmul(_X, _weights['w1']), _biases['b1'])) #以第一層layer_1作為輸入計算第二層 layer_2 = tf.nn.sigmoid(tf.add(tf.matmul(layer_1, _weights['w2']), _biases['b2'])) #以第二層layer_2作為輸入計算第三層,也就是計算輸出層 return (tf.matmul(layer_2, _weights['out']) + _biases['out']) # 前向傳播進行預測 pred = multilayer_perceptron(x, weights, biases) #求損失函式 cost = tf.reduce_mean(tf.nn.softmax_cross_entropy_with_logits(logits=pred, labels=y)) #使用隨機梯度下降進行優化 optm = tf.train.GradientDescentOptimizer(learning_rate=0.001).minimize(cost) #預測值和真實標籤進行對比,tf.argmax(pred, 1)返回的是pred中最大值的索引號 #tf.equal將預測的值和標籤值進行比較,相同為True,不相同為False corr = tf.equal(tf.argmax(pred, 1), tf.argmax(y, 1)) #tf.cast為型別轉換函式,將corr轉換為float型別資料 accr = tf.reduce_mean(tf.cast(corr, "float")) # INITIALIZER init = tf.global_variables_initializer() #訓練200個epoch training_epochs = 200 #每一個batch取100個樣本 batch_size = 100 display_step = 4 # LAUNCH THE GRAPH sess = tf.Session() sess.run(init) # 遍歷epoch for epoch in range(training_epochs): avg_cost = 0. #計算batch次數 total_batch = int(mnist.train.num_examples/batch_size) # 遍歷batch for i in range(total_batch): batch_xs, batch_ys = mnist.train.next_batch(batch_size) feeds = {x: batch_xs, y: batch_ys} sess.run(optm, feed_dict=feeds) avg_cost += sess.run(cost, feed_dict=feeds) avg_cost = avg_cost / total_batch # DISPLAY if (epoch+1) % display_step == 0: print ("Epoch: %03d/%03d cost: %.9f" % (epoch, training_epochs, avg_cost)) feeds = {x: batch_xs, y: batch_ys} train_acc = sess.run(accr, feed_dict=feeds) print ("TRAIN ACCURACY: %.3f" % (train_acc)) feeds = {x: mnist.test.images, y: mnist.test.labels} test_acc = sess.run(accr, feed_dict=feeds) print ("TEST ACCURACY: %.3f" % (test_acc)) print ("OPTIMIZATION FINISHED")
4.執行結果
執行結果如下,可以看出經過200輪訓練後,得到的測試精確度達到了0.884。
Epoch: 003/200 cost: 2.278398191
TRAIN ACCURACY: 0.260
TEST ACCURACY: 0.198
Epoch: 007/200 cost: 2.245890754
.......
Epoch: 191/200 cost: 0.457598143
TRAIN ACCURACY: 0.920
TEST ACCURACY: 0.883
Epoch: 195/200 cost: 0.452329346
TRAIN ACCURACY: 0.860
TEST ACCURACY: 0.883
Epoch: 199/200 cost: 0.447292094
TRAIN ACCURACY: 0.910
TEST ACCURACY: 0.884
OPTIMIZATION FINISHED
5.程式碼中部分方法介紹
1.tf.random_normal
功能:tf.random_normal()函式用於從服從指定正太分佈的數值中取出指定個數的值。 函式宣告:tf.random_normal(shape, mean=0.0, stddev=1.0, dtype=tf.float32, seed=None, name=None) 引數:shape: 輸出張量的形狀,必選 mean: 正態分佈的均值,預設為0 stddev: 正態分佈的標準差,預設為1.0 dtype: 輸出的型別,預設為tf.float32 seed: 隨機數種子,是一個整數,當設定之後,每次生成的隨機數都一樣 name: 操作的名稱
2.tf.nn.softmax_cross_entropy_with_logits
3.tf.equal(x, y, name=None)
功能:tf.equal用於判斷x和y是否相等,對於單個值直接進行判斷,相同返回True,不同返回False。對於向量則遍歷相同位置的數進行判斷,返回值也是向量,相同時對應位置為True,不相同時對應位置為False。
4.tf.cast(x, dtype, name=None)
功能:tf.cast為型別轉換函式,將x轉換為dtype型別資料。
5.tf.argmax(vector, 1)
功能:tf.argmax(vector, 1)返回的時vector中最大值的索引。如果vector是一個向量,那就返回其中最大值的索引,如果是一個矩陣,那就返回一個向量,這個向量的每一維都是對應矩陣行的最大值元素索引號。