【TensorFlow官方文档】MNIST机器学习入门
MNIST是一個(gè)入門級(jí)的計(jì)算機(jī)視覺數(shù)據(jù)集,它包含各種手寫數(shù)字圖片;它也包含每一張圖片對(duì)應(yīng)的標(biāo)簽,告訴我們這個(gè)是數(shù)字幾。比如,下面這四張圖片的標(biāo)簽分別是5,0,4,1。
從一個(gè)很簡(jiǎn)單的數(shù)學(xué)模型開始:訓(xùn)練一個(gè)機(jī)器學(xué)習(xí)模型用于預(yù)測(cè)圖片里面的數(shù)字,它叫做Softmax Regression。
- Softmax回歸介紹
我們知道MNIST的每一張圖片都表示一個(gè)數(shù)字,從0到9。我們希望得到給定圖片代表每個(gè)數(shù)字的概率。比如說,我們的模型可能推測(cè)一張包含9的圖片代表數(shù)字9的概率是80%但是判斷它是8的概率是5%(因?yàn)?和9都有上半部分的小圓),然后給予它代表其他數(shù)字的概率更小的值。
softmax模型可以用來給不同的對(duì)象分配概率。softmax回歸(softmax regression)分兩步:
第一步,為了得到一張給定圖片屬于某個(gè)特定數(shù)字類的證據(jù)(evidence),我們對(duì)圖片像素值進(jìn)行加權(quán)求和。如果這個(gè)像素具有很強(qiáng)的證據(jù)說明這張圖片不屬于該類,那么相應(yīng)的權(quán)值為負(fù)數(shù),相反如果這個(gè)像素?fù)碛杏欣淖C據(jù)支持這張圖片屬于這個(gè)類,那么權(quán)值是正數(shù)。下面的圖片顯示了一個(gè)模型學(xué)習(xí)到的圖片上每個(gè)像素對(duì)于特定數(shù)字類的權(quán)值。紅色代表負(fù)數(shù)權(quán)值,藍(lán)色代表正數(shù)權(quán)值。
我們也需要加入一個(gè)額外的偏置量(bias),因?yàn)檩斎胪鶗?huì)帶有一些無關(guān)的干擾量。因此對(duì)于給定的輸入圖片x 它代表的是數(shù)字 i 的證據(jù)可以表示為
其中bi代表數(shù)字 i 類的偏置量,j代表給定圖片 x 的像素索引用于像素求和。然后用softmax函數(shù)可以把這些證據(jù)轉(zhuǎn)換成概率 y :
這里的softmax可以看成是一個(gè)激勵(lì)(activation)函數(shù)或者鏈接(link)函數(shù),把我們定義的線性函數(shù)的輸出轉(zhuǎn)換成我們想要的格式,也就是關(guān)于10個(gè)數(shù)字類的概率分布。因此,給定一張圖片,它對(duì)于每一個(gè)數(shù)字的吻合度可以被softmax函數(shù)轉(zhuǎn)換成為一個(gè)概率值。softmax函數(shù)可以定義為:
展開等式右邊的子式,可以得到:
對(duì)于softmax回歸模型可以用下面的圖解釋,對(duì)于輸入的 xs 加權(quán)求和,再分別加上一個(gè)偏置量,最后再輸入到softmax函數(shù)中:
把它寫成一個(gè)等式:
- 導(dǎo)入MNIST數(shù)據(jù)集
上面代碼是官方文檔里的,但你發(fā)現(xiàn)運(yùn)行會(huì)出錯(cuò),改為下面這個(gè)代碼:
from tensorflow.examples.tutorials.mnist import input_data mnist = input_data.read_data_sets("MNIST_data/",one_hot=True)下載下來的數(shù)據(jù)集被分成兩部分:60000行的訓(xùn)練數(shù)據(jù)集( mnist.train )和10000行的測(cè)試數(shù)據(jù)集( mnist.test )。每一個(gè)MNIST數(shù)據(jù)單元有兩部分組成:一張包含手寫數(shù)字的圖片和一個(gè)對(duì)應(yīng)的標(biāo)簽。我們把這些圖片設(shè)為“xs”,把這些標(biāo)簽設(shè)為“ys”。訓(xùn)練數(shù)據(jù)集和測(cè)試數(shù)據(jù)集都包含xs和ys,比如訓(xùn)練數(shù)據(jù)集的圖片是 mnist.train.images ,訓(xùn)練數(shù)據(jù)集的標(biāo)簽是 mnist.train.labels 。
每一張圖片包含28X28個(gè)像素點(diǎn)。我們可以用一個(gè)數(shù)字?jǐn)?shù)組來表示這張圖片(把這個(gè)數(shù)組展開成一個(gè)向量,長(zhǎng)度是 28x28 = 784):
因此,在MNIST訓(xùn)練數(shù)據(jù)集中,mnist.train.images 是一個(gè)形狀為 [60000, 784] 的張量,第一個(gè)維度數(shù)字用來索引圖片,第二個(gè)維度數(shù)字用來索引每張圖片中的像素點(diǎn)。
相對(duì)應(yīng)的MNIST數(shù)據(jù)集的標(biāo)簽是介于0到9的數(shù)字,用來描述給定圖片里表示的數(shù)字。這里標(biāo)簽數(shù)據(jù)是"one-hot vectors"。 一個(gè)one-hot向量除了某一位的數(shù)字是1以外其余各維度數(shù)字都是0。所以在此教程中,數(shù)字n將表示成一個(gè)只有在第n維度(從0開始)數(shù)字為1的10維向量。比如,標(biāo)簽0將表示成([1,0,0,0,0,0,0,0,0,0,0])。因此,mnist.train.labels 是一個(gè) [60000, 10] 的數(shù)字矩陣。
- 實(shí)現(xiàn)回歸模型
使用TensorFlow之前,首先導(dǎo)入它:
import tensorflow as tf我們通過操作符號(hào)變量來描述這些可交互的操作單元,可以用下面的方式創(chuàng)建一個(gè):
x = tf.placeholder("float", [None, 784])x 不是一個(gè)特定的值,而是一個(gè)占位符 placeholder ,我們?cè)赥ensorFlow運(yùn)行計(jì)算時(shí)輸入這個(gè)值。我們希望能夠輸入任意數(shù)量的MNIST圖像,每一張圖展平成784維的向量。我們用2維的浮點(diǎn)數(shù)張量來表示這些圖,這個(gè)張量的形狀是 [None,784 ] 。(這里的 None 表示此張量的第一個(gè)維度可以是任何長(zhǎng)度的。)
權(quán)重值和偏置量當(dāng)然可以把它們當(dāng)做是另外的輸入(使用占位符),但TensorFlow有一個(gè)更好的方法來表示它們:Variable 。 一個(gè) Variable 代表一個(gè)可修改的張量,存在在TensorFlow的用于描述交互性操作的圖中。它們可以用于計(jì)算輸入值,也可以在計(jì)算中被修改。對(duì)于各種機(jī)器學(xué)習(xí)應(yīng)用,一般都會(huì)有模型參數(shù),可以用 Variable 表示。在這里,我們都用全為零的張量來初始化 W 和b 。因?yàn)槲覀円獙W(xué)習(xí) W 和 b 的值,它們的初值可以隨意設(shè)置。
W = tf.Variable(tf.zeros([784,10])) b = tf.Variable(tf.zeros([10]))現(xiàn)在,我們可以實(shí)現(xiàn)我們的模型啦。只需要一行代碼!
y = tf.nn.softmax(tf.matmul(x,W) + b)- 訓(xùn)練模型
為了訓(xùn)練我們的模型,我們首先需要定義一個(gè)指標(biāo)來評(píng)估這個(gè)模型是好的。其實(shí)在機(jī)器學(xué)習(xí),我們通常定義指標(biāo)來表示一個(gè)模型是壞的,這個(gè)指標(biāo)稱為成本(cost)或損失(loss),然后盡量最小化這個(gè)指標(biāo)。但是,這兩種方式是相同的。一個(gè)非常常見的,非常漂亮的成本函數(shù)是“交叉熵”(cross-entropy)。
y 是我們預(yù)測(cè)的概率分布, y' 是實(shí)際的分布(我們輸入的one-hot vector)。比較粗糙的理解是,交叉熵是用來衡量我們的預(yù)測(cè)用于描述真相的低效性。
為了計(jì)算交叉熵,我們首先需要添加一個(gè)新的占位符用于輸入正確值:
y_ = tf.placeholder("float", [None,10])計(jì)算交叉熵:
cross_entropy = -tf.reduce_sum(y_*tf.log(y))首先,用 tf.log 計(jì)算 y 的每個(gè)元素的對(duì)數(shù)。接下來,我們把 y_ 的每一個(gè)元素和 tf.log(y) 的對(duì)應(yīng)元素相乘。最后,用 tf.reduce_sum 計(jì)算張量的所有元素的總和。(注意,這里的交叉熵不僅僅用來衡量單一的一對(duì)預(yù)測(cè)和真實(shí)值,而是所有100幅圖片的交叉熵的總和。對(duì)于100個(gè)數(shù)據(jù)點(diǎn)的預(yù)測(cè)表現(xiàn)比單一數(shù)據(jù)點(diǎn)的表現(xiàn)能更好地描述我們的模型的性能。
現(xiàn)在我們知道我們需要我們的模型做什么啦,用TensorFlow來訓(xùn)練它是非常容易的。因?yàn)門ensorFlow擁有一張描述你各個(gè)計(jì)算單元的圖,它可以自動(dòng)地使用反向傳播算法(backpropagation algorithm)來有效地確定你的變量是如何影響你想要最小化的那個(gè)成本值的。然后TensorFlow會(huì)用你選擇的優(yōu)化算法來不斷地修改變量以降低成本。
train_step = tf.train.GradientDescentOptimizer(0.01).minimize(cross_entropy)在這里,我們要求TensorFlow用梯度下降算法(gradient descent algorithm)以0.01的學(xué)習(xí)速率最小化交叉熵。梯度下降算法(gradient descent algorithm)是一個(gè)簡(jiǎn)單的學(xué)習(xí)過程,TensorFlow只需將每個(gè)變量一點(diǎn)點(diǎn)地往使成本不斷降低的方向移動(dòng)。當(dāng)然TensorFlow也提供了其他許多優(yōu)化算法:只要簡(jiǎn)單地調(diào)整一行代碼就可以使用其他的算法。
在運(yùn)行計(jì)算之前,我們需要添加一個(gè)操作來初始化我們創(chuàng)建的變量:
init = tf.initialize_all_variables()現(xiàn)在我們可以在一個(gè) Session 里面啟動(dòng)我們的模型,并且初始化變量:
sess = tf.Session() sess.run(init)然后開始訓(xùn)練模型,這里我們讓模型循環(huán)訓(xùn)練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})該循環(huán)的每個(gè)步驟中,我們都會(huì)隨機(jī)抓取訓(xùn)練數(shù)據(jù)中的100個(gè)批處理數(shù)據(jù)點(diǎn),然后我們用這些數(shù)據(jù)點(diǎn)作為參數(shù)替換之前的占位符來運(yùn)行 train_step 。
使用一小部分的隨機(jī)數(shù)據(jù)來進(jìn)行訓(xùn)練被稱為隨機(jī)訓(xùn)練(stochastic training)- 在這里更確切的說是隨機(jī)梯度下降訓(xùn)練。在理想情況下,我們希望用我們所有的數(shù)據(jù)來進(jìn)行每一步的訓(xùn)練,因?yàn)檫@能給我們更好的訓(xùn)練結(jié)果,但顯然這需要很大的計(jì)算開銷。所以,每一次訓(xùn)練我們可以使用不同的數(shù)據(jù)子集,這樣做既可以減少計(jì)算開銷,又可以最大化地學(xué)習(xí)到數(shù)據(jù)集的總體特性。
- 評(píng)估模型
首先讓我們找出那些預(yù)測(cè)正確的標(biāo)簽。 tf.argmax 是一個(gè)非常有用的函數(shù),它能給出某個(gè)tensor對(duì)象在某一維上的其數(shù)據(jù)最大值所在的索引值。由于標(biāo)簽向量是由0,1組成,因此最大值1所在的索引位置就是類別標(biāo)簽,比如 tf.argmax(y,1) 返回的是模型對(duì)于任一輸入x預(yù)測(cè)到的標(biāo)簽值,而 tf.argmax(y_,1) 代表正確的標(biāo)簽,我們可以用 tf.equal 來檢測(cè)我們的預(yù)測(cè)是否真實(shí)標(biāo)簽匹配(索引位置一樣表示匹配)。
correct_prediction = tf.equal(tf.argmax(y,1), tf.argmax(y_,1))這行代碼會(huì)給我們一組布爾值。為了確定正確預(yù)測(cè)項(xiàng)的比例,我們可以把布爾值轉(zhuǎn)換成浮點(diǎn)數(shù),然后取平均值。例如[True, False, True, True] 會(huì)變成 [1,0,1,1] ,取平均值后得到 0.75 .
accuracy = tf.reduce_mean(tf.cast(correct_prediction, "float"))最后,我們計(jì)算所學(xué)習(xí)到的模型在測(cè)試數(shù)據(jù)集上面的正確率。
print sess.run(accuracy, feed_dict={x: mnist.test.images, y_: mnist.test.labels})這個(gè)最終結(jié)果值應(yīng)該大約是91%。
- 完整運(yùn)行代碼
from tensorflow.examples.tutorials.mnist import input_data
mnist = input_data.read_data_sets('G:\MNIST DATABASE\MNIST_data',one_hot=True)
def add_layers(inputdata,inputsize,outputsize,activation_function=None):
Weights = tf.Variable(tf.random_normal([inputsize,outputsize]))
biases = tf.Variable(tf.zeros([1,outputsize]) + 0.1)
Weights_biases_add = tf.matmul(inputdata,Weights) + biases
if activation_function is None:
outputs = Weights_biases_add
else:
outputs = activation_function(Weights_biases_add)
return outputs
def get_accuracy(v_x,v_y_):
global prediction
y_pre = sess.run(prediction,feed_dict={x:v_x})
correct_prediction = tf.equal(tf.argmax(y_pre,1),tf.argmax(v_y_,1))
accuracy = tf.reduce_mean(tf.cast(correct_prediction,tf.float32))
return sess.run(accuracy,feed_dict={x:v_x,y_:v_y_})
x = tf.placeholder(tf.float32,[None,784])
y_ = tf.placeholder(tf.float32,[None,10])
prediction = add_layers(x,784,10,activation_function=tf.nn.softmax)
cross_entropy = tf.reduce_mean(-tf.reduce_sum(y_*tf.log(prediction),
reduction_indices=[1]))
train_step = tf.train.GradientDescentOptimizer(0.5).minimize(cross_entropy)
init = tf.initialize_all_variables()
sess = tf.Session()
sess.run(init)
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})
if i % 50 ==0:
print(get_accuracy(mnist.test.images,mnist.test.labels))
轉(zhuǎn)載于:https://www.cnblogs.com/qqw-1995/p/9737122.html
總結(jié)
以上是生活随笔為你收集整理的【TensorFlow官方文档】MNIST机器学习入门的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 第25月第2天 Django-By-Ex
- 下一篇: 邻接矩阵无向图