TensorFlow 入門(二):Softmax 識別手寫數字

TensorFlow 入門(二):Softmax 識別手寫數字

@author: demonSong
@email: [email protected]

refer to: http://www.tensorfly.cn/tfdoc/tutorials/mnist_beginners.html

MNIST是一個非常簡單的機器視覺數據集,如下圖所示,它由幾萬張28像素x28像素的手寫數字組成,這些圖片只包含灰度值信息。我們的任務就是對這些手寫數字的圖片進行分類,轉成0~9一共十類。

這裏寫圖片描述

基本步驟

引包俠

from tensorflow.examples.tutorials.mnist import input_data

加載數據

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

注意:若提示你的主機中的軟件中止了一個已建立的連接,請關閉殺毒軟件,以防誤報。

你也可以直接從這裏下載數據集,並在根目錄下建立MNIST_data文件夾。再運行上述代碼即可。

數據集探查

print(mnist.train.images.shape, mnist.train.labels.shape)
print(mnist.test.images.shape, mnist.test.labels.shape)
print(mnist.validation.images.shape, mnist.validation.labels.shape)

# 輸出
(55000, 784) (55000, 10)
(10000, 784) (10000, 10)
(5000, 784) (5000, 10)

可以看到訓練集有55000個樣本,測試集有10000個樣本,同時驗證集有5000個樣本。每一個樣本都有對應的標註信息,即label。我們將在訓練集上訓練模型,在驗證集上檢驗效果並決定何時完成訓練,最後我們在測試集評測模型的效果(可通過準確率,召回率,F1-score等評測。)

每一張圖片包含28像素X28像素。我們可以用一個數字數組來表示這張圖片:

這裏寫圖片描述

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

這裏手寫數字識別爲多分類問題,因此我們採用Softmax Regression模型來處理。關於Softmax,可以參看這裏。你也可以認爲它是二分類問題Sigmoid函數的推廣。具體形式如下:

yi=ezij=1Kezj

表示第i類模型預測的概率(總共有K類),zj 表示上一層的輸出,可以是任意實數。Softmax的好處在於可以把每個類歸一化到[0, 1]之間,且所有類的概率之和爲1,這樣我們可以從中選擇最大概率的j ,來表示模型的輸出類別。

關於Softmax的推導可以參看這裏。符號不是很嚴格,但基本能看明白。

咱們繼續

這裏寫圖片描述

我們第一層採用Logistic Regression,一張圖片總共有(28 x 28)784個特徵,每個特徵與一個參數相乘,代表這個特徵在此類別上的貢獻,可以參看上圖。

所以有

zj=i=1784wjixi+bj

定義輸入向量和會話
首先載入TensorFlow庫,並創建一個新的InteractiveSession,使用這個命令將這個session註冊爲默認的session,之後的運算也默認跑在這個session裏,不同session之間的數據和運算應該都是相互獨立的。接下來創建一個Placeholder,即輸入數據的地方。Placeholder的第一個參數是數據類型,第二個參數[None, 784]代表tensor的shape,也就是數據的尺寸,這裏None代表不限條數的輸入,784代表每條輸入是一個784維的向量。

import tensorflow as tf
sess = tf.InteractiveSession()
x = tf.placeholder(tf.float32, [None, 784])

創建變量
定義Sotfmax Regression模型中的weights和biases對象,注意這裏的變量是全局性質的,所以使用TensorFlow中的Variable對象。

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

實現Sotfmax Regression算法

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

定義損失函數
採用交叉信息熵,公式如下:

Loss=iyilog(yi)

其中yi 表示真實值,yi 表示預測的概率。
y_ = tf.placeholder(tf.float32, [None, 10])
loss = tf.reduce_mean(-tf.reduce_sum(y_ * tf.log(y), reduction_indices = [1]))

先定義一個placeholder,輸入真實的label,用來計算cross entropy。tf.reduce_sum也就是求和的 , 而tf.reduce_mean則用來對每個batch數據結果求平均。

定義優化算法
類似與梯度下降算法,此處我們採用隨機梯度下降SGD,能夠更快的收斂,且容易跳出局部最優解。

# 學習速率爲0.5
train_step = tf.train.GradientDescentOptimizer(0.5).minimize(loss)

運行

tf.global_variables_initializer().run()

一切準備就緒,喂數據

for i in range(1000):
    batch_xs, batch_ys = mnist.train.next_batch(100)
    train_step.run({x : batch_xs, y_ : batch_ys})

模型驗證

correct_prediction = tf.equal(tf.argmax(y, 1), tf.argmax(y_, 1))
accuracy = tf.reduce_mean(tf.cast(correct_prediction, tf.float32))
print(accuracy.eval({x : mnist.test.images, y_ : mnist.test.labels}))

# 輸出
0.922

注意:前兩行都只是定義,還未真正的執行,最後eval纔是執行的代碼。0.922的準確率,對於只有一層的Logistic Regression多分類已經不錯了。

總結

  • 定義算法公式,也就是神經網絡forward時的計算。
  • 定義loss,選定優化器,並指定優化器優化loss。
  • 迭代地對數據進行訓練。
  • 在測試集或驗證集上對準確率進行評測。
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章