TensorFlow框架(3)之MNIST機器學習入門

1. MNIST數據集

1.1 概述

  Tensorflow框架載tensorflow.contrib.learn.python.learn.datasets包中提供多個機器學習的數據集。本節介紹的是MNIST數據集,其功能都定義在mnist.py模塊中。python

MNIST是一個入門級的計算機視覺數據集,它包含各類手寫數字圖片:web

圖 11 數組

  它也包含每一張圖片對應的標籤,告訴咱們這個是數字幾。好比,上面這四張圖片的標籤分別是5,0,4,1網絡

1.2 加載

  有兩種方式能夠獲取MNIST數據集:框架

1) 自動下載

  TensorFlow框架提供了一個函數:read_data_sets,該函數可以實現自動下載的功能。以下所示的程序,就可以自動下載數據集。機器學習

from tensorflow.examples.tutorials.mnist import input_data 函數

mnist = input_data.read_data_sets("MNIST_data/", one_hot=True)性能

//因爲input_data只是對read_data_sets進行了包裝,其什麼也沒有作,因此咱們能夠直接使用read_data_sets. 學習

From tensorflow.contrib.learn.python.learn.datasets.mnist import read_data_sets 測試

Mnist=read_data_sets("MNIST_data",one_hot=True)

2) 手動下載

  用戶也可以手動下載數據集,而後向read_data_sets函數傳遞所在的本地目錄,以下所示:

from tensorflow.examples.tutorials.mnist import input_data

mnist = input_data.read_data_sets("/tmp/MNIST_data/", False, one_hot=True)

PS:

    MNIST數據集能夠Yann LeCun's website進行下載,如所示是下載後的目錄:/tmp/MNIST_data/

圖 12

1.3 結構

1) 數據分類

  自動下載方式的數據集被分紅如表 11所示的三部分。這樣的切分很重要,在機器學習模型設計時必須有一個單獨的測試數據集不用於訓練,而是用來評估這個模型的性能,從而更加容易把設計的模型推廣到其餘數據集上(泛化)。

表 11

數據集

目的

mnist.train

55000 圖片和標籤, 用於訓練。

mnist.test

10000 圖片和標籤, 用於最終測試訓練的準確性。

mnist.validation

5000 圖片和標籤, 用於迭代驗證訓練的準確性。

PS:

  如果手動下載則只有兩部分,即表中的train和test兩部分。

2) 數據展開

  正如前面提到的同樣,每個MNIST數據單元有兩部分組成:一張包含手寫數字的圖片和一個對應的標籤。咱們把這些圖片設爲"X",把這些標籤設爲"Y"。訓練數據集和測試數據集都包含X和Y,好比訓練數據集的圖片是 mnist.train.images ,訓練數據集的標籤是 mnist.train.labels。

  其中每一張圖片包含28像素*28像素。咱們能夠用一個數字數組來表示這張圖片:

圖 13

  TensorFlow把這個數組展開成一個向量(數組),長度是 28x28 = 784,即TensorFlow將一個二維的數組展開成一個一維的數組,從[28, 28]數組轉換爲[784]數組。所以,在MNIST訓練數據集中,mnist.train.images 是一個形狀爲 [60000, 784] 的張量,第一個維度數字用來索引圖片,第二個維度數字用來索引每張圖片中的像素點。在此張量裏的每個元素,都表示某張圖片裏的某個像素的灰度值,值介於0和1之間,如圖 14所示的二維結構。

圖 14

  相對應的MNIST數據集的標籤是介於0到9的數字,用來描述給定圖片裏表示的數字。爲了用於這個教程,咱們使標籤數據是"one-hot vectors"。一個one-hot向量除了某一位的數字是1之外其他各維度數字都是0。因此在此教程中,數字n將表示成一個只有在第n維度(從0開始)數字爲1的10維向量。好比,標籤0將表示成([1,0,0,0,0,0,0,0,0,0,0])。所以,mnist.train.labels 是一個 [60000, 10] 的數字矩陣。

圖 15

2. MNIST分類學習

2.1 實現理論

2.1.1 M-P神經元模型

  傳統的M-P神經元模型中,每一個神經元都接收來自n個其它神經元傳遞過來的輸入信號,這些輸入信號經過待權重的鏈接進行傳遞,神經元接收到的總輸入值將與神經元的閾值進行比較,而後經過"激活函數"處理以產生神經元的輸出。如圖 21所示的一個神經元模型。

圖 21

PS:

    圖中所示的值都爲real value,並不是爲向量或矩陣。

2.1.2 softmax函數

  softmax函數與sigmoid函數相似均可以做爲神經網絡的激活函數。sigmoid將一個real value映射到(0,1)的區間(固然也能夠是(-1,1)),這樣能夠用來作二分類。

而softmax把一個k維的real value向量[a1,a2,a3,a4….]映射成一個[b1,b2,b3,b4….],其中bi是一個0-1的常數,而後能夠根據bi的大小來進行多分類的任務,如取權重最大的一維。

因此對於MNIST分類任務是多分類類型,因此須要使用softmax函數做爲神經網絡的激活函數。

2.1.3 MNIST模型分析

  正如圖 14所分析的,輸入的訓練圖片或測試圖片爲一個[60000, 784]的矩陣,每張圖片都是一個[784]的向量;輸出爲一個[60000, 10]的矩陣,每張圖片都對應有一個[10]的向量標籤。因此對於每張圖片的輸入和每一個標籤的輸出,其神經網絡模型可表示爲錯誤! 未找到引用源。所示的簡化版本,圖中全部值都爲read value。

圖 22 前饋神經網絡(一個帶有10個神經元的隱藏層)

 

  若是把它寫成一個等式,咱們能夠獲得:

