Tensorflow實戰入門:MNIST手寫數字識別

說在前頭

本文是使用BP神經網絡中的softmax迴歸模型實現MNIST手寫數字識別,實際上能實現MNIST手寫數字識別的神經網絡還有CNN(卷積神經網絡),下一篇可能會寫。

Tensorflow是個什麼東西

Tensorflow是一個採用 數據流圖,用於數值計算的開源軟件庫。節點在圖中表示數學操作,圖中的線則表示在節點間相互聯繫的多維數據數組,即張量(Tensor)。

數據流圖用“結點”和“線”的有向圖來描述數學計算。“節點” 一般用來表示施加的數學操作,但也可以表示數據輸入的起點/輸出的終點,或者是讀取/寫入持久變量的終點。“線”表示“節點”之間的輸入/輸出關係。這些數據“線”可以輸運“size可動態調整”的多維數據數組,即“張量”。張量從圖中流過的直觀圖像是這個工具取名爲“Tensorflow”的原因,Tensor(張量)和Flow(流動)。

以上是從Tensorflow官網中摘錄的一段文字,個人jio得介紹得挺貼切。把以上文字具象化理解,可以看下面這張圖。

在這裏插入圖片描述
在Tensorflow中進行的所有計算,都可以用類似這樣一種數據流圖來表達。Tensorflow把計算定義在計算圖中,把計算圖送到會話中執行。Tensorflow把計算分爲這麼兩步,目的是爲了兼具開發效率和計算效率。

  • TensorFlow將計算過程完全運行在Python外部。

  • Tensorflow依賴於一個高效的C++後端來進行計算,並通過session連接。

    先創建一個圖,然後在session中啓動它。

MNIST數據集

編程語言入門有Hello World,機器學習入門有MNIST。

MNIST是一個入門級的計算機視覺數據集,它包含各種手寫數字圖片,它也包含每一張圖片對應的標籤,告訴我們這個是數字幾。

MNIST數據集包含訓練集(60000張)和測試集(10000張)

  • mnist.train
    • mnist.train.images(60000,784)
    • mnist.train.labels(6000,10)
  • mnist.test
    • mnist.test.images(10000,784)
    • mnist.test.labels(10000,10)

用到的模型概述

本次用到的神經網絡模型簡潔地用圖來表示

在這裏插入圖片描述
如圖所示,本次用到的模型是BP神經網絡中的softmax迴歸模型,模型中有一個輸入層(接受特徵輸入)和一個輸出層(輸出層用了softmax激活函數)。

關於softmax函數的計算原理,可以看看這篇博客:一分鐘理解softmax函數(超簡單)

說白了softmax函數就是將一個樣本分別屬於各個類別的預測結果(暫且只是一系列的迴歸值,並沒有轉化爲概率)輸入softmax函數,進行非負性和歸一化處理,最後得到0-1之內的分類概率。

開始擼代碼

代碼邏輯分爲兩方面,分別是 定義計算圖執行會話

定義計算圖

  • 導入Tensorflow
import tensorflow as tf

在這裏插入圖片描述
放在工程目錄下的MNIST_data目錄下
在這裏插入圖片描述
然後代碼中使用tensorflow自帶的一個庫input_data把數據讀取進來

from tensorflow.examples.tutorials.mnist import input_data
mnist = input_data.read_data_sets("MNIST_data/",one_hot=True)
  • 我們來看看這些圖片長什麼樣

    import matplotlib.pyplot as plt
    img_bytes = mnist.train.images[2]
    img = img_bytes.reshape([28, 28])*255
    plt.imshow(img)
    

    長這樣,是一張手寫的數字圖片,像素爲28 * 28
    在這裏插入圖片描述

  • 定義輸入和輸出的佔位符,這裏並不顯式指定要輸入的特徵和特徵對應的實際標籤值

x_data = tf.placeholder(tf.float32, [None, 784])  # 佔位符:輸入
y_data = tf.placeholder(tf.float32, [None, 10])   # 佔位符:輸出
  • 隨機初始化神經網絡的參數和閾值

    w = tf.Variable(tf.zeros([784, 10]))   # 參數矩陣
    bias = tf.Variable(tf.zeros([10]))     # 閾值
    
  • 定義假設函數

    y = tf.nn.softmax(tf.matmul(x_data, w) + bias)   # 假設函數
    
  • 定義損失函數

    cross_entropy = tf.reduce_mean(-tf.reduce_sum(y_data*tf.log(y), axis=1))  # 損失函數(交叉熵)
    
  • 選擇優化器和定義訓練節點

    optimizer = tf.train.GradientDescentOptimizer(0.03)   # 梯度下降法優化器
    train = optimizer.minimize(cross_entropy)   # 訓練節點
    
  • 評估模型在訓練集上的精度

    correct_prediction = tf.equal(tf.argmax(y,1), tf.argmax(y_data,1))
    

    ​ 這行代碼會給我們一組布爾值。而爲了確定正確預測項的比例,我們可以把布爾值轉換成浮點數,然後 取平均值。例如,[True, False, True, True] 會變成 [1,0,1,1]

    acc = tf.reduce_mean(tf.cast(correct_prediction, dtype=tf.float32)) #模型預測值與樣本實際值比較的精度
    

執行會話

  • 啓動會話

    sess = tf.Session()
    
  • 會話執行變量初始化操作,當計算圖中含有變量的時候一定要執行這一步

    sess.run(tf.global_variables_initializer())
    
  • 開始模型訓練

    for i in range(20000):
        x_s, y_s = mnist.train.next_batch(100)   #每次迭代批量地從數據集中獲取數據
        sess.run(train, feed_dict={x_data:x_s, y_data:y_s})   #模型訓練
        if i%1000 == 0:     #每1000輪計算一次模型精度
            acc_tr = sess.run(acc, feed_dict={x_data: x_s, y_data: y_s})
            print(i, '輪訓練的精度', acc_tr)
    
  • 評估模型在測試集上的精度

acc_te = sess.run(acc, feed_dict={x_data:mnist.test.images, y_data:mnist.test.labels})  # 測試集精度
print('模型測試精度:', acc_te)
sess.close()

代碼運行結果

最終的模型測試精度爲0.9229,這個成績還行,因爲我們只是使用了一個比較簡單的模型。
在這裏插入圖片描述

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章