標籤:轉化 required TE 切換 github https 指定 sed
MNIST資料集介紹
MNIST是一個入門級的電腦視覺資料集,它包含各種手寫數字圖片:
MNIST資料集是含標註資訊的,以片分別代表5, 0, 4和1。
MNIST資料集的官網是Yann LeCun‘s website
自動下載
首先貼出github地址:https://github.com/tensorflow/tensorflow/tree/master/tensorflow/examples/tutorials/mnist
建立一個input_data.py的檔案:
# Copyright 2015 The TensorFlow Authors. All Rights Reserved.## Licensed under the Apache License, Version 2.0 (the "License");# you may not use this file except in compliance with the License.# You may obtain a copy of the License at## http://www.apache.org/licenses/LICENSE-2.0## Unless required by applicable law or agreed to in writing, software# distributed under the License is distributed on an "AS IS" BASIS,# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.# See the License for the specific language governing permissions and# limitations under the License.# =============================================================================="""Functions for downloading and reading MNIST data."""from __future__ import absolute_importfrom __future__ import divisionfrom __future__ import print_functionimport gzipimport osimport tempfileimport numpyfrom six.moves import urllibfrom six.moves import xrange # pylint: disable=redefined-builtinimport tensorflow as tffrom tensorflow.contrib.learn.python.learn.datasets.mnist import read_data_sets
檔案 內容 train-images-idx3-ubyte.gz 訓練集圖片 - 55000 張 訓練圖片, 5000 張 驗證圖片 train-labels-idx1-ubyte.gz 訓練集圖片對應的數字標籤 t10k-images-idx3-ubyte.gz 測試集圖片 - 10000 張 圖片 t10k-labels-idx1-ubyte.gz 測試集圖片對應的數字標籤 載下來的資料集被分成兩部分:
60000行的訓練資料集和10000行的測試資料集。
把這個數組展開成一個向量,長度是 28x28 = 784。如何展開這個數組(數字間的順序)不重要,只要保持各個圖片採用相同的方式展開。
在MNIST訓練資料集中,mnist.train.images 是一個形狀為 [60000, 784] 的張量,
第一個維度資料表示圖片的索引,第二個維度資料表示圖片中像素的索引,值介於0和1之間。。
Softmax Regression模型
我們知道MNIST的每一張圖片都表示一個數字,從0到9。我們希望得到給定圖片代表每個數位機率。
比如說,我們的模型可能推測一張包含9的圖片代表數字9的機率是80%,但是判斷它是8的機率是15%(因為8和9都有上半部分的小圓),判斷它是6的機率是5%,然後給予它代表其他數位機率更小的值。
Softmax Regression是一個簡單的模型,很適合用來處理得到一個待分類對象在多個類別上的機率分布。所以,這個模型通常是很多進階模型的最後一步。
Softmax Regression大致分為兩步:
Step 1: add up the evidence of our input being in certain classes;Step 2: convert that evidence into probabilities.
為了得到一張給定圖片屬於某個特定數字類的證據(evidence),我們對圖片像素值進行加權求和。
如果這個像素具有很強的證據說明這張圖片不屬於該類,那麼相應的權值為負數,相反如果這個像素擁有有利的證據支援這張圖片屬於這個類,那麼權值是正數。
下面是一個直觀的例子,圖片中藍色表示正值,紅色表示負值(藍色地區的形狀趨向於數字形狀):
我們也需要加入一個額外的偏置量(bias),因為輸入往往會帶有一些無關的幹擾量。因此對於給定的輸入圖片 x 它代表的是數字 i 的證據可以表示為:
如果將這個過程公式化,將得到:
如們將這個過程公式化,將得到:
也可以簡化成:
看完之後,是不是覺得不明覺厲?開頭可能還能理解,但是後面搬出公式了,是不是覺得莫名其妙了?沒錯,就是要這種感覺,那繼續吧~
實現迴歸模型
為了在Python中進行科學計算工作,我們常常使用一些獨立庫函數包,例如NumPy來實現複雜的矩陣計算。但是由於Python的運行效率並不夠快,所以常常用一些更加高效的語言來實現。但是,這樣做會帶來語言轉換(例如轉換回python操作)的開銷。
TensorFlow在這方面做了一些最佳化,可以對你所描述的一系列的互動計算的流程完全獨立於Python之外,從而避免了語言切換的開銷。
為了使用TensorFlow,我們需要引用該庫函數:
import tensorflow as tf
利用一些符號變數來描述互動計算的過程,建立如下:
x = tf.placeholder(tf.float32, [None, 784])
說明下,placeholder函數可以理解為形參,用於定義過程,在執行的時候再賦具體的值;
這裡的 x 不是一個特定的值,而是一個預留位置,即需要時指定。
我們在TensorFlow運行計算時輸入這個值。我們希望能夠輸入任意數量的MNIST映像,每一張圖展平成784維的向量。我們用2維的浮點數張量來表示這些圖,這個張量的形狀是[None,784(28*28) ]。(這裡的None表示此張量的第一個維度可以是任何長度的。)
使用Variable(變數)來表示模型中的權值和偏置,這些參數是可變的。如下:
W = tf.Variable(tf.zeros([784, 10]))b = tf.Variable(tf.zeros([10]))
說明下,zeros是建立一個所有的參數為0的tensor對象;
這裡的W和b均被初始化為0值矩陣。W的維數為784 * 10,是因為我們需要將一個784維的像素值經過相應的權值之乘轉化為10個類別上的evidence值;b是十個類別上累加的偏置值。
現在,實現softmax regression模型僅需要一行代碼:
y = tf.nn.softmax(tf.matmul(x,W) + b)
其中,matmul函數實現了 x 和 W 的乘積,這裡 x 為二維矩陣,所以放在前面。可以看出,在TensorFlow中實現softmax regression模型是很簡單的。
首先,用 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)
在這裡,使用了一個學習率為0.01的梯度下降演算法來最小化代價函數。梯度下降是一個簡單的計算方式,即使得變數值朝著減小代價函數值的方向變化。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個隨機資料,這種操作成為批處理(batch)。
然後,每次運行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))
correct_prediction是一個布爾值的列表,例如 [True, False, True, True]。
可以使用tf.cast()函數將其轉換為[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}))
Softmax regression模型由於模型較簡單,所以在測試集上的準確率在91%左右,這個結果並不算太好。
通過一些簡單的最佳化,準確率可以達到97%,目前最好的模型的準確率為99.7%。(這裡有眾多模型在MNIST資料集上的運行結果)。
源碼
利用Softmax模型實現手寫體識別的完整代碼如下:
完善了代碼的注釋,以便閱讀起來更好理解,同時增加輸出訓練過程:
import input_dataimport tensorflow as tffrom tensorflow.examples.tutorials.mnist import input_datamnist = input_data.read_data_sets("data/", one_hot=True)print("Download Done!")# 設定權重weights和偏置biases作為最佳化變數,初始值設為0weights = tf.Variable(tf.zeros([784, 10]))biases = tf.Variable(tf.zeros([10]))# 構建模型x = tf.placeholder("float", [None, 784])# 模型的預測值y = tf.nn.softmax(tf.matmul(x, weights) + biases) # 真實值y_real = tf.placeholder("float", [None, 10]) # 預測值與真實值的交叉熵cross_entropy = -tf.reduce_sum(y_real * tf.log(y)) # 使用梯度下降最佳化器最小化交叉熵train_step = tf.train.GradientDescentOptimizer(0.01).minimize(cross_entropy) # 比較預測值和真實值是否一致correct_prediction = tf.equal(tf.argmax(y, 1), tf.arg_max(y_real, 1)) # 統計預測正確的個數,取均值得到準確率accuracy = tf.reduce_mean(tf.cast(correct_prediction, "float")) # 開始訓練init = tf.initialize_all_variables()sess = tf.Session()sess.run(init)for i in range(5000): # 每次隨機選取100個資料進行訓練,即所謂的隨機梯度下降 batch_xs, batch_ys = mnist.train.next_batch(100) # 正式執行train_step,用feed_dict的資料取代placeholder sess.run(train_step, feed_dict={x: batch_xs, y_real:batch_ys}) if i % 100 == 0: # 每訓練100次後評估模型 print("Step " + str(i) +",Training Accuracy "+ str(sess.run(accuracy, feed_dict={x: mnist.test.images, y_real: mnist.test.labels})))print("Accuarcy on Test-dataset: ", sess.run(accuracy, feed_dict={x: mnist.test.images, y_real: mnist.test.labels}))
最後執行的結果:
多次執行,會發現每次都不一樣,但基本都是在91%
如果把訓練次數增加到10W次,會發現成功率在98%
訓練過程:
嗯,TensorFlow的hello world就是這樣,花了不少時間介紹Softmax模型,尤其是公式那塊看的不懂,但感覺,數學在機器學習裡面真的很重要~小結:
本文使用Softmax Regression模型對MNIST資料集進行訓練,主要圍繞Softmax模型的原理(看不懂篇)以及怎麼在TensorFlow裡面使用這個模型,更重要的事,從這個模型學習到的設計思想~
進群:125240963 即可擷取十套PDF!
通過Python來學習人工智慧!事半功倍!TensorFlow之入門篇!