tensorfllow MNIST機器學習入門

MNIST機器學習入門

這個教程的目標讀者是對機器學習和TensorFlow都不太瞭解的新手。若是你已經瞭解MNIST和softmax迴歸(softmax regression)的相關知識,你能夠閱讀這個快速上手教程html

當咱們開始學習編程的時候,第一件事每每是學習打印"Hello World"。就比如編程入門有Hello World,機器學習入門有MNIST。python

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

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

在此教程中,咱們將訓練一個機器學習模型用於預測圖片裏面的數字。咱們的目的不是要設計一個世界一流的複雜模型 -- 儘管咱們會在以後給你源代碼去實現一流的預測模型 -- 而是要介紹下如何使用TensorFlow。因此,咱們這裏會從一個很簡單的數學模型開始,它叫作Softmax Regression。web

對應這個教程的實現代碼很短,並且真正有意思的內容只包含在三行代碼裏面。可是,去理解包含在這些代碼裏面的設計思想是很是重要的:TensorFlow工做流程和機器學習的基本概念。所以,這個教程會很詳細地介紹這些代碼的實現原理。算法

MNIST數據集

MNIST數據集的官網是Yann LeCun's website。在這裏,咱們提供了一份python源代碼用於自動下載和安裝這個數據集。你能夠下載這份代碼,而後用下面的代碼導入到你的項目裏面,也能夠直接複製粘貼到你的代碼文件裏面。編程

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

下載下來的數據集被分紅兩部分:60000行的訓練數據集(mnist.train)和10000行的測試數據集(mnist.test)。這樣的切分很重要,在機器學習模型設計時必須有一個單獨的測試數據集不用於訓練而是用來評估這個模型的性能,從而更加容易把設計的模型推廣到其餘數據集上(泛化)。後端

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

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

咱們把這個數組展開成一個向量,長度是 28x28 = 784。如何展開這個數組(數字間的順序)不重要,只要保持各個圖片採用相同的方式展開。從這個角度來看,MNIST數據集的圖片就是在784維向量空間裏面的點, 而且擁有比較複雜的結構 (提醒: 此類數據的可視化是計算密集型的)。

展平圖片的數字數組會丟失圖片的二維結構信息。這顯然是不理想的,最優秀的計算機視覺方法會挖掘並利用這些結構信息,咱們會在後續教程中介紹。可是在這個教程中咱們忽略這些結構,所介紹的簡單數學模型,softmax迴歸(softmax regression),不會利用這些結構信息。

所以,在MNIST訓練數據集中,mnist.train.images 是一個形狀爲 [60000, 784] 的張量,第一個維度數字用來索引圖片,第二個維度數字用來索引每張圖片中的像素點。在此張量裏的每個元素,都表示某張圖片裏的某個像素的強度值,值介於0和1之間。

相對應的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] 的數字矩陣。

如今,咱們準備好能夠開始構建咱們的模型啦!

Softmax迴歸介紹

咱們知道MNIST的每一張圖片都表示一個數字,從0到9。咱們但願獲得給定圖片表明每一個數字的機率。好比說,咱們的模型可能推測一張包含9的圖片表明數字9的機率是80%可是判斷它是8的機率是5%(由於8和9都有上半部分的小圓),而後給予它表明其餘數字的機率更小的值。

這是一個使用softmax迴歸(softmax regression)模型的經典案例。softmax模型能夠用來給不一樣的對象分配機率。即便在以後,咱們訓練更加精細的模型時,最後一步也須要用softmax來分配機率。

softmax迴歸(softmax regression)分兩步:第一步

爲了獲得一張給定圖片屬於某個特定數字類的證據(evidence),咱們對圖片像素值進行加權求和。若是這個像素具備很強的證聽說明這張圖片不屬於該類,那麼相應的權值爲負數,相反若是這個像素擁有有利的證據支持這張圖片屬於這個類,那麼權值是正數。

