1. 程式人生 > >MNIST資料集手寫體識別(MLP實現)

MNIST資料集手寫體識別(MLP實現)

github部落格傳送門
csdn部落格傳送門

本章所需知識:

  1. 沒有基礎的請觀看深度學習系列視訊
  2. tensorflow
  3. Python基礎

    資料下載連結:

  4. 深度學習基礎網路模型(mnist手寫體識別資料集)

    MNIST資料集手寫體識別(MLP實現)

import tensorflow as tf
import tensorflow.examples.tutorials.mnist.input_data as input_data  # 匯入下載資料集手寫體
mnist = input_data.read_data_sets('../MNIST_data/', one_hot=True)


class MLPNet:  # 建立一個MLPNet類
    def __init__(self):
        self.x = tf.placeholder(dtype=tf.float32, shape=[None, 784], name='input_x')  # 建立一個tensorflow佔位符(稍後傳入圖片資料),定義資料型別為tf.float32,形狀shape為 None為批次 784為資料集撐開的 28*28的手寫體圖片 name可選引數
        self.y = tf.placeholder(dtype=tf.float32, shape=[None, 10], name='input_label')  # 建立一個tensorflow佔位符(稍後傳入圖片標籤), name可選引數

        self.w1 = tf.Variable(tf.truncated_normal(shape=[784, 100], dtype=tf.float32, stddev=tf.sqrt(1 / 100)))  # 定義全連結 第一層/輸入層 變數w/神經元w/特徵數w 為截斷正態分佈 形狀shape為[784, 100](100個神經元個數的矩陣), stddev(標準差的值 一般情況為sqrt(1/當前神經元個數))
        self.b1 = tf.Variable(tf.zeros([100], dtype=tf.float32))  # 定義變數偏值b 值為零 形狀shape為 [100] 當前層w 的個數, 資料型別 dtype為tf.float32

        self.w2 = tf.Variable(tf.truncated_normal(shape=[100, 10], dtype=tf.float32, stddev=tf.sqrt(1 / 10)))  # 定義全連結 第二層/輸出層 變數w/神經元w/特徵數w 為截斷正態分佈 形狀為[上一層神經元個數, 當前輸出神經元個數] 由於我們是識別十分類問題,手寫體 0,1,2,3,4,5,6,7,8,9所以我們選擇十個神經元 stddev同上
        self.b2 = tf.Variable(tf.zeros([10], dtype=tf.float32))  # 設定原理同上

    # 前向計算
    def forward(self):
        self.forward_1 = tf.nn.relu(tf.matmul(self.x, self.w1) + self.b1)  # 全連結第一層
        self.forward_2 = tf.nn.relu(tf.matmul(self.forward_1, self.w2) + self.b2)  # 全連結第二層
        self.output = tf.nn.softmax(self.forward_2)  # softmax分類器分類
    
    # 後向計算
    def backward(self):
        self.cost = tf.reduce_mean(tf.square(self.output - self.y))  # 定義均方差損失
        self.opt = tf.train.AdamOptimizer().minimize(self.cost)      # 使用AdamOptimizer優化器 優化 self.cost損失函式

    # 計算識別精度
    def acc(self):
        # 將預測值 output 和 標籤值 self.y 進行比較
        self.z = tf.equal(tf.argmax(self.output, 1, name='output_max'), tf.argmax(self.y, 1, name='y_max'))
        # 最後對比較出來的bool值 轉換為float32型別後 求均值就可以看到滿值為 1的精度顯示
        self.accaracy = tf.reduce_mean(tf.cast(self.z, tf.float32))


if __name__ == '__main__':
    net = MLPNet()  # 啟動tensorflow繪圖的MLPNet
    net.forward()   # 啟動前向計算
    net.backward()  # 啟動後向計算
    net.acc()       # 啟動精度計算
    init = tf.global_variables_initializer()  # 定義初始化tensorflow所有變數操作
    with tf.Session() as sess:                # 建立一個Session會話
        sess.run(init)                        # 執行init變數內的初始化所有變數的操作
        for i in range(10000):                # 訓練10000次
            ax, ay = mnist.train.next_batch(100)  # 從mnist資料集中取資料出來 ax接收圖片 ay接收標籤
            loss, accaracy, _ = sess.run(fetches=[net.cost, net.accaracy, net.opt], feed_dict={net.x: ax, net.y: ay})  # 將資料喂進神經網路(以字典的方式傳入) 接收loss返回值
            if i % 1000 == 0:  # 每訓練1000次
                test_ax, test_ay = mnist.test.next_batch(100)  # 則使用測試集對當前網路進行測試
                test_output = sess.run(net.output, feed_dict={net.x: test_ax})  # 將測試資料喂進網路 接收一個output值
                z = tf.equal(tf.argmax(test_output, 1, name='output_max'), tf.argmax(test_ay, 1, name='test_y_max'))  # 對output值和標籤y值進行求比較運算
                accaracy2 = sess.run(tf.reduce_mean(tf.cast(z, tf.float32)))  # 求出精度的準確率進行列印
                print(accaracy2)  # 列印當前測試集的精度 

最後附上訓練截圖:

MLP