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 能夠當作是一個激勵(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 數據集來簡單體驗了一下真實數據的訓練和預測過程,可是準確率還不夠高,後面咱們會學習用卷積的方式來進行模型訓練,準確率會更高。