下面的圖片顯示了一個模型學習到的圖片上每一個像素對於特定數字類的權值。紅色表明負數權值,藍色表明正數權值。

咱們也須要加入一個額外的偏置量(bias),由於輸入每每會帶有一些無關的干擾量。所以對於給定的輸入圖片 x 它表明的是數字 i 的證據能夠表示爲

其中 表明權重, 表明數字 i 類的偏置量,j 表明給定圖片 x 的像素索引用於像素求和。而後用softmax函數能夠把這些證據轉換成機率 y

這裏的softmax能夠當作是一個激勵(activation)函數或者連接(link)函數,把咱們定義的線性函數的輸出轉換成咱們想要的格式,也就是關於10個數字類的機率分佈。所以,給定一張圖片,它對於每個數字的吻合度能夠被softmax函數轉換成爲一個機率值。softmax函數能夠定義爲:

展開等式右邊的子式,能夠獲得:

可是更多的時候把softmax模型函數定義爲前一種形式:把輸入值當成冪指數求值,再正則化這些結果值。這個冪運算表示,更大的證據對應更大的假設模型(hypothesis)裏面的乘數權重值。反之,擁有更少的證據意味着在假設模型裏面擁有更小的乘數係數。假設模型裏的權值不能夠是0值或者負值。Softmax而後會正則化這些權重值,使它們的總和等於1,以此構造一個有效的機率分佈。(更多的關於Softmax函數的信息,能夠參考Michael Nieslen的書裏面的這個部分,其中有關於softmax的可交互式的可視化解釋。)

對於softmax迴歸模型能夠用下面的圖解釋,對於輸入的xs加權求和,再分別加上一個偏置量,最後再輸入到softmax函數中:

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

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

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

實現迴歸模型

爲了用python實現高效的數值計算,咱們一般會使用函數庫,好比NumPy,會把相似矩陣乘法這樣的複雜運算使用其餘外部語言實現。不幸的是,從外部計算切換回Python的每個操做,仍然是一個很大的開銷。若是你用GPU來進行外部計算,這樣的開銷會更大。用分佈式的計算方式,也會花費更多的資源用來傳輸數據。

TensorFlow也把複雜的計算放在python以外完成,可是爲了不前面說的那些開銷,它作了進一步完善。Tensorflow不單獨地運行單一的複雜計算,而是讓咱們能夠先用圖描述一系列可交互的計算操做,而後所有一塊兒在Python以外運行。(這樣相似的運行方式,能夠在很多的機器學習庫中看到。)

使用TensorFlow以前,首先導入它:

import tensorflow as tf 

咱們經過操做符號變量來描述這些可交互的操做單元,能夠用下面的方式建立一個:

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

x不是一個特定的值,而是一個佔位符placeholder,咱們在TensorFlow運行計算時輸入這個值。咱們但願可以輸入任意數量的MNIST圖像,每一張圖展平成784維的向量。咱們用2維的浮點數張量來表示這些圖,這個張量的形狀是[None,784 ]。(這裏的None表示此張量的第一個維度能夠是任何長度的。)

咱們的模型也須要權重值和偏置量,固然咱們能夠把它們當作是另外的輸入(使用佔位符),但TensorFlow有一個更好的方法來表示它們:Variable 。 一個Variable表明一個可修改的張量,存在在TensorFlow的用於描述交互性操做的圖中。它們能夠用於計算輸入值,也能夠在計算中被修改。對於各類機器學習應用,通常都會有模型參數,能夠用Variable表示。

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

咱們賦予tf.Variable不一樣的初值來建立不一樣的Variable:在這裏,咱們都用全爲零的張量來初始化Wb。由於咱們要學習Wb的值,它們的初值能夠隨意設置。

注意,W的維度是[784,10],由於咱們想要用784維的圖片向量乘以它以獲得一個10維的證據值向量,每一位對應不一樣數字類。b的形狀是[10],因此咱們能夠直接把它加到輸出上面。

