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函數的推廣。具體形式如下:
表示第i類模型預測的概率(總共有K類), 表示上一層的輸出,可以是任意實數。Softmax的好處在於可以把每個類歸一化到[0, 1]之間,且所有類的概率之和爲1,這樣我們可以從中選擇最大概率的 ,來表示模型的輸出類別。
關於Softmax的推導可以參看這裏。符號不是很嚴格,但基本能看明白。
咱們繼續
我們第一層採用Logistic Regression,一張圖片總共有(28 x 28)784個特徵,每個特徵與一個參數相乘,代表這個特徵在此類別上的貢獻,可以參看上圖。
所以有
定義輸入向量和會話
首先載入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)
定義損失函數
採用交叉信息熵,公式如下:
其中 表示真實值, 表示預測的概率。
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。
- 迭代地對數據進行訓練。
- 在測試集或驗證集上對準確率進行評測。