一文全解:利用谷歌深度學習框架Tensorflow識別手寫數字圖片(初學者篇)

筆記整理者:王小草 
筆記整理時間2017年2月24日 原文地址 http://blog.csdn.net/sinat_33761963/article/details/56837466?fps=1&locationNum=5git

Tensorflow官方英文文檔地址:https://www.tensorflow.org/get_started/mnist/beginners 
本文整理時官方文檔最近更新時間:2017年2月15日算法


1.案例背景

本文是跟着Tensorflow官方文檔的第二篇教程–識別手寫數字。數組

MNIST是一個簡單的計算機視覺數據集,它是由一系列手寫數字圖片組成的,好比: 
image_1b9kfq4dp1lk91qk212n1spikdh16.png-6.7kB數據結構

在數據集中,每一張圖片會有一個標籤label,表示該張圖片上的數字是什麼。好比以上圖片所對應的標籤是:5,0,4,1機器學習

對於初學者,爲何開篇就要介紹這個案例呢?舉個栗子, 當咱們學習寫程序的時候,第一句打印的就是「Hello world」。那麼MNIST相對於機器學習,就如同「Hello world」相對於程序ide

本文要介紹的是訓練一個模型,使得這個模型能夠根據輸入的圖片預測出上面寫的是什麼數字。可是本文的目的可不是去教你們訓練一個具備超級優秀表現的完美模型哦(這個在以後的文檔中會給出),而只是去創建一個簡單的模型(softmax regression)讓你們初嘗tensorflow情滋味.函數

雖然要完成這個模型,對tensorflow只是幾行代碼的事,但理解這背後tensorflow運做的原理以及核心的機器學習概念也是至關重要呢。因此,接下去會對整個過程與原理都進行詳細解釋。學習

2.數據的獲取:The MNIST Data

MNIST數據集能夠在網站http://yann.lecun.com/exdb/mnist/下載到。 
可是在TensorFlow中爲了方便學習者獲取這個數據,封裝了一個方法,咱們只須要調用這個方法,程序就會自動去下載和獲取數據集。代碼以下:測試

// 導入input_data這個類
from tensorflow.examples.tutorials.mnist import input_data //從這個類裏調用read_data_sets這個方法 mnist = input_data.read_data_sets("MNIST_data/", one_hot=True)

獲取到的數據集有3部分組成: 
(1)55,000個訓練樣本(用來訓練模型) 
(2)10,000個測試樣本(用來測試模型,避免過擬合) 
(3)5,000個驗證樣本(用來驗證超參數) 
(通常在機器學習的建模中,都須要準備這3類數據集。)優化

對於每個樣本點,有兩部分數據組成: 
(1)手寫數字圖片,記作x 
(2)標籤,記作y

手寫數字圖片由28*28像素組成,能夠將其轉換成28*28的由數字組成的數組。以下例子: 
image_1b9khd9j41naf1uu776i4s11bqs1j.png-18.4kB 
而這個28*28的數組又能夠鋪平成1*784的一個向量。至於鋪平的方式無所謂,只要保證全部圖片被鋪平的方式都同樣就行啦。因此,一個圖片能夠被一個1*784的向量所表示。

可能你會問,把圖片這樣從二維空間鋪平會不會喪失了一些信息,會帶來壞的影響嗎?這個你放心,如今那些最好的計算機圖像處理方法都是用了這個結構的,這在以後的教程中會有講到。

好了,若是運行以上兩行代碼成功,那麼數據就已經下載下來了,能夠直接調用mnist.train.images,獲取訓練數據集的圖片, 這是一個大小爲[55000, 784]的tensor,第一維是55000張圖片,第二維是784個像素。像素的強度是用0-1之間的數字表示的。 
image_1b9ki7q661uqp1od4m0bmps1d0120.png-11.4kB

另外上面也說了,每一個圖片會對應一個標籤,表示這個圖片上對應的手寫數字。 
根據須要,咱們須要將這0-9的數字標籤轉換成one-hot編碼,什麼是One-hot編碼,舉個例子一看便知,好比原來的標籤是3,編碼以後就變成了[0,0,0,1,0,0,0,0,0,0],也就是生成一個1*10的向量,分別對應0-9的數字在3對應的位置上爲1,其他位置上都是0. 
通過這樣編碼以後,訓練集的標籤數據就變成了[55000,10]的浮點類型的數組了。