如今,咱們能夠實現咱們的模型啦。只須要一行代碼!

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

首先,咱們用tf.matmul(​​X,W)表示x乘以W,對應以前等式裏面的,這裏x是一個2維張量擁有多個輸入。而後再加上b,把和輸入到tf.nn.softmax函數裏面。

至此,咱們先用了幾行簡短的代碼來設置變量,而後只用了一行代碼來定義咱們的模型。TensorFlow不只僅可使softmax迴歸模型計算變得特別簡單,它也用這種很是靈活的方式來描述其餘各類數值計算,從機器學習模型對物理學模擬仿真模型。一旦被定義好以後,咱們的模型就能夠在不一樣的設備上運行:計算機的CPU,GPU,甚至是手機!

訓練模型

爲了訓練咱們的模型,咱們首先須要定義一個指標來評估這個模型是好的。其實,在機器學習,咱們一般定義指標來表示一個模型是壞的,這個指標稱爲成本(cost)或損失(loss),而後儘可能最小化這個指標。可是,這兩種方式是相同的。

一個很是常見的,很是漂亮的成本函數是「交叉熵」(cross-entropy)。交叉熵產生於信息論裏面的信息壓縮編碼技術,可是它後來演變成爲從博弈論到機器學習等其餘領域裏的重要技術手段。它的定義以下:

y 是咱們預測的機率分佈, y' 是實際的分佈(咱們輸入的one-hot vector)。比較粗糙的理解是,交叉熵是用來衡量咱們的預測用於描述真相的低效性。更詳細的關於交叉熵的解釋超出本教程的範疇,可是你頗有必要好好理解它

爲了計算交叉熵,咱們首先須要添加一個新的佔位符用於輸入正確值:

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

而後咱們能夠用 計算交叉熵:

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

首先,用 tf.log 計算 y 的每一個元素的對數。接下來,咱們把 y_ 的每個元素和 tf.log(y_) 的對應元素相乘。最後,用 tf.reduce_sum 計算張量的全部元素的總和。(注意,這裏的交叉熵不只僅用來衡量單一的一對預測和真實值,而是全部100幅圖片的交叉熵的總和。對於100個數據點的預測表現比單一數據點的表現能更好地描述咱們的模型的性能。

如今咱們知道咱們須要咱們的模型作什麼啦,用TensorFlow來訓練它是很是容易的。由於TensorFlow擁有一張描述你各個計算單元的圖,它能夠自動地使用反向傳播算法(backpropagation algorithm)來有效地肯定你的變量是如何影響你想要最小化的那個成本值的。而後,TensorFlow會用你選擇的優化算法來不斷地修改變量以下降成本。

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

在這裏,咱們要求TensorFlow用梯度降低算法(gradient descent algorithm)以0.01的學習速率最小化交叉熵。梯度降低算法(gradient descent algorithm)是一個簡單的學習過程,TensorFlow只需將每一個變量一點點地往使成本不斷下降的方向移動。固然TensorFlow也提供了其餘許多優化算法:只要簡單地調整一行代碼就可使用其餘的算法。

TensorFlow在這裏實際上所作的是,它會在後臺給描述你的計算的那張圖裏面增長一系列新的計算操做單元用於實現反向傳播算法和梯度降低算法。而後,它返回給你的只是一個單一的操做,當運行這個操做時,它用梯度降低算法訓練你的模型,微調你的變量,不斷減小成本。

如今,咱們已經設置好了咱們的模型。在運行計算以前,咱們須要添加一個操做來初始化咱們建立的變量:

init = tf.initialize_all_variables()

如今咱們能夠在一個Session裏面啓動咱們的模型,而且初始化變量:

sess = tf.Session()
sess.run(init)

而後開始訓練模型,這裏咱們讓模型循環訓練1000次!

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}) 

該循環的每一個步驟中,咱們都會隨機抓取訓練數據中的100個批處理數據點,而後咱們用這些數據點做爲參數替換以前的佔位符來運行train_step

