深度學習第二課MINIST數字識別

數字識別

本次訓練一個能夠識別圖片的手寫數字的機器學習模型。

  1. 導入MNIST數據集
  2. 分析MNIST樣本特點定義變量。
  3. 構建模型。
  4. 訓練模型。
  5. 測試模型。
  6. 保存模型。
  7. 讀取模型。

1.導入MNIST數據集

從第一課我們可以知道需要一個數據集來訓練模型。
這個數據集就是圖片,來源於一個開源的訓練數據集—MNIST。
MNIST數據集的官網是 http://yann.lecun.com/exdb/mnist/
大家可以到官網去下載圖片的數據集。
在這裏插入圖片描述

同時TensorFlow也提供了一個庫,可以用來自動下載安裝MNIST。
代碼如下:

from tensorflow.examples.tutorials.mnist import input_data
mnist = input_data.read_data_sets("MNIST_data/", one_hot=True)

運行之後,會自動下載數據集並且解壓到當前代碼同級目錄下面的MNIST_data文件夾下。

代碼之中的one_hot = true,表示將樣本標籤轉換爲one_hot編碼。因爲本例是識別數字,計算機在得出結果後,會通過該種方式表達得到的結果。比如一張圖片被識別爲數字1,則計算機表達爲[1.0.0.0.0.0.0.0.0.0],如果是被識別爲數字2,則計算機表達爲[0.1.0.0.0.0.0.0.0.0],被識別爲3的話,則計算機表達爲[0.0.1.0.0.0.0.0.0.0]。後面的以此類推,且只需要表示0~9的數字。

在MNIST數據集的圖片,每張圖片是28×28的像素值。
圖片黑色的地方的RGB值爲0。
關於像素值和RGB可以看看之前我寫的圖像處理的博客的前面一部分:
博文鏈接:https://blog.csdn.net/qq_44807642/article/details/98205162

我們先將數據集的信息打印出來,看一看具體內容。

import tensorflow as tf #導入tensorflow庫
from tensorflow.examples.tutorials.mnist import input_data
mnist = input_data.read_data_sets("MNIST_data/", one_hot=True)
import pylab 

print ('輸入數據:',mnist.train.images)
print('數據爲:',mnist.train.images.shape)

im = mnist.train.images[1]
im = im.reshape(-1,28)
pylab.imshow(im)
pylab.show()
    

運行效果如下圖:
在這裏插入圖片描述

在圖中,輸入數據是圖每點的RGB值,數據是代表有55000張這樣的圖片。相當於一個55000×784的二維數組。
第一個維度的數字55000的可以用來識別是哪張圖片。
第二個維度的數字784的可以識別該點的RGB值。

MNIST包含三個數據集,分別是
訓練數據集:用於訓練
測試數據集(mnist.test):用於評估訓練中的準確度
驗證數據集(mnist.validation):用於評估模型的準確度。

2.分析MNIST樣本特點定義變量。

因爲輸入圖片是個550000×784的矩陣。所以可以先創建一個[None,784]的佔位符x和一個[None,10]的佔位符y(因爲電腦輸出結果用one_hot編碼表示,所以用到[None,10]的佔位符)

tf.reset_default_graph()    #tf.reset_default_graph函數用於清除默認圖形堆棧並重置全局默認圖形。
# tf 輸入
x = tf.placeholder(tf.float32, [None, 784]) # mnist data維度 28*28=784
y = tf.placeholder(tf.float32, [None, 10]) # 0-9 數字

第三行代碼中的None,表示此張量第一個的維度可以是任何長度的,x就代表能夠輸入任意數量的MNIST圖像,每一張圖可以展成784維的向量。

3.構建模型。

3.1定義學習參數

在這個模型裏面一樣需要定義w(權重值),b(偏執值)。

W = tf.Variable(tf.random_normal([784, 10]))
b = tf.Variable(tf.zeros([10]))

學過線性代數可以知道,比如兩個矩陣[x,y]和[y,n]相乘,會得到一個[x,n]的新矩陣。
所以這裏就是我們爲什麼要把W定爲[784,10]的原因。
因爲我們最後需要的是一個10維的one_hot編碼。
我們用一個784維的圖片向量去乘以W,就可以得到一個10維向量了。

3.2定義輸出節點
pred = tf.nn.softmax(tf.matmul(x, W) + b)