恩恩,數據都下載下來,而且咱們也知道數據的具體格式和內容啦,接下去,讓咱們開始創建模型吧~~

3.創建多分類模型:Softmax Regressions

3.1 Softmax Regressions原理

由於咱們的目的是區分出0-9的數字,也就是要將圖片在這10個類中進行分類,屬於多元分類模型。對於一張圖片,咱們想要模型獲得的是屬於這10個類別的機率,舉個例子,若是模型判斷一張圖片屬於9的機率由80%,屬於8的機率是5%,屬於其餘數字的機率都很小,那麼最後這張圖片應被歸於9的類別。

Softmax Regressions是一個很是經典的用於多分類模型的方法。就算是以後的筆記中講到的更復雜的模型,他們的最後一層也是會調用Softmax 這個方法的。

一個Softmax Regressions主要有2步: 
(1)分別將輸入數據屬於某個類別的證據相加 
(2)將這個證據轉換成機率

好了,那麼首先這個證據是個神馬東東呢,其實就是一個線性模型,由權重w,與偏執項b組成: 
image_1b9klmfl61gdh1quj10j11j4e8qf2d.png-3.9kB 
i表示第i類,j表示輸入的這張圖片的第j個像素,也就是求將每一個像素乘以它的權重w,在加上偏執項的和。

求出了evidence以後,就要使用softmax函數將它轉換成機率了。 
image_1b9klvhnpkl91qh65oh1jto1nel2q.png-3.1kB

這裏的softmax其實至關因而一個激活函數或者鏈接函數,將輸出的結果轉換成咱們想要的那種形式(在這裏,是轉換成10各種別上的機率分佈)。那麼這個softmax的過程是通過了什麼樣的函數轉換呢?以下公式: 
image_1b9km32ul101e1mf1s53g2n1ccm37.png-4.4kB 
展開以上公式: 
image_1b9km3jfr1usv1ur5bod2m0ari3k.png-5.4kB 
也就是說,將剛剛的線性輸出evidence做爲softmax函數裏的輸入x,先進過一個冪函數,而後作正態化,使得全部的機率相加等於1.

將softmax regression的過程畫出來以下: 
image_1b9kmmqo41ibqu4rr081f4tncr4e.png-43.3kB

若是寫成公式,那就是以下: 
image_1b9kmne5l1el4nh91nnmsg91cpk4r.png-22.2kB

將以上公式作改進,變成矩陣和向量的形式: 
image_1b9kmoem1seburr1k1710p8113k58.png-18.5kB

要是想簡單直觀一點,那麼就這樣: 
image_1b9kmpnb0fqd13la1mjlifjt445l.png-3kB

至此,咱們知道了多元分類Softmax Regressions的計算原理,那麼接下去就能夠去嘗試用tensorflow來實現Softmax Regressions啦~

2.2 Tensorflow實現softmax regression

1.要使用tensorflow,實現導入tensorflow的庫:

import tensorflow as tf

2.爲輸入數據x建立佔位符

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

這裏的x並非具體的數值,而是一個佔位符,就是先給要輸入的數據霸佔一個位置,等當真的讓TensorFlow運行計算的時候,再傳入x的真實數據。由於咱們的輸入數據n個是1*784的向量,能夠表示成2層的tensor,大小是[None,784],None表示到時候後傳輸的數據能夠任何長度,也就是說能夠是任何數量的樣本點。

3.建立兩個權重變量 
w和b是在訓練過程當中不斷改變不斷優化的,使用Variable來建立:

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

以上,咱們初始化兩個權重都爲0,在以後的訓練與學習中會不斷被優化成其餘值。注意,w的大小是[784,10]表示784個像素輸入點乘以10維的向量(10個類別)。b的大小是[ 10 ]

4.創建softmax模型

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

以上代碼可見,咱們先將x與W相乘了,而後加上了b,而後將線性輸出通過softmax的轉換。

嗯,至此softmax的模型就寫好了。

4.模型訓練

1.創建損失函數 
上面咱們搭建了一個初始的softmax的模型,注意模型中的參數w,b是本身隨便定義的。那麼訓練模型的目的是讓模型在學習樣本的過程當中不斷地優化參數,使得模型的表現最好。

那麼如何評價模型表現的好壞呢?在機器學習中,咱們通常使用損失函數來評價模型的好壞。若是模型預測的結果與真實的結果相差越遠,那麼損失大,模型的表現就越很差。所以,咱們渴望去最小化損失從而獲得最優的模型。