使用一小部分的隨機數據來進行訓練被稱爲隨機訓練(stochastic training)- 在這裏更確切的說是隨機梯度降低訓練。在理想狀況下,咱們但願用咱們全部的數據來進行每一步的訓練,由於這能給咱們更好的訓練結果,但顯然這須要很大的計算開銷。因此,每一次訓練咱們可使用不一樣的數據子集,這樣作既能夠減小計算開銷,又能夠最大化地學習到數據集的整體特性。

評估咱們的模型

那麼咱們的模型性能如何呢?

首先讓咱們找出那些預測正確的標籤。tf.argmax 是一個很是有用的函數,它能給出某個tensor對象在某一維上的其數據最大值所在的索引值。因爲標籤向量是由0,1組成,所以最大值1所在的索引位置就是類別標籤,好比tf.argmax(y,1)返回的是模型對於任一輸入x預測到的標籤值,而 tf.argmax(y_,1) 表明正確的標籤,咱們能夠用 tf.equal 來檢測咱們的預測是否真實標籤匹配(索引位置同樣表示匹配)。

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

這行代碼會給咱們一組布爾值。爲了肯定正確預測項的比例,咱們能夠把布爾值轉換成浮點數,而後取平均值。例如,[True, False, True, True] 會變成 [1,0,1,1] ,取平均值後獲得 0.75.

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

最後,咱們計算所學習到的模型在測試數據集上面的正確率。

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

這個最終結果值應該大約是91%。

這個結果好嗎?嗯,並不太好。事實上,這個結果是不好的。這是由於咱們僅僅使用了一個很是簡單的模型。不過,作一些小小的改進,咱們就能夠獲得97%的正確率。最好的模型甚至能夠得到超過99.7%的準確率!(想了解更多信息,能夠看看這個關於各類模型的性能對比列表。)

比結果更重要的是,咱們從這個模型中學習到的設計思想。不過,若是你仍然對這裏的結果有點失望,能夠查看下一個教程,在那裏你能夠學習如何用FensorFlow構建更加複雜的模型以得到更好的性能!

原文地址:MNIST For ML Beginners 翻譯:linbojin

 

 

 

深刻MNIST

TensorFlow是一個很是強大的用來作大規模數值計算的庫。其所擅長的任務之一就是實現以及訓練深度神經網絡。

在本教程中,咱們將學到構建一個TensorFlow模型的基本步驟,並將經過這些步驟爲MNIST構建一個深度卷積神經網絡。

這個教程假設你已經熟悉神經網絡和MNIST數據集。若是你還沒有了解,請查看新手指南.

安裝

在建立模型以前,咱們會先加載MNIST數據集,而後啓動一個TensorFlow的session。

加載MNIST數據

爲了方便起見,咱們已經準備了一個腳本來自動下載和導入MNIST數據集。它會自動建立一個'MNIST_data'的目錄來存儲數據。

import input_data mnist = input_data.read_data_sets('MNIST_data', one_hot=True) 

這裏,mnist是一個輕量級的類。它以Numpy數組的形式存儲着訓練、校驗和測試數據集。同時提供了一個函數,用於在迭代中得到minibatch,後面咱們將會用到。

運行TensorFlow的InteractiveSession

Tensorflow依賴於一個高效的C++後端來進行計算。與後端的這個鏈接叫作session。通常而言,使用TensorFlow程序的流程是先建立一個圖,而後在session中啓動它。

這裏,咱們使用更加方便的InteractiveSession類。經過它,你能夠更加靈活地構建你的代碼。它能讓你在運行圖的時候,插入一些計算圖,這些計算圖是由某些操做(operations)構成的。這對於工做在交互式環境中的人們來講很是便利,好比使用IPython。若是你沒有使用InteractiveSession,那麼你須要在啓動session以前構建整個計算圖,而後啓動該計算圖

import tensorflow as tf sess = tf.InteractiveSession() 

計算圖

