神經網絡實現Mnist手寫數字識別

1.Mnist手寫數字識別介紹

? ? ? ? Mnist手寫數字識別是Kaggle上一個很經典的機器學習數據集,里邊包括55000張訓練數據和10000張圖片的測試數據,每張圖片大小為28*28像素的單通圖片。該任務為通過機器學習來識別圖片中的數字屬于0,1,2,3,4,5,6,7,8,9中那個,是個典型的多分類問題,以至于Tensorflow在其example中加入了該數據集,并提供了相應的實現方法。

? ? ? ?圖片長什么樣呢?展示如下:


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函數和ReLu(max(0, x*w+bias)函數。本例子對網絡架構定義如下圖所示,除了輸入層和輸出層外,增加了兩個隱藏層。隱藏層1設計了256個神經元,隱藏層2設計了128個神經元。那么,我們就可以推倒出W1和W2的大小。W1維度為:784*256,W2維度為:256*128,W3維度為:128*10。


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

https://blog.csdn.net/m0_37041325/article/details/77040060?utm_source=blogxgwz0?這篇博客對此有比較詳細的介紹,這個也是神經網絡的一個重點知識點。

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是一個向量,那就返回其中最大值的索引,如果是一個矩陣,那就返回一個向量,這個向量的每一維都是對應矩陣行的最大值元素索引號。

代碼github鏈接:https://github.com/zhuwsh/mnist-master

注意:當執行mnist = input_data.read_data_sets('data/', one_hot=True)因為各種原因(比如下載超時)而獲取不到數據集時,可以在網上直接搜索下載mnist數據集。或者從github鏈接https://github.com/zhuwsh/mnist-master獲取。

最后編輯于
?著作權歸作者所有,轉載或內容合作請聯系作者
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發布,文章內容僅代表作者本人觀點,簡書系信息發布平臺,僅提供信息存儲服務。

推薦閱讀更多精彩內容