其中matmul函數的源代碼是

matmul(
    a,
    b,
    transpose_a=False,
    transpose_b=False,
    adjoint_a=False,
    adjoint_b=False,
    a_is_sparse=False,
    b_is_sparse=False,
    name=None
)

就是將矩陣 a 乘以矩陣 b,生成a * b。

softmax的功能就是把一個N*1的向量歸一化爲(0,1)之間的值。達到分類的效果。

3.3反向定義
# Minimize error using cross entropy
cost = tf.reduce_mean(-tf.reduce_sum(y*tf.log(pred), reduction_indices=1))
#參數設置
learning_rate = 0.01 #學習率
# 使用梯度下降優化器
optimizer = tf.train.GradientDescentOptimizer(learning_rate).minimize(cost)

將上面生成的pred與樣本標籤y進行一次交叉熵的運算,後取平均值。

tf.reduce_sum()函數計算一個張量的各個維度上元素的總和。
tf.reduce_mean()計算張量的各個維度上的元素的平均值。

不停更新W,b使其cost值越來越小。

4.訓練模型。

在訓練模型中,我們將模型迭代25次,一次取100條數據訓練,間隔一次就進行顯示狀態。然後開始訓練。

training_epochs = 25
batch_size = 100
display_step = 1
saver = tf.train.Saver()
model_path = "log/521model.ckpt"

# 啓動session
with tf.Session() as sess:
    sess.run(tf.global_variables_initializer())# Initializing OP

    # 啓動循環開始訓練
    for epoch in range(training_epochs):
        avg_cost = 0.
        total_batch = int(mnist.train.num_examples/batch_size)
        # 遍歷全部數據集
        for i in range(total_batch):
            batch_xs, batch_ys = mnist.train.next_batch(batch_size)
           
            _, c = sess.run([optimizer, cost], feed_dict={x: batch_xs,
                                                          y: batch_ys})
            avg_cost += c / total_batch
        # 顯示訓練中的詳細信息
        if (epoch+1) % display_step == 0:
            print ("Epoch:", '%04d' % (epoch+1), "cost=", "{:.9f}".format(avg_cost))

    print( " Finished!")

5.使用模型

在訓練完成之後,我們就可以直接使用啦。

 # 測試 model
    correct_prediction = tf.equal(tf.argmax(pred, 1), tf.argmax(y, 1))
    # 計算準確率
    accuracy = tf.reduce_mean(tf.cast(correct_prediction, tf.float32))
    print ("Accuracy:", accuracy.eval({x: mnist.test.images, y: mnist.test.labels}))

這一段代碼爲測試代碼,可以先看下模型準確率

在這裏插入圖片描述

6.保存模型

	save_path = saver.save(sess, model_path)
    print("Model saved in file: %s" % save_path)

用這兩句代碼對模型進行保存,並輸出保存路徑。
並且在session創建之前添加saver和model_path的定義。

saver = tf.train.Saver()
model_path = "log/521model.ckpt"

然後我們就可以在代碼的同級目錄下找到log文件夾,裏面有有如下文件。
在這裏插入圖片描述

7.讀取模型

在模型儲存好後,我們用兩張圖片來實驗一下,用下面的session代碼替換掉以前的session。

with tf.Session() as sess:
    # Initialize variables
    sess.run(tf.global_variables_initializer())
    # Restore model weights from previously saved model
    saver.restore(sess, model_path)
    
     # 測試 model
    correct_prediction = tf.equal(tf.argmax(pred, 1), tf.argmax(y, 1))
    # 計算準確率
    accuracy = tf.reduce_mean(tf.cast(correct_prediction, tf.float32))
    print ("Accuracy:", accuracy.eval({x: mnist.test.images, y: mnist.test.labels}))
    
    output = tf.argmax(pred, 1)
    batch_xs, batch_ys = mnist.train.next_batch(2)
    outputval,predv = sess.run([output,pred], feed_dict={x: batch_xs})
    print(outputval,predv,batch_ys)

    im = batch_xs[0]
    im = im.reshape(-1,28)
    pylab.imshow(im)
    pylab.show()
    
    im = batch_xs[1]
    im = im.reshape(-1,28)
    pylab.imshow(im)
    pylab.show()

運行效果如下,到這裏我們就已經成功了!
在這裏插入圖片描述

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