爲了在Python中進行高效的數值計算,咱們一般會使用像NumPy一類的庫,將一些諸如矩陣乘法的耗時操做在Python環境的外部來計算,這些計算一般會經過其它語言並用更爲高效的代碼來實現。

但遺憾的是,每個操做切換回Python環境時仍須要不小的開銷。若是你想在GPU或者分佈式環境中計算時,這一開銷更加可怖,這一開銷主要多是用來進行數據遷移。

TensorFlow也是在Python外部完成其主要工做,可是進行了改進以免這種開銷。其並無採用在Python外部獨立運行某個耗時操做的方式,而是先讓咱們描述一個交互操做圖,而後徹底將其運行在Python外部。這與Theano或Torch的作法相似。

所以Python代碼的目的是用來構建這個能夠在外部運行的計算圖,以及安排計算圖的哪一部分應該被運行。詳情請查看基本用法中的計算圖表一節。

構建Softmax 迴歸模型

在這一節中咱們將創建一個擁有一個線性層的softmax迴歸模型。在下一節,咱們會將其擴展爲一個擁有多層卷積網絡的softmax迴歸模型。

佔位符

咱們經過爲輸入圖像和目標輸出類別建立節點,來開始構建計算圖。

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

這裏的xy並非特定的值,相反,他們都只是一個佔位符,能夠在TensorFlow運行某一計算時根據該佔位符輸入具體的值。

輸入圖片x是一個2維的浮點數張量。這裏,分配給它的shape[None, 784],其中784是一張展平的MNIST圖片的維度。None表示其值大小不定,在這裏做爲第一個維度值,用以指代batch的大小,意即x的數量不定。輸出類別值y_也是一個2維張量,其中每一行爲一個10維的one-hot向量,用於表明對應某一MNIST圖片的類別。

雖然placeholdershape參數是可選的,但有了它,TensorFlow可以自動捕捉因數據維度不一致致使的錯誤。

變量

咱們如今爲模型定義權重W和偏置b。能夠將它們看成額外的輸入量,可是TensorFlow有一個更好的處理方式:變量。一個變量表明着TensorFlow計算圖中的一個值,可以在計算過程當中使用,甚至進行修改。在機器學習的應用過程當中,模型參數通常用Variable來表示。

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

咱們在調用tf.Variable的時候傳入初始值。在這個例子裏,咱們把Wb都初始化爲零向量。W是一個784x10的矩陣(由於咱們有784個特徵和10個輸出值)。b是一個10維的向量(由於咱們有10個分類)。

Before Variables can be used within a session, they must be initialized using that session. This step takes the initial values (in this case tensors full of zeros) that have already been specified, and assigns them to each Variable. This can be done for all Variables at once.

變量須要經過seesion初始化後,才能在session中使用。這一初始化步驟爲,爲初始值指定具體值(本例當中是全爲零),並將其分配給每一個變量,能夠一次性爲全部變量完成此操做。

sess.run(tf.initialize_all_variables())

類別預測與損失函數

如今咱們能夠實現咱們的迴歸模型了。這隻須要一行!咱們把向量化後的圖片x和權重矩陣W相乘,加上偏置b,而後計算每一個分類的softmax機率值。

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

能夠很容易的爲訓練過程指定最小化偏差用的損失函數,咱們的損失函數是目標類別和預測類別之間的交叉熵。

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

注意,tf.reduce_sum把minibatch裏的每張圖片的交叉熵值都加起來了。咱們計算的交叉熵是指整個minibatch的。

訓練模型

咱們已經定義好模型和訓練用的損失函數,那麼用TensorFlow進行訓練就很簡單了。由於TensorFlow知道整個計算圖,它可使用自動微分法找到對於各個變量的損失的梯度值。TensorFlow有大量內置的優化算法 這個例子中,咱們用最速降低法讓交叉熵降低,步長爲0.01.

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

這一行代碼其實是用來往計算圖上添加一個新操做,其中包括計算梯度,計算每一個參數的步長變化,而且計算出新的參數值。

