TensorFlow MNIST初級學習

MNIST

MNIST 是一個入門級計算機視覺數據集,包含了不少手寫數字圖片,如圖所示:python

數據集中包含了圖片和對應的標註,在 TensorFlow 中提供了這個數據集,咱們能夠用以下方法進行導入:算法

from tensorflow.examples.tutorials.mnist import input_data
mnist = input_data.read_data_sets('MNIST_data/', one_hot=True)
print(mnist)

輸出結果以下:網絡

Extracting MNIST_data/train-images-idx3-ubyte.gz

Extracting MNIST_data/train-labels-idx1-ubyte.gz

Extracting MNIST_data/t10k-images-idx3-ubyte.gz

Extracting MNIST_data/t10k-labels-idx1-ubyte.gz

Datasets(train=<tensorflow.contrib.learn.python.learn.datasets.mnist.DataSet object at 0x101707ef0>, validation=<tensorflow.contrib.learn.python.learn.datasets.mnist.DataSet object at 0x1016ae4a8>, test=<tensorflow.contrib.learn.python.learn.datasets.mnist.DataSet object at 0x1016f9358>)

在這裏程序會首先下載 MNIST 數據集,而後解壓並保存到剛剛制定好的 MNIST_data 文件夾中,而後輸出數據集對象。機器學習

數據集中包含了 55000 行的訓練數據集(mnist.train)、5000 行驗證集(mnist.validation)和 10000 行的測試數據集(mnist.test),文件以下所示:函數

正如前面提到的同樣,每個 MNIST 數據單元有兩部分組成:一張包含手寫數字的圖片和一個對應的標籤。咱們把這些圖片設爲 xs,把這些標籤設爲 ys。訓練數據集和測試數據集都包含 xs 和 ys,好比訓練數據集的圖片是 mnist.train.images ,訓練數據集的標籤是 mnist.train.labels,每張圖片是 28 x 28 像素,即 784 個像素點,咱們能夠把它展開造成一個向量,即長度爲 784 的向量。性能

因此訓練集咱們能夠轉化爲 [55000, 784] 的向量,第一維就是訓練集中包含的圖片個數,第二維是圖片的像素點表示的向量。學習

Softmax

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

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

好比判斷一張圖片中的動物是什麼,可能的結果有三種,貓、狗、雞,假如咱們能夠通過計算得出它們分別的得分爲 3.二、5.一、-1.7,Softmax 的過程首先會對各個值進行次冪計算,分別爲 24.五、164.0、0.18,而後計算各個次冪結果佔總次冪結果的比重,這樣就能夠獲得 0.1三、0.8七、0.00 這三個數值,因此這樣咱們就能夠實現差異的放縮,即好的更好、差的更差。編碼

若是要進一步求損失值能夠進一步求對數而後取負值,這樣 Softmax 後的值若是值越接近 1,那麼獲得的值越小,即損失越小,若是越遠離 1,那麼獲得的值越大。

實現迴歸模型

首先導入 TensorFlow,命令以下:

import tensorflow as tf

接下來咱們指定一個輸入,在這裏輸入即爲樣本數據,若是是訓練集那麼則是 55000 x 784 的矩陣,若是是驗證集則爲 5000 x 784 的矩陣,若是是測試集則是 10000 x 784 的矩陣,因此它的行數是不肯定的,可是列數是肯定的。

因此能夠先聲明一個 placeholder 對象:

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

這裏第一個參數指定了矩陣中每一個數據的類型,第二個參數指定了數據的維度。

接下來咱們須要構建第一層網絡,表達式以下:

這裏其實是對輸入的 x 乘以 w 權重,而後加上一個偏置項做爲輸出,而這兩個變量實際是在訓練的過程當中動態調優的,因此咱們須要指定它們的類型爲 Variable,代碼以下:

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

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

接下來須要實現的就是上圖所述的公式了,咱們再進一步調用 Softmax 進行計算,獲得 y:

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

經過上面幾行代碼咱們就已經把模型構建完畢了,結構很是簡單。

損失函數

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

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

y 是咱們預測的機率分佈, y_label 是實際的分佈,比較粗糙的理解是,交叉熵是用來衡量咱們的預測用於描述真相的低效性。

咱們能夠首先定義 y_label,它的表達式是:

y_label = tf.placeholder(tf.float32, [None, 10])

接下來咱們須要計算它們的交叉熵,代碼以下:

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

首先用 reduce_sum() 方法針對每個維度進行求和,reduction_indices 是指定沿哪些維度進行求和。

而後調用 reduce_mean() 則求平均值,將一個向量中的全部元素求算平均值。

這樣咱們最後只須要優化這個交叉熵就行了。

因此這樣咱們再定義一個優化方法:

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

這裏使用了 GradientDescentOptimizer,在這裏,咱們要求 TensorFlow 用梯度降低算法(gradient descent algorithm)以 0.5 的學習速率最小化交叉熵。梯度降低算法(gradient descent algorithm)是一個簡單的學習過程,TensorFlow 只需將每一個變量一點點地往使成本不斷下降的方向移動便可。

運行模型

定義好了以上內容以後,至關於咱們已經構建好了一個計算圖,即設置好了模型,咱們把它放到 Session 裏面運行便可:

with tf.Session() as sess:

    sess.run(tf.global_variables_initializer())

    for step in range(total_steps + 1):

        batch_x, batch_y = mnist.train.next_batch(batch_size)

        sess.run(train, feed_dict={x: batch_x, y_label: batch_y})

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

這裏須要一些變量的定義:

batch_size = 100

total_steps = 5000

測試模型

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

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

correct_prediction = tf.equal(tf.argmax(y, axis=1), tf.argmax(y_label, axis=1))

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

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

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

steps_per_test = 100

if step % steps_per_test == 0:

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

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

這樣咱們就經過完成了訓練和測試階段,實現了一個基本的訓練模型,後面咱們會繼續優化模型來達到更好的效果。

運行結果以下:

0 0.453

100 0.8915

200 0.9026

300 0.9081

400 0.9109

500 0.9108

600 0.9175

700 0.9137

800 0.9158

900 0.9176

1000 0.9167

1100 0.9186

1200 0.9206

1300 0.9161

1400 0.9218

1500 0.9179

1600 0.916

1700 0.9196

1800 0.9222

1900 0.921

2000 0.9223

2100 0.9214

2200 0.9191

2300 0.9228

2400 0.9228

2500 0.9218

2600 0.9197

2700 0.9225

2800 0.9238

2900 0.9219

3000 0.9224

3100 0.9184

3200 0.9253

3300 0.9216

3400 0.9218

3500 0.9212

3600 0.9225

3700 0.9224

3800 0.9225

3900 0.9226

4000 0.9201

4100 0.9138

4200 0.9184

4300 0.9222

4400 0.92

4500 0.924

4600 0.9234

4700 0.9219

4800 0.923

4900 0.9254

5000 0.9218

結語

本節經過一個 MNIST 數據集來簡單體驗了一下真實數據的訓練和預測過程,可是準確率還不夠高,後面咱們會學習用卷積的方式來進行模型訓練,準確率會更高。

相關文章
相關標籤/搜索