【TensorFlow官方文檔】MNIST機器學習入門


MNIST是一個入門級的計算機視覺數據集,它包含各種手寫數字圖片;它也包含每一張圖片對應的標簽,告訴我們這個是數字幾。比如,下面這四張圖片的標簽分別是5,0,4,1。

從一個很簡單的數學模型開始:訓練一個機器學習模型用於預測圖片里面的數字,它叫做Softmax Regression

  • Softmax回歸介紹

我們知道MNIST的每一張圖片都表示一個數字,從0到9。我們希望得到給定圖片代表每個數字的概率。比如說,我們的模型可能推測一張包含9的圖片代表數字9的概率是80%但是判斷它是8的概率是5%(因為8和9都有上半部分的小圓),然后給予它代表其他數字的概率更小的值。

softmax模型可以用來給不同的對象分配概率。softmax回歸(softmax regression)分兩步:

第一步,為了得到一張給定圖片屬於某個特定數字類的證據(evidence),我們對圖片像素值進行加權求和。如果這個像素具有很強的證據說明這張圖片不屬於該類,那么相應的權值為負數,相反如果這個像素擁有有利的證據支持這張圖片屬於這個類,那么權值是正數。下面的圖片顯示了一個模型學習到的圖片上每個像素對於特定數字類的權值。紅色代表負數權值,藍色代表正數權值。

我們也需要加入一個額外的偏置量(bias),因為輸入往往會帶有一些無關的干擾量。因此對於給定的輸入圖片x 它代表的是數字 i 的證據可以表示為

其中bi代表數字 i 類的偏置量,j代表給定圖片 x 的像素索引用於像素求和。然后用softmax函數可以把這些證據轉換成概率 y :

這里的softmax可以看成是一個激勵(activation)函數或者鏈接(link)函數,把我們定義的線性函數的輸出轉換成我們想要的格式,也就是關於10個數字類的概率分布。因此,給定一張圖片,它對於每一個數字的吻合度可以被softmax函數轉換成為一個概率值。softmax函數可以定義為:

展開等式右邊的子式,可以得到:

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

把它寫成一個等式:

  • 導入MNIST數據集
import input_data mnist = input_data.read_data_sets("MNIST_data/", one_hot=True) 

上面代碼是官方文檔里的,但你發現運行會出錯,改為下面這個代碼:

from tensorflow.examples.tutorials.mnist 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.labels 。

每一張圖片包含28X28個像素點。我們可以用一個數字數組來表示這張圖片(把這個數組展開成一個向量,長度是 28x28 = 784):

因此,在MNIST訓練數據集中,mnist.train.images 是一個形狀為 [60000, 784] 的張量,第一個維度數字用來索引圖片,第二個維度數字用來索引每張圖片中的像素點。

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

  • 實現回歸模型

使用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 和b 。因為我們要學習 W 和 b 的值,它們的初值可以隨意設置。

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

現在,我們可以實現我們的模型啦。只需要一行代碼!

y = tf.nn.softmax(tf.matmul(x,W) + b) 
  • 訓練模型

為了訓練我們的模型,我們首先需要定義一個指標來評估這個模型是好的。其實在機器學習,我們通常定義指標來表示一個模型是壞的,這個指標稱為成本(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也提供了其他許多優化算法:只要簡單地調整一行代碼就可以使用其他的算法。

在運行計算之前,我們需要添加一個操作來初始化我們創建的變量:

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%。

  • 完整運行代碼
import tensorflow as tf
from tensorflow.examples.tutorials.mnist import input_data

mnist = input_data.read_data_sets('G:\MNIST DATABASE\MNIST_data',one_hot=True)

def add_layers(inputdata,inputsize,outputsize,activation_function=None):
Weights = tf.Variable(tf.random_normal([inputsize,outputsize]))
biases = tf.Variable(tf.zeros([1,outputsize]) + 0.1)

Weights_biases_add = tf.matmul(inputdata,Weights) + biases

if activation_function is None:
outputs = Weights_biases_add
else:
outputs = activation_function(Weights_biases_add)

return outputs

def get_accuracy(v_x,v_y_):
global prediction
y_pre = sess.run(prediction,feed_dict={x:v_x})
correct_prediction = tf.equal(tf.argmax(y_pre,1),tf.argmax(v_y_,1))
accuracy = tf.reduce_mean(tf.cast(correct_prediction,tf.float32))
return sess.run(accuracy,feed_dict={x:v_x,y_:v_y_})



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

prediction = add_layers(x,784,10,activation_function=tf.nn.softmax)

cross_entropy = tf.reduce_mean(-tf.reduce_sum(y_*tf.log(prediction),
reduction_indices=[1]))

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

init = tf.initialize_all_variables()

sess = tf.Session()
sess.run(init)
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})

if i % 50 ==0:
print(get_accuracy(mnist.test.images,mnist.test.labels))


免責聲明!

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



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