返回的train_step操做對象,在運行時會使用梯度降低來更新參數。所以,整個模型的訓練能夠經過反覆地運行train_step來完成。

for i in range(1000): batch = mnist.train.next_batch(50) train_step.run(feed_dict={x: batch[0], y_: batch[1]}) 

每一步迭代,咱們都會加載50個訓練樣本,而後執行一次train_step,並經過feed_dictxy_張量佔位符用訓練訓練數據替代。

注意,在計算圖中,你能夠用feed_dict來替代任何張量,並不只限於替換佔位符

評估模型

那麼咱們的模型性能如何呢?

首先讓咱們找出那些預測正確的標籤。tf.argmax 是一個很是有用的函數,它能給出某個tensor對象在某一維上的其數據最大值所在的索引值。因爲標籤向量是由0,1組成,所以最大值1所在的索引位置就是類別標籤,好比tf.argmax(y,1)返回的是模型對於任一輸入x預測到的標籤值,而 tf.argmax(y_,1) 表明正確的標籤,咱們能夠用 tf.equal 來檢測咱們的預測是否真實標籤匹配(索引位置同樣表示匹配)。

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

這裏返回一個布爾數組。爲了計算咱們分類的準確率,咱們將布爾值轉換爲浮點數來表明對、錯,而後取平均值。例如:[True, False, True, True]變爲[1,0,1,1],計算出平均值爲0.75

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

最後,咱們能夠計算出在測試數據上的準確率,大概是91%。

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

構建一個多層卷積網絡

在MNIST上只有91%正確率,實在太糟糕。在這個小節裏,咱們用一個稍微複雜的模型:卷積神經網絡來改善效果。這會達到大概99.2%的準確率。雖然不是最高,可是仍是比較讓人滿意。

權重初始化

爲了建立這個模型,咱們須要建立大量的權重和偏置項。這個模型中的權重在初始化時應該加入少許的噪聲來打破對稱性以及避免0梯度。因爲咱們使用的是ReLU神經元,所以比較好的作法是用一個較小的正數來初始化偏置項,以免神經元節點輸出恆爲0的問題(dead neurons)。爲了避免在創建模型的時候反覆作初始化操做,咱們定義兩個函數用於初始化。

def weight_variable(shape): initial = tf.truncated_normal(shape, stddev=0.1) return tf.Variable(initial) def bias_variable(shape): initial = tf.constant(0.1, shape=shape) return tf.Variable(initial) 

卷積和池化

TensorFlow在卷積和池化上有很強的靈活性。咱們怎麼處理邊界?步長應該設多大?在這個實例裏,咱們會一直使用vanilla版本。咱們的卷積使用1步長(stride size),0邊距(padding size)的模板,保證輸出和輸入是同一個大小。咱們的池化用簡單傳統的2x2大小的模板作max pooling。爲了代碼更簡潔,咱們把這部分抽象成一個函數。

def conv2d(x, W): return tf.nn.conv2d(x, W, strides=[1, 1, 1, 1], padding='SAME') def max_pool_2x2(x): return tf.nn.max_pool(x, ksize=[1, 2, 2, 1], strides=[1, 2, 2, 1], padding='SAME') 

第一層卷積

如今咱們能夠開始實現第一層了。它由一個卷積接一個max pooling完成。卷積在每一個5x5的patch中算出32個特徵。卷積的權重張量形狀是[5, 5, 1, 32],前兩個維度是patch的大小,接着是輸入的通道數目,最後是輸出的通道數目。 而對於每個輸出通道都有一個對應的偏置量。

W_conv1 = weight_variable([5, 5, 1, 32]) b_conv1 = bias_variable([32]) 

爲了用這一層,咱們把x變成一個4d向量,其第二、第3維對應圖片的寬、高,最後一維表明圖片的顏色通道數(由於是灰度圖因此這裏的通道數爲1,若是是rgb彩色圖,則爲3)。

