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


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

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”相對於程序

本文要介紹的是訓練一個模型,使得這個模型可以根據輸入的圖片預測出上面寫的是什么數字。但是本文的目的可不是去教大家訓練一個具有超級優秀表現的完美模型哦(這個在之后的文檔中會給出),而只是去建立一個簡單的模型(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多元分類模型的案例。


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM