我是一個(gè)很懶的人髓帽,我想試試
希望我能堅(jiān)持到最后被碗,把tensorflow的官方教程全部翻譯出來
提高自己甚侣,也幫助他人
我的博客:終身學(xué)習(xí)者
MNIST For ML Beginners
本教程面向剛開始學(xué)習(xí)機(jī)器學(xué)習(xí)和 TensorFlow 的讀者创千。如果你已經(jīng)知道 MNIST 是什么,以及softmax(多項(xiàng)邏輯)回歸是什么皆串,那么你可能更適合這個(gè)快速上手教程淹办。請(qǐng)?jiān)陂_始任何教程之前安裝好 TensorFlow。
當(dāng)一個(gè)人開始學(xué)習(xí)編程的時(shí)候恶复,一般來說第一件事就是打印"Hello World"怜森。正如編程有 Hello World齐遵,機(jī)器學(xué)習(xí)有 MNIST 。
MNIST 是一個(gè)簡單的機(jī)器視覺數(shù)據(jù)庫塔插。它是由類似下列的各種手寫數(shù)字圖像組成:
每張圖像同時(shí)也包含了標(biāo)簽,告訴我們這個(gè)數(shù)字是多少拓哟。比如想许,上面的圖像的標(biāo)簽分別是5,0断序,4流纹,1。
在這個(gè)教程里面违诗,我們將要訓(xùn)練一個(gè)模型用來查看圖像并預(yù)測出上面的數(shù)字是多少漱凝。我們的目標(biāo)不是訓(xùn)練一個(gè)真實(shí)精確,有著最高性能诸迟,盡管我們接下來將提供你代碼來實(shí)現(xiàn)這個(gè)茸炒,而是簡單使用 TensorFlow 。因此阵苇,我們將從一個(gè)非常簡單的稱為 Softmax Regression 模型開始壁公。
本教程的實(shí)現(xiàn)代碼非常的短,而且真正有意思的內(nèi)容只發(fā)生在短短的三行中绅项。然而紊册,去理解代碼后面的理念是非常重要的:TensorFlow 的工作原理和機(jī)器學(xué)習(xí)概念的核心。正因?yàn)槿绱丝旃ⅲ覀儗⑼ㄟ^這些代碼小心的講解這些囊陡。
About this tutorial
本教程將逐行解釋 mnist_softmax.py 代碼所做的事情。
你可以通過幾種不同的方式來學(xué)習(xí)本教程掀亥,其中包括:
- 通過你閱讀的每行代碼的解釋后撞反,復(fù)制并粘貼每個(gè)代碼片段到 Python 環(huán)境中。
- 在閱讀理解之前和之后運(yùn)行整個(gè)
mnist_softmax.py
文件铺浇,并使用本教程來理解你不清楚的代碼部分痢畜。
我們將在本教程中完成以下任務(wù):
- 學(xué)習(xí)關(guān)于 MNIST 數(shù)據(jù)集和 softmax regressions
- 根據(jù)查看圖像中的每個(gè)像素來創(chuàng)建一個(gè)識(shí)別數(shù)字的模型
- 使用 TensorFlow 來 “看” 上千個(gè)數(shù)字圖像例子來訓(xùn)練模型識(shí)別數(shù)字(并執(zhí)行我們第一個(gè) TensorFlow 會(huì)話來實(shí)現(xiàn))
- 通過我們的測試數(shù)據(jù)來檢測我們的模型的準(zhǔn)確度
The MNIST Data
MNIST 數(shù)據(jù)托管在 Yann LeCun 的網(wǎng)站上。如果你正在復(fù)制和粘貼本教程的代碼鳍侣,請(qǐng)先從這兩行代碼開始丁稀,它將自動(dòng)下載并讀取數(shù)據(jù):
from tensorflow.examples.tutorials.mnist import input_data
mnist = input_data.read_data_sets("MNIST_data/", one_hot=True)
MNIST 數(shù)據(jù)集分為三個(gè)部分:55000 訓(xùn)練數(shù)據(jù) (mnist.train
),10000 測試數(shù)據(jù) (mnist.test
)倚聚, 和 5000 驗(yàn)證數(shù)據(jù) (mnist.validation
)线衫。這種劃分是非常重要的:我們?cè)谶€沒有學(xué)習(xí)任何東西之前劃分?jǐn)?shù)據(jù),這對(duì)于機(jī)器學(xué)習(xí)來說是非常有必要的惑折。這樣我們就可以確認(rèn)我們的學(xué)習(xí)后的模型的實(shí)際泛化能力如何授账!
正如前面提到的枯跑,每個(gè) MNIST 數(shù)據(jù)是由兩部分組成的:一個(gè)手寫數(shù)字圖像和一個(gè)對(duì)應(yīng)的標(biāo)簽。我們成圖像為“x”白热,標(biāo)簽為“y”敛助。訓(xùn)練集和測試集都包含了圖像和對(duì)應(yīng)的標(biāo)簽;例如訓(xùn)練圖像是 mnist.train.images
而標(biāo)簽圖像是 mnist.train.labels
屋确。
每個(gè)圖像是28x28像素組成纳击。我們可以認(rèn)為這個(gè)一個(gè)很大的數(shù)字?jǐn)?shù)組:
我們可以將這個(gè)28x28的行列式變成一個(gè)784的數(shù)組。只要我們保證每個(gè)圖像采用相同的方式攻臀,那么我們并不在意如何把這個(gè)行列式展開焕数。從這個(gè)角度來看,MNIST 圖像集只是一個(gè)784維矢量空間的一束 具有復(fù)雜結(jié)構(gòu)的 點(diǎn)集而已(警告:可視化是計(jì)算密集型)刨啸。
展開這些數(shù)據(jù)將丟失圖像的2D結(jié)構(gòu)信息堡赔。這當(dāng)然是不好的。最好的機(jī)器視覺方法會(huì)利用這種結(jié)構(gòu)信息设联,我們將在之后的教程中講解這些善已。但是在這里我們使用的簡單模型,一個(gè) softmax regressions(下面將會(huì)定義) 并沒有使用這種信息离例。
結(jié)果是 mnist.train.images
是一個(gè)形狀為 [55000, 784]
的張量(一個(gè)N維數(shù)組)雕拼。第一維是圖像列表的一個(gè)索引,第二維是每個(gè)圖像的每個(gè)像素的索引粘招。張量中的每個(gè)條目是表示特定圖像的特定像素的像素強(qiáng)度值啥寇,值介于0和1之間。
MNIST中的每個(gè)圖像都有對(duì)應(yīng)的一個(gè)標(biāo)簽數(shù)字洒扎,標(biāo)簽數(shù)字是0到9辑甜,代表了圖像中畫的數(shù)字。
為了本教程的目的袍冷,我們將要我們的標(biāo)簽作為 "one-hot vectors"磷醋。一個(gè)one-hot 向量是一個(gè)只有其中一個(gè)維度是1,其他維是0的向量胡诗。在這種情況下邓线,向量上第n維的數(shù)字1表示第n的數(shù)字。例如3表示為[0,0,0,1,0,0,0,0,0,0]煌恢。所以 mnist.train.labels
是一個(gè)[55000, 10]
的數(shù)組骇陈。
現(xiàn)在我們準(zhǔn)備好實(shí)際構(gòu)造我們的模型了!
Softmax Regressions
我們知道 MNIST 里的每個(gè)圖像都是手寫數(shù)字0到9中的一個(gè)瑰抵。所以對(duì)于一張圖像來說只有十種可能性你雌。我們希望能夠查看每張圖并給出每張圖的每個(gè)數(shù)字的概率。例如二汛,對(duì)于我們的模型婿崭,在看一張手寫數(shù)字9的圖像拨拓,它能夠80%確定這是9,但是有5%的可能是8(因?yàn)樗麄兩习氩糠侄际且粋€(gè)圓)氓栈,所有其他數(shù)字的可能性加起來是另外的15%渣磷,因?yàn)榭偣哺怕适?00%。
這是 softmax regression 的一個(gè)簡單授瘦,自然的經(jīng)典模型幸海。softmax 可以幫助你給幾個(gè)不同的事物分別分配概率,因?yàn)?softmax 可以給我們一系列的0到1之間的值奥务,并且總和達(dá)到1。之后當(dāng)我們訓(xùn)練更復(fù)雜的模型的時(shí)候袜硫,最后一步也是要使用 softmax 層氯葬。
softmax regression 有兩個(gè)步驟:首先我們將我們輸入的證據(jù)(evidence) 加入到確定的類別中。然后我們計(jì)算對(duì)應(yīng)的證據(jù)的概率婉陷。
為了收集給定圖像在特定類別上的證據(jù)帚称,我們進(jìn)行了像素值的加權(quán)求和。如果圖像在某個(gè)類上有很高的像素強(qiáng)度的證據(jù)則權(quán)重為正秽澳,相反則為負(fù)闯睹。
下圖顯示了一個(gè)模型在學(xué)習(xí)每個(gè)類別的權(quán)重,紅色表示負(fù)權(quán)重担神,而藍(lán)色表示正權(quán)重楼吃。
我們也另外添加了一些被稱為偏差的證據(jù)⊥叮基本上孩锡,我們希望能夠有些東西獨(dú)立于輸入。結(jié)果對(duì)于給定輸入
![][03]
其中亥贸,$W_i$ 表示權(quán)重躬窜,$b_i$ 表示類$i$的偏置,$j$ 表示輸入圖像 $x$ 的所有像素的索引炕置。然后我們用 softmax 函數(shù)將這些證據(jù)計(jì)算出概率 $y$ :
$$
y = \text{softmax}(\text{evidence})
$$
這里的 softmax 被視為是一個(gè)激勵(lì)(activation)或者鏈接(link)函數(shù)荣挨,在這種情況下,將我們的線性函數(shù)的輸出塑造成我們想要的形式——一種10個(gè)數(shù)字分類的概率分布朴摊。你可以認(rèn)為是將我們的輸入的證據(jù)轉(zhuǎn)化為我們?cè)诿總€(gè)分類上的概率默垄,定義如下:
$$
\text{softmax}(evidence) = \text{normalize}(\exp(evidence))
$$
展開等式:
$$
\text{softmax}(evidence)_i = \frac{\exp(evidence_i)}{\sum_j \exp(evidence_j)}
$$
但是把 softmax 視為激勵(lì)是有利的:將輸入值指數(shù)化,然后正則化甚纲。指數(shù)意味著每多一個(gè)單位的證據(jù)增加了假設(shè)(hypothesis)中乘數(shù)的權(quán)重厕倍。反之,每少一個(gè)單位的證據(jù)意味著減少了假設(shè)中乘數(shù)的權(quán)重贩疙。假設(shè)是不會(huì)有零或者負(fù)權(quán)重的讹弯。然后 softmax 歸一化權(quán)重况既,使得總權(quán)重為一,形成一個(gè)有效的概率分布组民。(更多有關(guān)于softmax函數(shù)的信息請(qǐng)查閱 Michael Nielsen 書籍的有關(guān)部分棒仍,其中包含交互式可視化的內(nèi)容。)
你可以將 softmax 回歸看成如下圖所示臭胜,有很多的輸入 $x$莫其。對(duì)于每個(gè)輸出,我們計(jì)算 $x$ 的加權(quán)求和耸三,加上偏置乱陡,然后在應(yīng)用于 softmax 函數(shù)中。
寫成等式仪壮,如下:
我們可以將這個(gè)過程“矢量化”憨颠,轉(zhuǎn)化為矩陣乘法和向量加法。這有助于提高計(jì)算效率积锅。(也是一個(gè)更有用的思考方式爽彤。)
更簡潔的寫法如下:
$$
y = \text{softmax}(Wx + b)
$$
現(xiàn)在讓我們將其用 TensorFlow 表示。
Implementing the Regression
為了使用 Python 進(jìn)行高效的數(shù)值計(jì)算缚陷,我們通常使用諸如 NumPy這樣的的庫來做復(fù)雜的操作适篙,例如矩陣乘法,它使用另一種高效的語言來實(shí)現(xiàn)箫爷。不幸的是嚷节,每一次運(yùn)算的結(jié)果都會(huì)返回給 Python,這會(huì)帶來許多額外的開銷虎锚。如果你希望在GPU或者以分布式計(jì)算的方式來運(yùn)行的話丹喻,這其中的轉(zhuǎn)化數(shù)據(jù)的成本將非常高,帶來的開銷將更加糟糕翁都。
TensorFlow 也在 Python 之外進(jìn)行繁重的計(jì)算碍论,但是為了避免這種開銷,TensorFlow 做了更進(jìn)一步的完善柄慰。TensorFlow 不在 Python 單獨(dú)運(yùn)行一個(gè)昂貴的操作鳍悠,而是讓我們描述一整個(gè)交互操作的圖,然后再一起在 Python之外運(yùn)行坐搔。(這種類似的情況可以在其他的機(jī)器學(xué)習(xí)庫里看見藏研。)
為了使用TensorFlow,首先我們需要載入它概行。
import tensorflow as tf
我們通過操作符號(hào)變量來描述這些交互操作〈赖玻現(xiàn)在讓我們來創(chuàng)建一個(gè):
x = tf.placeholder(tf.float32, [None, 784])
x
不是一個(gè)特定的值。它是一個(gè)占位符(placeholder
),當(dāng)我們讓 TensorFlow 執(zhí)行計(jì)算的時(shí)候讓我們輸入這個(gè)值业踏。我們希望能夠輸入任意數(shù)量的 MNIST 圖像禽炬,將其展開為一個(gè)784維的矢量。我們用一個(gè)2維浮點(diǎn)數(shù)張量來表示這些圖勤家,其形如 [None, 784]
腹尖。(這里None
表示這個(gè)維度可以是任意長度的。)
對(duì)于我們的模型伐脖,我們一樣需要權(quán)重和偏置热幔。我們也可以設(shè)想把他們當(dāng)作額外的輸入,但是 TensorFlow 有一個(gè)更好的方式來處理它:Variable
讼庇。一個(gè) Variable
是一個(gè)可變的張量绎巨,存在于 TensorFlow 的可交互的圖中。它可以在計(jì)算中被使用和被修改蠕啄。對(duì)于機(jī)器學(xué)習(xí)應(yīng)用來說场勤,通常將模型參數(shù)設(shè)置為 Variable
。
W = tf.Variable(tf.zeros([784, 10]))
b = tf.Variable(tf.zeros([10]))
我們通過tf.Variable
給Variable
初始值來創(chuàng)建這些 Variable
:在這里介汹,我們用全為零的張量來初始化W
和b
。既然我們要學(xué)習(xí)W
and b
舶沛,那么他們被初始化成什么并不重要嘹承。
注意,W
形如[784, 10]如庭,因?yàn)槲覀兿M艘?84維的圖像矢量來產(chǎn)生一個(gè)10維的不同類的證據(jù)的向量叹卷。b
的形狀是[10],所以我們可以把它加在輸出上坪它。
現(xiàn)在我們可以實(shí)現(xiàn)我們的模型了骤竹。只需要一行代碼來定義它!
y = tf.nn.softmax(tf.matmul(x, W) + b)
首先往毡,我們通過tf.matmul(x, W)
來使W
乘以x
蒙揣。對(duì)應(yīng)方程中的 $Wx$ ,這里 $Wx$ 作為一個(gè)小技巧來處理多項(xiàng)輸入的2維張量x
开瞭。然后我們加上b
懒震,最后應(yīng)用tf.nn.softmax
。
至此嗤详,經(jīng)過兩行代碼設(shè)置變量后个扰,我們只使用了一行代碼來定義我們的模型。這不是因?yàn)?TensorFlow 是被設(shè)計(jì)為使用 softmax 回歸特別簡單:而這是一個(gè)非常靈活的方式來描述許多類型的數(shù)值計(jì)算葱色,從機(jī)器學(xué)習(xí)模型到物理模擬仿真都是如此递宅。而一旦定義后,我們的模型可以運(yùn)行在不同的設(shè)備中:你的電腦的CPU上,GPU上办龄,甚至是手機(jī)上烘绽!
Training
為了訓(xùn)練我們的模型,我們需要定義什么樣的模型是好的土榴。那么實(shí)際上诀姚,在機(jī)器學(xué)習(xí)中我們通常定義什么樣的模型是壞的。我們稱之為代價(jià)(cost)玷禽,或者是損失(loss)赫段,這代表著我們的模型與我們的期望的差距有多遠(yuǎn)。我們嘗試使這個(gè)誤差最小矢赁,因?yàn)檎`差越小糯笙,模型也就越好。
一個(gè)非常常見撩银,非常好的損失模型被稱為交叉熵("cross-entropy")给涕。交叉熵源于信息理論里的信息壓縮編碼思想,現(xiàn)在在很多領(lǐng)域中其演變?yōu)橐环N重要的思想额获,從博弈論到機(jī)器學(xué)習(xí)都是如此够庙,它被定義為:
$$
H_{y'}(y) = -\sum_i y'_i \log(y_i)
$$
其中$y$是我們的預(yù)測概率分布,$y'$是實(shí)際分布(數(shù)字標(biāo)簽的one-hot向量)抄邀。更粗糙的說話是耘眨,交叉熵是用于衡量我們的預(yù)測描述的實(shí)際的低效性。理解交叉熵更多的細(xì)節(jié)是超出本教程的范圍的境肾,但是它是值得理解的剔难。
為了實(shí)現(xiàn)交叉熵,我們首先增加一個(gè)占位符用來輸入正確的答案:
y_ = tf.placeholder(tf.float32, [None, 10])
然后我們可以實(shí)現(xiàn)交叉熵函數(shù)奥喻,$-\sum y'\log(y)$:
cross_entropy = tf.reduce_mean(-tf.reduce_sum(y_ * tf.log(y), reduction_indices=[1]))
首先偶宫, tf.log
計(jì)算了y
的每個(gè)元素的對(duì)數(shù)。然后我們將y_
與相對(duì)于的tf.log(y)
相乘环鲤。再然后由于reduction_indices=[1]
纯趋,tf.reduce_sum
將y的第二維元素求和。最后冷离,tf.reduce_mean
計(jì)算批處理中所有樣本的平均值结闸。
注意,在源代碼中酒朵,我們不適用這個(gè)公式桦锄,因?yàn)樗跀?shù)值上是不穩(wěn)定的。相反蔫耽,我們應(yīng)用tf.nn.softmax_cross_entropy_with_logits
在非歸一化的logits上( 例如结耀,我們?cè)?code>tf.matmul(x, W) + b中調(diào)用softmax_cross_entropy_with_logits
)留夜,因?yàn)樵趕oftmax激活中的數(shù)值計(jì)算是更穩(wěn)定的。在你的代碼中图甜,請(qǐng)考慮使用tf.nn.softmax_cross_entropy_with_logits
替代碍粥。
現(xiàn)在我們知道我們想要我們的模型做什么了,對(duì)于 TensorFlow 來說訓(xùn)練它來做這些是非常簡單的黑毅。因?yàn)?TensorFlow 知道你所有計(jì)算的圖嚼摩,它可以自動(dòng)使用反向傳播算法來有效的確定你的變量如何影響你要求最小化的損失。而且它可以應(yīng)用你選擇的優(yōu)化算法來修改變量并減小損失矿瘦。
train_step = tf.train.GradientDescentOptimizer(0.5).minimize(cross_entropy)
在這種情況下枕面,我們讓 TensorFlow 使用學(xué)習(xí)率為0.5的梯度下降(gradient descent algorithm)來最小化cross_entropy
。梯度下降是一種簡單的過程缚去,其中 TensorFlow 將每個(gè)變量往降低成本的方向微小的變化潮秘。但是 TensorFlow 也提供了許多其他的優(yōu)化算法:使用它是簡單的如同調(diào)整一條直線一樣。
TensorFlow 在這里實(shí)際上所做的是易结,在后臺(tái)中實(shí)現(xiàn)反向傳播和梯度下降的地方增加一個(gè)新的操作到你的圖里枕荞。然后它返回給你一個(gè)單獨(dú)的操作,當(dāng)運(yùn)行時(shí)搞动,進(jìn)行梯度下降訓(xùn)練躏精,微調(diào)你的變量使得損失減小。
現(xiàn)在我們可以在InteractiveSession
中啟動(dòng)模型:
sess = tf.InteractiveSession()
首先我們創(chuàng)建一個(gè)操作來初始化我們創(chuàng)建的變量:
tf.global_variables_initializer().run()
開始訓(xùn)練——我們執(zhí)行循環(huán)訓(xùn)練1000次:
for _ 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)的每次中鹦肿,我們“批量”從訓(xùn)練數(shù)據(jù)集中隨機(jī)抽取100個(gè)數(shù)據(jù)矗烛。我們用批數(shù)據(jù)替換占位符
來運(yùn)行train_step
。
使用小批量隨機(jī)數(shù)據(jù)稱為隨機(jī)訓(xùn)練狮惜,在這種情況下稱為隨機(jī)梯度下降高诺。理想情況下碌识,我們希望在每一步的訓(xùn)練中使用所有的數(shù)據(jù)碾篡,因?yàn)檫@樣我們可以更好的了解我們應(yīng)該做什么,但是這樣做將帶來很大的開銷筏餐。因此开泽,在每一步的訓(xùn)練中我們每次使用不同的子集。這樣的開銷不會(huì)太大而且可以得到相同的好處魁瞪。
Evaluating Our Model
那么我們的模型性能如何穆律?
首先,讓我們找出那些我們預(yù)測正確的標(biāo)簽导俘。 tf.argmax
是一個(gè)非常有用的函數(shù)峦耘,它能給你一個(gè)張量中某個(gè)維度上最大值的索引。例如旅薄, tf.argmax(y,1)
是 我們模型認(rèn)為每個(gè)輸入最有可能的標(biāo)簽辅髓,其中tf.argmax(y_,1)
是正確的標(biāo)簽。我們可以使用 tf.equal
來檢驗(yàn)我們的預(yù)測與真實(shí)是否匹配。
correct_prediction = tf.equal(tf.argmax(y,1), tf.argmax(y_,1))
這段代碼會(huì)給我們一組布爾值洛口。為了確定正確的比例矫付,我們將其轉(zhuǎn)化為浮點(diǎn)數(shù)。例如第焰,[True, False, True, True]
變成 [1,0,1,1]
买优,這樣其正確率為0.75。
accuracy = tf.reduce_mean(tf.cast(correct_prediction, tf.float32))
最后挺举,我們計(jì)算我們模型在測試集上的準(zhǔn)確性杀赢。
print(sess.run(accuracy, feed_dict={x: mnist.test.images, y_: mnist.test.labels}))
這大概為92%。
這個(gè)結(jié)果很好嗎豹悬?不怎么樣葵陵。實(shí)際上這個(gè)結(jié)果很差。這是因?yàn)槲覀兪褂昧艘粋€(gè)非常簡單的模型瞻佛。做了一些小的調(diào)整后脱篙,我們將得到97%的準(zhǔn)確率。最好的模型能得到大于99.7%的準(zhǔn)確率伤柄!(想了解更多信息绊困,請(qǐng)查看這個(gè)不同結(jié)果的列表 。)
重要的是我們從這個(gè)模型中所學(xué)到的東西适刀。不過如果你對(duì)這里的結(jié)論感到一點(diǎn)失望秤朗,請(qǐng)查看 下一個(gè)教程 ,我們使用 TensorFlow 構(gòu)建一個(gè)更復(fù)雜的模型已得到更好的結(jié)果笔喉!
[03]:http://latex.codecogs.com/svg.latex?evidence_i=\sum_j W_{i,~ j}x_j+b_i
<script type="text/javascript" src="http://cdn.mathjax.org/mathjax/latest/MathJax.js?config=default"></script>