x_image = tf.reshape(x, [-1,28,28,1]) 

We then convolve x_image with the weight tensor, add the bias, apply the ReLU function, and finally max pool. 咱們把x_image和權值向量進行卷積,加上偏置項,而後應用ReLU激活函數,最後進行max pooling。

h_conv1 = tf.nn.relu(conv2d(x_image, W_conv1) + b_conv1)
h_pool1 = max_pool_2x2(h_conv1)

第二層卷積

爲了構建一個更深的網絡,咱們會把幾個相似的層堆疊起來。第二層中,每一個5x5的patch會獲得64個特徵。

W_conv2 = weight_variable([5, 5, 32, 64]) b_conv2 = bias_variable([64]) h_conv2 = tf.nn.relu(conv2d(h_pool1, W_conv2) + b_conv2) h_pool2 = max_pool_2x2(h_conv2) 

密集鏈接層

如今,圖片尺寸減少到7x7,咱們加入一個有1024個神經元的全鏈接層,用於處理整個圖片。咱們把池化層輸出的張量reshape成一些向量,乘上權重矩陣,加上偏置,而後對其使用ReLU。

W_fc1 = weight_variable([7 * 7 * 64, 1024]) b_fc1 = bias_variable([1024]) h_pool2_flat = tf.reshape(h_pool2, [-1, 7*7*64]) h_fc1 = tf.nn.relu(tf.matmul(h_pool2_flat, W_fc1) + b_fc1) 

Dropout

爲了減小過擬合,咱們在輸出層以前加入dropout。咱們用一個placeholder來表明一個神經元的輸出在dropout中保持不變的機率。這樣咱們能夠在訓練過程當中啓用dropout,在測試過程當中關閉dropout。 TensorFlow的tf.nn.dropout操做除了能夠屏蔽神經元的輸出外,還會自動處理神經元輸出值的scale。因此用dropout的時候能夠不用考慮scale。

keep_prob = tf.placeholder("float") h_fc1_drop = tf.nn.dropout(h_fc1, keep_prob) 

輸出層

最後,咱們添加一個softmax層,就像前面的單層softmax regression同樣。

W_fc2 = weight_variable([1024, 10]) b_fc2 = bias_variable([10]) y_conv=tf.nn.softmax(tf.matmul(h_fc1_drop, W_fc2) + b_fc2) 

訓練和評估模型

這個模型的效果如何呢?

爲了進行訓練和評估,咱們使用與以前簡單的單層SoftMax神經網絡模型幾乎相同的一套代碼,只是咱們會用更加複雜的ADAM優化器來作梯度最速降低,在feed_dict中加入額外的參數keep_prob來控制dropout比例。而後每100次迭代輸出一第二天志。

cross_entropy = -tf.reduce_sum(y_*tf.log(y_conv))
train_step = tf.train.AdamOptimizer(1e-4).minimize(cross_entropy) correct_prediction = tf.equal(tf.argmax(y_conv,1), tf.argmax(y_,1)) accuracy = tf.reduce_mean(tf.cast(correct_prediction, "float")) sess.run(tf.initialize_all_variables()) for i in range(20000): batch = mnist.train.next_batch(50) if i%100 == 0: train_accuracy = accuracy.eval(feed_dict={ x:batch[0], y_: batch[1], keep_prob: 1.0}) print "step %d, training accuracy %g"%(i, train_accuracy) train_step.run(feed_dict={x: batch[0], y_: batch[1], keep_prob: 0.5}) print "test accuracy %g"%accuracy.eval(feed_dict={ x: mnist.test.images, y_: mnist.test.labels, keep_prob: 1.0}) 

以上代碼,在最終測試集上的準確率大概是99.2%。

目前爲止,咱們已經學會了用TensorFlow快捷地搭建、訓練和評估一個複雜一點兒的深度學習模型。

原文地址:Deep MNIST for Experts 翻譯:chenweican

相關文章
相關標籤/搜索