咱們也能夠用向量表示這個計算過程:用矩陣乘法和向量相加。這有助於提升計算效率。(也是一種更有效的思考方式)

更進一步,能夠寫成更加緊湊的方式:

式中, B和Y都爲一個[10]類型的向量,X爲一個[784]類型的向量,W是一個[10,784]類型的矩陣。

 

2.2 TensorFlow實現

  對於機器學習中的監督學習任務能夠分四個步驟完成,以下所示:

  1. 模型選擇:選擇一個estimator對象;
  2. 模型訓練:根據訓練數據集來訓練模型;
  3. 模型測試:測量模型的泛化能力,即對其評分;
  4. 模型應用:進行實際預測或應用。

2.2.1 模型選擇

  因爲咱們已經選擇神經網絡爲監督學習任務的模型,即式(3)所示的等式,咱們可經過使用下標來代表等式中變量的維數,以下所示:

因此在TensorFlow中的實現,就須要定義相應的變量和等式。可是式(4)中的X是一個[784]的向量,而實際待訓練的輸入數據是一個[60000, 784] 的矩陣,因此須要對式(4)進行稍微的變形,使其知足數據輸入和數據輸出的要求,即以下所示的等式:

  • X是輸入參數,爲訓練數據,即多張圖像;
  • WB是未知參數,即經過神經網絡來訓練的數據;
  • Y爲輸出參數,爲圖像標籤,將使用該值與已知標籤進行比較。

 

以下所示是TensorFlow的實現:

# Create the model

x = tf.placeholder("float", [None, 784])

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

b = tf.Variable(tf.zeros([10]))

y = tf.nn.softmax(tf.matmul(x,W) + b)

2.2.2 模型訓練

1) 模型評估

  咱們能夠建立一個模型(model),但咱們仍然不知道模型的好壞。爲了評估一個TensorFlow模型的性能,咱們能夠提供一個指望值,而後比較模型產生值和指望值之差來進行評估。

傳統方法採用"均分偏差"法評估一個模型的性能:,首先提供一個指望向量,而後對產生值(f(x))和指望值(y)兩個向量的每一個元素進行取平方差,而後求出每一個元素的總和。

    因爲傳遞神經網絡採用梯度降低法來逐漸調整式(4)中的W和B參數,即逐步減小均分偏差的值;然而若以"均分偏差"爲標準逐步調整參數,其歸約的速度很是慢。因此提出以"交叉熵"法爲標準評估模型的值,以下所示:

以下所示的TensorFlow實現:

# Define loss and optimizer

y_ = tf.placeholder("float", [None,10])

cross_entropy = -tf.reduce_sum(y_ * tf.log(y))

 

2) 訓練過程

  TensorFlow提供多個優化器來逐步優化模型,即逐步優化未知參數。優化器以用戶指定的評估的偏差爲優化目標,即最小化模型評估的偏差,或最大化模型評估的偏差。

優化器基於梯度降低法自動修改神經網絡的訓練參數,即W和b的值。

以下是以GradientDescentOptimizer優化器爲示例的訓練過程:

# Train

train_step = tf.train.GradientDescentOptimizer(0.01).minimize(cross_entropy)

for i in range(1000):

batch_xs, batch_ys = mnist.train.next_batch(100)

sess.run(train_step, feed_dict={x: batch_xs, y_: batch_ys})

 

2.2.3 模型測試

  爲了評估模型的泛化性能,咱們經過比較產生值(f(x))和指望值(y)之間的差別來進行評測性能。

因爲本節的MNIST數據標籤(輸出值)是一個one-hot的便利,向量中的元素直郵一個爲"1",因此使用特性的比較方式,以下所示是TensorFlow的實現:

# Test trained model

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

accuracy = tf.reduce_mean(tf.cast(correct_prediction, "float"))

print(sess.run(accuracy, feed_dict={x: mnist.test.images, y_: mnist.test.labels}))

其中:

  • tf.argmax:能給出某個tensor對象在某一維上的其數據最大值所在的索引值。因爲標籤向量是由0,1組成,所以最大值1所在的索引位置就是類別標籤。
  • tf.cast:類型轉換,將一個tensor對象的全部元素類型轉換爲另外一種類型。即上述將tf.equal方法生成的布爾值轉換成浮點數。
  • tf.reduce_mean:求矩陣或向量的平均值。若x=[[1., 1.] [2., 2.]],則tf.reduce_mean(x) ==> 1.5=1+1+2+2/4

 

上述三個小節的完整程序以下所示:

from __future__ import print_function

import tensorflow as tf

from tensorflow.examples.tutorials.mnist import input_data

 

# Import data

mnist = input_data.read_data_sets("/tmp/MNIST_data/", False, one_hot=True)

 

# Create the model

x = tf.placeholder("float", [None, 784])

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

b = tf.Variable(tf.zeros([10]))

y = tf.nn.softmax(tf.matmul(x,W) + b)

 

# Define loss and optimizer

y_ = tf.placeholder("float", [None,10])

cross_entropy = -tf.reduce_sum(y_ * tf.log(y))

train_step = tf.train.GradientDescentOptimizer(0.01).minimize(cross_entropy)

 

init = tf.initialize_all_variables()

sess = tf.Session()

sess.run(init)

 

# Train

for i in range(1000):

batch_xs, batch_ys = mnist.train.next_batch(100)

sess.run(train_step, feed_dict={x: batch_xs, y_: batch_ys})

 

# Test trained model

#下述y的值是在上述訓練最後一步已經計算得到,因此可以與原始標籤y_進行比較

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

accuracy = tf.reduce_mean(tf.cast(correct_prediction, "float"))

print(sess.run(accuracy, feed_dict={x: mnist.test.images, y_: mnist.test.labels}))

3. 參考文獻

相關文章
相關標籤/搜索