這裏介紹一個最經常使用的損失函數:交叉熵損失。公式以下: 
image_1b9l3m4nm5kp1f1r2ch1tgm2k3p.png-3.9kB

y表示模型預測出來的機率分佈,y’表示真實的類別機率分佈(就是之間one-hot編碼以後的標籤)。yi表示預測爲第i個類的機率, yi’表示真實屬於i類的機率(只有i類爲1,其他爲0)

交叉熵從必定意義上能夠度量模型對於真實狀況的擬合程度,交叉熵越大,則模型越不擬合,表現力越差。

要實現交叉熵函數,代碼以下:

// 爲真實的標籤添加佔位符
y_ = tf.placeholder(tf.float32, [None, 10]) // 建立交叉熵函數 cross_entropy = tf.reduce_mean(-tf.reduce_sum(y_ * tf.log(y), reduction_indices=[1]))

解釋一下上面的代碼,tf.log表示將y的每個元素都作log運算;而後將其乘以對應的真實標籤的類別y_中的元素。tf.reduce_sum表示的是將索引爲1的值進行求和。tf.reduce_mean表示對全部樣本的交叉熵求均值。

注意注意,在源碼中,咱們沒有使用這個公式,由於這樣計算下去數值不穩定。取而代之的是直接在線性函數以後應用了tf.nn.softmax_cross_entropy_with_gogits(即,沒有單獨通過softmax函數),這樣會更加穩定。

2.使用BP算法優化參數 
損失函數就是咱們的目標函數,要找到目標函數的最小值,就是對參數求偏導等於0.咱們可使用優化器去不斷地下降損失尋找最優參數。好比說最經常使用的是梯度降低法。代碼以下:

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

上面使用了梯度降低法最小化交叉熵損失,學習率設置爲0.5,每一次迭代,w,b兩類參數都會改變,直到損失達到最小的時候,就得到了最優的w,b。 
不過tensorflow也提供了不少其餘的優化器(後續介紹)

3.運行迭代 
模型訓練的graph基本已經完成,如今咱們能夠初始化變量,建立會話,來進行循環訓練了。

// 建立會話
sess = tf.InteractiveSession() // 初始化全部變量 tf.global_variables_initializer().run() //循環1000次訓練模型 for _ in range(1000): # 獲取訓練集與標籤集,每次獲取100個樣本 batch_xs, batch_ys = mnist.train.next_batch(100) # 喂數據,訓練 sess.run(train_step, feed_dict={x: batch_xs, y_: batch_ys})

在每次循環中,都會從訓練集中獲取一批樣本,每批有100個樣本。而後運行train_step這個操做,而且給以前的佔位符喂入數據。

你可能會以爲奇怪,爲何不直接拿全部的訓練集來作循環訓練,爲啥每次要隨機地拿100個樣本呢?這裏應用了隨機梯度降低法。直接使用全部樣原本作循環迭代的「梯度降低法」當然更理想,可是會大大增長計算的成本,而「隨機梯度降低法」減小了計算量而且也保持了相對一致的準確率。

5.模型評估

經過模型的訓練,咱們獲得了最優的參數,可是在這個最優的參數下,模型的表現力到底如何呢?

咱們能夠看看在測試集上模型預測的label與樣本真實的Label相同的有多少比例。 
tf.argmax返回的是一個tensor裏在某個維度上最大值的索引,好比tf.argmax(y,1)取出的是預測輸出的10個類別的機率向量中最大機率的那個索引(對應某個類別),tf.argmax(y_,1)取出的是該樣本的真實類別的索引,若是對於一個樣本,二者相同,則說明對該樣本的預測正確。下面代碼,用tf.equal返回的是一個布爾類型的列表。

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

要求出正確率,只要將布爾類型的列表所有求和再求均值便可:

accuracy = tf.reduce_mean(tf.cast(correct_prediction, tf.float32))

如今咱們喂入測試數據集,來運行計算測試集上的準確率:

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

 

打印出來大概是92%。

這個結果好嗎?額。。其實並無呢,並且能夠說挺差的。。 
模型表現很差的緣由在於咱們使用的是一個很簡單的模型,作一些小的改良,正確率能夠達到97%。最好的模型能夠達到99.7的準確率!

至此,咱們介紹了完整的用tensorflow來訓練softmax regression多元分類模型的案例。

相關文章
相關標籤/搜索