91精品国产综合久久四虎久久_国产成人午夜高潮毛片_99er视频精品免费观看_2020亚洲熟女在线观看_日本女优人体写真_国内黄色毛片_年轻的老师中文版在线_丰满女邻居做爰_久久久久久精品成人免费图片

這不僅僅是另一個(gè)使用TensorFlow來(lái)做MNIST數(shù)字圖像識(shí)別的教程
一個(gè)信息量豐富、可視化的和交互的MNIST數(shù)字圖像識(shí)別教程。
編者注:想學(xué)習(xí)如何從零開(kāi)始構(gòu)建和訓(xùn)練你的第一個(gè)TensorFlow圖,請(qǐng)查看Aaron Schumacher在線教程里的《你好,TensorFlow!》!

更多內(nèi)容可以參考Strata北京2017的相關(guān)議題。

請(qǐng)耐心看完這篇博文。每一個(gè)人學(xué)習(xí)機(jī)器學(xué)習(xí)幾乎都是從用MNIST數(shù)據(jù)集來(lái)做手寫(xiě)數(shù)字圖像識(shí)別開(kāi)始的,但是我希望這個(gè)教程和其他的有所不同。

我記得當(dāng)TensorFlow在2015年11月被發(fā)布的時(shí)候,我按照這個(gè)《為T(mén)ensorFlow初學(xué)者準(zhǔn)備的MNIST教程》里面的步驟,盲目地復(fù)制和粘貼其中所有的代碼到我的命令行終端。然后一些數(shù)字按照它們本應(yīng)該出現(xiàn)的樣子跳了出來(lái)。我想“OK,我知道有些神奇的事情發(fā)生了。但為什么我看不到它們?”所以我寫(xiě)這篇博文的目的就是制作一個(gè)既有交互性還能有可視化的MNIST教程。同時(shí)還希望能教給你一兩件其他的教程僅僅假定你知道的事情。

這個(gè)教程里,我會(huì)使用TensorFlow的機(jī)器學(xué)習(xí)庫(kù),并基于Ubuntu 14.04版和Python3。如果你想了解如何在你自己的系統(tǒng)里安裝TensorFlow,可以在這里查看我的其他教程。

如果你還沒(méi)有安裝numpy和matplotlib庫(kù),你需要安裝他們。請(qǐng)打開(kāi)一個(gè)Ubuntu命令行終端,并敲入如下的一行命令:

$ sudo apt-get install python-numpy python3-numpy python-matplotlib python3-matplotlib

首先,我們需要在終端里開(kāi)啟一個(gè)python命令行編輯器,并用如下幾行代碼導(dǎo)入MNIST數(shù)據(jù)集(和其他python的依賴庫(kù)):

from tensorflow.examples.tutorials.mnist import input_data

mnist = input_data.read_data_sets(‘MNIST_data’, one_hot=True)

import matplotlib.pyplot as plt

import numpy as np

import random as ran

接著讓我們定義幾個(gè)函數(shù),用來(lái)指定從數(shù)據(jù)集里導(dǎo)入的訓(xùn)練和測(cè)試數(shù)據(jù)的數(shù)量。這些代碼并不是特別緊要,除非你希望能了解它們背后的邏輯。

你需要復(fù)制粘貼每個(gè)函數(shù),并在終端里敲兩次回車。

def TRAIN_SIZE(num):

print (‘Total Training Images in Dataset = ‘ + str(mnist.train.images.shape))

print (‘————————————————–‘)

x_train = mnist.train.images[:num,:]

print (‘x_train Examples Loaded = ‘ + str(x_train.shape))

y_train = mnist.train.labels[:num,:]

print (‘y_train Examples Loaded = ‘ + str(y_train.shape))

print(”)

return x_train, y_train

def TEST_SIZE(num):

print (‘Total Test Examples in Dataset = ‘ + str(mnist.test.images.shape))

print (‘————————————————–‘)

x_test = mnist.test.images[:num,:]

print (‘x_test Examples Loaded = ‘ + str(x_test.shape))

y_test = mnist.test.labels[:num,:]

print (‘y_test Examples Loaded = ‘ + str(y_test.shape))

return x_test, y_test

我們還要定義兩個(gè)簡(jiǎn)單的函數(shù)來(lái)重新排列圖像尺寸并顯示這些圖像數(shù)據(jù):

def display_digit(num):

print(y_train[num])

label = y_train[num].argmax(axis=0)

image = x_train[num].reshape([28,28])

plt.title(‘Example: %d? Label: %d’ % (num, label))

plt.imshow(image, cmap=plt.get_cmap(‘gray_r’))

plt.show()

def display_mult_flat(start, stop):

images = x_train[start].reshape([1,784])

for i in range(start+1,stop):

images = np.concatenate((images, x_train[i].reshape([1,784])))

plt.imshow(images, cmap=plt.get_cmap(‘gray_r’))

plt.show()

現(xiàn)在開(kāi)始構(gòu)建和訓(xùn)練我們的模型的部分。首先我們定義一些變量來(lái)指定希望導(dǎo)入多少訓(xùn)練和測(cè)試樣本。剛開(kāi)始我會(huì)導(dǎo)入所有的數(shù)據(jù),但是后面我會(huì)改變這個(gè)值來(lái)節(jié)省一些資源:

x_train, y_train = TRAIN_SIZE(55000)

Total Training Images in Dataset = (55000, 784)

————————————————–

x_train Examples Loaded = (55000, 784)

y_train Examples Loaded = (55000, 10)

那么這些代碼到底是什么意思哪?在我們用的這個(gè)數(shù)據(jù)集里面,一共有55000個(gè)手寫(xiě)的從0到9的數(shù)字樣本。每個(gè)樣本都是一個(gè)28×28像素的圖像,并被扁平化成一個(gè)包含784個(gè)值的數(shù)組,其中每個(gè)值代表了一個(gè)像素的灰度。之所以要被扁平化,是因?yàn)橹挥羞@樣TensorFlow才能線性地使用它。上面的代碼顯示了在變量x_train?里面,我們導(dǎo)入了55000個(gè)樣本,每個(gè)都包含784個(gè)像素。變量x_train?是一個(gè)55000行加784列的矩陣。變量y_train?包含了所有x_train?樣本所對(duì)應(yīng)的正確的標(biāo)識(shí)。這里并沒(méi)有用一個(gè)整數(shù)來(lái)存貯標(biāo)識(shí),而是用一個(gè)1×10的二元數(shù)組來(lái)存儲(chǔ)。其中某一位數(shù)字為1就代表這個(gè)數(shù)字是它對(duì)應(yīng)那個(gè)位置。這種方式也被叫做一熱位編碼(one-hot encoding)。下面的例子給出了代表數(shù)字7的數(shù)組。

Img-1-array-b4889b9860c9e009bbd58e827a114129

圖1 代表數(shù)字7的數(shù)組。來(lái)源:Justin Francis

讓我們來(lái)隨便找一張圖片,并用我們上面定義的函數(shù)來(lái)讀取扁平化的數(shù)據(jù),重新排列它,再顯示出來(lái),并把它所對(duì)應(yīng)的標(biāo)識(shí)也打印出來(lái)(注意:想要繼續(xù)編輯python代碼,你需要關(guān)掉matplot打開(kāi)的窗口):

display_digit(ran.randint(0, x_train.shape[0]))

figure_2-33bc342809c17f6253e0f0931bc7650e

圖2 ?[ 0.? 0.? 0.? 0.? 0.? 0.? 0.? 1.? 0.? 0.] 來(lái)源:Justin Francis

下面是分類器使用的多個(gè)訓(xùn)練樣本的扁平化的數(shù)據(jù)形式。當(dāng)然,我們的分類器看到的是從零到一個(gè)代表灰度的數(shù)值,而不是看到的像素點(diǎn)。

display_mult_flat(0,400)

figure_3_CROP-a82c885d99db57d5493b91bddadda9e5

圖3 前400個(gè)訓(xùn)練樣本。來(lái)源:Justin Francis

到目前為止,我們還根本沒(méi)用到TensorFlow。下一步就是導(dǎo)入TensorFlow,并定義我們的會(huì)話(session)。某種意義上說(shuō),TensorFlow會(huì)創(chuàng)建一個(gè)有向無(wú)環(huán)圖,讓你導(dǎo)入數(shù)據(jù),并在一個(gè)會(huì)話里運(yùn)行這個(gè)圖。

import tensorflow as tf

sess = tf.Session()

接著我們定義一個(gè)占位符。顧名思義,占位符是一個(gè)用來(lái)導(dǎo)入數(shù)據(jù)的變量。唯一需要注意的就是,想要導(dǎo)入數(shù)據(jù)到這個(gè)變量,數(shù)據(jù)必須完全匹配占位符的尺寸(shape)和類型(type)。TensorFlow的官網(wǎng)是這樣解釋的:“一個(gè)占位符存在的意思僅僅是為了作為導(dǎo)入數(shù)據(jù)的目標(biāo)。它并沒(méi)有被初始化且不包含數(shù)據(jù)?!边@里我們定義x占位符作為一個(gè)導(dǎo)入x_train數(shù)據(jù)的變量。

x = tf.placeholder(tf.float32, shape=[None, 784])

當(dāng)我們把None分配給占位符時(shí),就意味著這個(gè)占位符可以被導(dǎo)入任意數(shù)量的樣本。在我們的例子里,這個(gè)占位符可以被導(dǎo)入任意多個(gè)有784列的值。

下面我們定義y_,用來(lái)導(dǎo)入y_train的數(shù)據(jù)。這個(gè)變量后面會(huì)被用來(lái)比較我們的分類預(yù)測(cè)與標(biāo)準(zhǔn)答案。這里可以認(rèn)為我們的標(biāo)識(shí)就是分類的類別。

y_ = tf.placeholder(tf.float32, shape=[None, 10])

接著我們定義權(quán)重?W和偏置量b。這兩個(gè)變量是分類器里的普通工作者:它們是在訓(xùn)練完的分類器里,我們用來(lái)計(jì)算預(yù)測(cè)所需要的唯一的值。

首先我們把權(quán)重和偏置量都設(shè)為零,因?yàn)殡S后TensorFlow會(huì)自己優(yōu)化這些值。注意:我們的權(quán)重W是一個(gè)784個(gè)值對(duì)應(yīng)于10個(gè)分類的每一個(gè)類的集合。

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

b = tf.Variable(tf.zeros([10]))

我喜歡把這些權(quán)重看做是對(duì)應(yīng)于10個(gè)數(shù)字的10張速查表。這和老師們用一個(gè)透明的速查表來(lái)給多選題目打分很類似。不幸的是對(duì)偏置量的解釋有些超出這個(gè)教程的范疇,但我還是喜歡把它看成一個(gè)和權(quán)重相關(guān)的特殊關(guān)系。它們兩個(gè)一起影響我們的最終答案。

現(xiàn)在我們來(lái)定義分類函數(shù),即?y。這個(gè)特殊的分類器也被叫做多元邏輯回歸。我們通過(guò)把每個(gè)扁平化的數(shù)字與我們的權(quán)重相乘,并加上偏置量來(lái)做出預(yù)測(cè):

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

讓我們暫時(shí)先忽略softmax,直接看看softmax函數(shù)內(nèi)部是什么樣。matmul是矩陣相乘的函數(shù)。如果你了解矩陣相乘,你應(yīng)該能較好地理解這個(gè)計(jì)算,并且知道x?*?W?+?b會(huì)產(chǎn)生一個(gè)訓(xùn)練樣本數(shù)量(m)×分類的數(shù)量(n)的(m×n)的矩陣。

Matrix_multiplication_qtl3.svg_CROP-d6afcd60f46108686975458f49b43289

圖4 簡(jiǎn)單的矩陣相乘。來(lái)源:Quartl on Wikimedia Commons

如果你還對(duì)此有疑惑,可以通過(guò)執(zhí)行對(duì)y的輸出來(lái)確認(rèn):

print(y)

Tensor(“Softmax:0”, shape=(?, 10), dtype=float32)

上面的輸出結(jié)果告訴我們y在會(huì)話里什么,但如果我們是想看到y(tǒng)的實(shí)際值哪?由于不能通過(guò)直接打印一個(gè)TensorFlow圖里面的對(duì)象來(lái)獲得它的實(shí)際值,你必須運(yùn)行一個(gè)給它導(dǎo)入數(shù)據(jù)的適當(dāng)?shù)臅?huì)話。注意:如果你僅僅只是運(yùn)行sess.run(y),TensorFlow會(huì)提醒你需要給它導(dǎo)入數(shù)據(jù)。

x_train, y_train = TRAIN_SIZE(3)

sess.run(tf.global_variables_initializer())

#如果使用TensorFlow 0.12之前的版本,請(qǐng)用下面的命令:

#sess.run(tf.initialize_all_variables())

print(sess.run(y, feed_dict={x: x_train}))

[[ 0.1? 0.1? 0.1? 0.1? 0.1? 0.1? 0.1? 0.1? 0.1? 0.1]

[ 0.1? 0.1? 0.1? 0.1? 0.1? 0.1? 0.1? 0.1? 0.1? 0.1]

[ 0.1? 0.1? 0.1? 0.1? 0.1? 0.1? 0.1? 0.1? 0.1? 0.1]]

現(xiàn)在我們可以看到對(duì)前三個(gè)訓(xùn)練樣本的分類預(yù)測(cè)。到目前為止,我們的分類器什么也不知道。所以它就給出了一個(gè)平均的10%概率,來(lái)預(yù)測(cè)我們的三個(gè)樣本在每個(gè)類別里的概率。

但是你可能會(huì)問(wèn)TensorFlow是怎么知道這個(gè)概率的?它是通過(guò)計(jì)算softmax函數(shù)的結(jié)果來(lái)學(xué)習(xí)概率的。Softmax函數(shù)獲得一系列數(shù)值,并設(shè)法讓它們的和為1,并以此來(lái)獲得每個(gè)值的概率。任何softmax值總是會(huì)被轉(zhuǎn)換成大于0小于1。還是沒(méi)搞清楚?可以試著運(yùn)行下面的代碼(譯者注:在TensorFlow版本0.10運(yùn)行會(huì)報(bào)錯(cuò),版本0.11上正常),以了解softmax是怎么做數(shù)學(xué)計(jì)算的。

sess.run(tf.nn.softmax(tf.zeros([4])))

sess.run(tf.nn.softmax(tf.constant([0.1, 0.005, 2])))

接著定義我們的cross_entropy函數(shù),也叫做損失或代價(jià)函數(shù)。它被用來(lái)衡量我們分類的結(jié)果的好壞。代價(jià)越高,則越不準(zhǔn)確。它是通過(guò)比較預(yù)測(cè)的每個(gè)樣本的y與y_train里面的真實(shí)值來(lái)計(jì)算準(zhǔn)確度的。我們的目標(biāo)是最小化這個(gè)損失。

cross_entropy = tf.reduce_mean(-tf.reduce_sum(y_ * tf.log(y), reduction_indices=[1]))

這個(gè)函數(shù)對(duì)所有的預(yù)測(cè)值y(值的范圍是從0到1)進(jìn)行l(wèi)og運(yùn)算后和真實(shí)值y_進(jìn)行矩陣元素相乘。如果值接近0,log計(jì)算后的值就是一個(gè)非常大的負(fù)值(例如,-np.log(0.01) = 4.6);如果值接近1,log計(jì)算后的值就是一個(gè)小的負(fù)值(例如,-np.log(0.99) = 0.1)。

Logx.svg_CROP-ffa511daa78917099590b02956888207

圖5 Y = log (x)函數(shù)。來(lái)源Lfahlberg on Wikimedia Commons

本質(zhì)上,如果預(yù)測(cè)結(jié)果是不對(duì)的但是置信度很高,我們就用一個(gè)很大的值來(lái)“懲罰”分類器;而如果結(jié)果是對(duì)的且置信度也很高,我們只用一個(gè)非常小的值。

下面是一個(gè)編造的python數(shù)組的例子。顯示了softmax預(yù)測(cè)的結(jié)果是3且置信度很高。

j = [0.03, 0.03, 0.01, 0.9, 0.01, 0.01, 0.0025,0.0025, 0.0025, 0.0025]

讓我用下面這個(gè)標(biāo)識(shí)為3的數(shù)組作為基準(zhǔn)來(lái)比較它和我們的softmax函數(shù)。

k = [0,0,0,1,0,0,0,0,0,0]

您能猜出損失函數(shù)會(huì)返回什么結(jié)果嗎?你能看出下面對(duì)“j”進(jìn)行l(wèi)og計(jì)算是如何對(duì)一個(gè)錯(cuò)誤答案用一個(gè)非常大的負(fù)數(shù)進(jìn)行懲罰的嗎?運(yùn)行下面的例子來(lái)試著理解吧。

-np.log(j)

-np.multiply(np.log(j),k)

上面會(huì)返回9個(gè)0和一個(gè)0.1053。加和后,我們就會(huì)認(rèn)為這是一個(gè)不錯(cuò)的預(yù)測(cè)。下面看看如果我們的預(yù)測(cè)結(jié)果不變,但實(shí)際的正確答案是2的時(shí)候會(huì)怎么樣。

k = [0,0,1,0,0,0,0,0,0,0]

np.sum(-np.multiply(np.log(j),k))

這次cross_entropy函數(shù)返回的是4.6051。意味著對(duì)我們錯(cuò)誤的預(yù)測(cè)做了一個(gè)很嚴(yán)重的懲罰。之所以有這樣的嚴(yán)重的懲罰,是因?yàn)榉诸惼骱苡行判牡卣J(rèn)為是3,但真實(shí)值應(yīng)該是2。

下面我們開(kāi)始訓(xùn)練分類器。訓(xùn)練的目的就是找到合適的W和b值來(lái)得到盡可能小的損失值。

下面部分里,你可以自己修改一些變量的值。下面所有的全大寫(xiě)字母變量的值都是可以被修改和嘗試的。實(shí)際上我很鼓勵(lì)你這么做!先用例子里給出的這些值,然后你可以修改來(lái)得到更多或者更少的訓(xùn)練樣本數(shù)量,或者是不同的學(xué)習(xí)率的值,再看看結(jié)果有什么不同。

如果你設(shè)定TRAIN_SIZE為一個(gè)很大的數(shù),那么要有等一會(huì)的心理準(zhǔn)備。任何時(shí)間,你都可以從這里開(kāi)始再運(yùn)行這些代碼,并嘗試不同的值。

x_train, y_train = TRAIN_SIZE(5500)

x_test, y_test = TEST_SIZE(10000)

LEARNING_RATE = 0.1

TRAIN_STEPS = 2500

現(xiàn)在我們可以初始化所有的變量了。初始化之后,TensorFlow的圖才能夠使用它們。

init = tf.global_variables_initializer()

#If using TensorFlow prior to 0.12 use:

#init = tf.initialize_all_variables()

sess.run(init)

我們需要使用梯度下降法來(lái)訓(xùn)練分類器。首先定義我們的訓(xùn)練方法以及一些測(cè)量準(zhǔn)確度的變量。變量training將會(huì)基于選定的LEARNING_RATE(學(xué)習(xí)速率)執(zhí)行梯度下降優(yōu)化器,以期獲得最小化的損失函數(shù)cross_entropy。

training = tf.train.GradientDescentOptimizer(LEARNING_RATE).minimize(cross_entropy)

correct_prediction = tf.equal(tf.argmax(y,1), tf.argmax(y_,1))

accuracy = tf.reduce_mean(tf.cast(correct_prediction, tf.float32))

我們定義一個(gè)循環(huán),重復(fù)執(zhí)行TRAIN_STEPS次。每循環(huán)一次,就運(yùn)行一次training,使用feed_dict從x_train和y_train里輸入訓(xùn)練樣本。為了計(jì)算準(zhǔn)確率,代碼會(huì)運(yùn)行來(lái)accuracy對(duì)x_test里沒(méi)見(jiàn)過(guò)的數(shù)據(jù)進(jìn)行分類并比較獲得的y值和y_test的值。我們的測(cè)試數(shù)據(jù)必須是分類器沒(méi)見(jiàn)過(guò)的,沒(méi)有用于訓(xùn)練,這一點(diǎn)非常重要。如果一個(gè)老師給學(xué)生們一個(gè)小測(cè)驗(yàn),而最后還用同樣的試題來(lái)做期末考試,那么最終會(huì)得到一個(gè)對(duì)學(xué)生們掌握知識(shí)的程度的不準(zhǔn)確的測(cè)量。

for i in range(TRAIN_STEPS+1):

sess.run(training, feed_dict={x: x_train, y_: y_train})

if i%100 == 0:

print(‘Training Step:’ + str(i) + ‘? Accuracy =? ‘ + str(sess.run(accuracy, feed_dict={x: x_test, y_: y_test})) + ‘? Loss = ‘ + str(sess.run(cross_entropy, {x: x_train, y_: y_train})))

為了對(duì)梯度下降的原理做可視化,你可以把損失想象為一個(gè)基于y_和y的784維的圖像,其中包含不同的x、W和b值。如果你無(wú)法可視化784維,這很正常。我強(qiáng)烈建議你看看Chris Olah的這個(gè)博文來(lái)了解MNIST所涉及的維度問(wèn)題。為了能更好更簡(jiǎn)單地解釋這個(gè)問(wèn)題,我們使用兩維空間的函數(shù)y = x^2。

2000px-Y-x2.svg_CROP-b3c8a97949dde322d5d427d389fbeb0d

圖6 拋物線y = x^2。來(lái)源: Adrignola on Wikimedia Commons

在循環(huán)的每一步中,依賴于cross_entropy的計(jì)算值的大小,分類器會(huì)根據(jù)LEARNING_RATE移動(dòng)一步,向它認(rèn)為會(huì)降低cross_entropy的方向前進(jìn)一點(diǎn)。而這個(gè)更低的點(diǎn)則是由TensorFlow通過(guò)對(duì)cross_entropy求導(dǎo)數(shù)計(jì)算得出的。這個(gè)導(dǎo)數(shù)是在當(dāng)前點(diǎn)的切線的斜率。在向這個(gè)新的點(diǎn)移動(dòng)的時(shí)候,相應(yīng)地W和b都會(huì)被改變,而斜率也在降低。在我們舉的這個(gè)y = x^2例子里,這就意味著向X=0方向移動(dòng),也即最小化。如果這個(gè)學(xué)習(xí)速率非常小,那么分類器就會(huì)在訓(xùn)練過(guò)程中采用很小的步長(zhǎng);如果這個(gè)值太大,分類器的步長(zhǎng)就會(huì)很大,那么就很可能“跨越”過(guò)真正的最小點(diǎn)。

Parabola-antipodera-fc9340fc00fc732a8c304683a10b75ce

圖7 實(shí)黑線顯示的是在某個(gè)點(diǎn)的切線。來(lái)源:Tosha on Wikimedia Commons

有沒(méi)有注意到上面例子里訓(xùn)練循環(huán)結(jié)束前的階段,雖然損失還在降低但是準(zhǔn)確率則是在略微地降低?這意味著我們還是可以持續(xù)地降低損失值,但是這對(duì)于預(yù)測(cè)未見(jiàn)過(guò)的測(cè)試數(shù)據(jù)并提高準(zhǔn)確度并沒(méi)有什么幫助。這也被稱為過(guò)擬合(不能泛化)。使用代碼給出的默認(rèn)設(shè)置值,我得到了大概91%的準(zhǔn)確率。如果我想通過(guò)作弊得到94%的準(zhǔn)確率,我可以把測(cè)試樣本數(shù)量取為100。這顯示了如果沒(méi)有充足的測(cè)試樣本的話,你可能會(huì)得到一個(gè)有偏頗的準(zhǔn)確率。

需要記住的是上面是計(jì)算我們的分類器的一個(gè)非常低效的方法。但我是故意這樣做的,主要是為了學(xué)習(xí)和做實(shí)驗(yàn)。理想情況是當(dāng)用一個(gè)非常大的數(shù)據(jù)集做訓(xùn)練時(shí),可以采取小批次多次訓(xùn)練,而不是一次都訓(xùn)練完。如果你想學(xué)習(xí)這么做的話,可以看看TensorFlow網(wǎng)站上的這個(gè)教程。

下面到了我最喜歡的部分。我們已經(jīng)計(jì)算出了權(quán)重的速查表,那么就用下面的代碼把他們畫(huà)出來(lái)吧。

for i in range(10):

plt.subplot(2, 5, i+1)

weight = sess.run(W)[:,i]

plt.title(i)

plt.imshow(weight.reshape([28,28]), cmap=plt.get_cmap(‘seismic’))

frame1 = plt.gca()

frame1.axes.get_xaxis().set_visible(False)

frame1.axes.get_yaxis().set_visible(False)

再可視化一下。

plt.show()

index-572fe4dbb7be3a13472d199369b34141

圖8 來(lái)源:Justin Francis

上圖對(duì)從0到9的權(quán)重值進(jìn)行了可視化。這也是我們的分類器最重要的部分。這個(gè)機(jī)器學(xué)習(xí)的整個(gè)工作就是找出什么是最優(yōu)的權(quán)重。一旦這些權(quán)重被計(jì)算出來(lái),就可以用這個(gè)權(quán)重速查表來(lái)很容易地找到答案了。這也就是為什么神經(jīng)網(wǎng)絡(luò)可以很容易地被移植移動(dòng)設(shè)備上。因?yàn)槟P鸵坏┯?xùn)練好,就不再需要很多存儲(chǔ)和計(jì)算資源來(lái)做計(jì)算了。我們的分類器就是通過(guò)比較測(cè)試樣例和圖里面的紅色與藍(lán)色區(qū)域去做預(yù)測(cè)的。認(rèn)為越紅的區(qū)域命中的概率越高;白色的區(qū)域是中性的,而藍(lán)色的區(qū)域則是錯(cuò)誤的。

所以現(xiàn)在讓我們使用這個(gè)速查表來(lái)對(duì)一個(gè)樣本進(jìn)行分類。

x_train, y_train = TRAIN_SIZE(1)

display_digit(0)

看看得出的預(yù)測(cè)y。

answer = sess.run(y, feed_dict={x: x_train})

print(answer)

這是一個(gè)(1×10)的矩陣。每一列包含一個(gè)概率值。

[[? 2.12480136e-05 ? 1.16469264e-05 ? 8.96317810e-02 ? 1.92015115e-02

8.20863759e-04 ? 1.25168199e-05 ? 3.85381973e-05 ? 8.53746116e-01

6.91888575e-03 ? 2.95970142e-02]]

但這樣的顯示對(duì)我們不是很有用。因此我們用argmax函數(shù)來(lái)獲得最高預(yù)測(cè)概率值的那個(gè)位置。

answer.argmax()

至此,讓我們使用這個(gè)速查表來(lái)建立一個(gè)函數(shù),對(duì)這個(gè)數(shù)據(jù)集里的一個(gè)隨機(jī)選取的圖片做識(shí)別。

def display_compare(num):

# THIS WILL LOAD ONE TRAINING EXAMPLE

x_train = mnist.train.images[num,:].reshape(1,784)

y_train = mnist.train.labels[num,:]

# THIS GETS OUR LABEL AS A INTEGER

label = y_train.argmax()

# THIS GETS OUR PREDICTION AS A INTEGER

prediction = sess.run(y, feed_dict={x: x_train}).argmax()

plt.title(‘Prediction: %d Label: %d’ % (prediction, label))

plt.imshow(x_train.reshape([28,28]), cmap=plt.get_cmap(‘gray_r’))

plt.show()

然后運(yùn)行這個(gè)函數(shù)。

display_compare(ran.randint(0, 55000))

你能找到一個(gè)預(yù)測(cè)錯(cuò)誤的例子嗎?只要運(yùn)行display_compare(2),你就可以找到分類器做的一個(gè)錯(cuò)誤的數(shù)字識(shí)別(把9認(rèn)成4)。你覺(jué)得為什么對(duì)這個(gè)樣本的分類會(huì)出錯(cuò)?

下面的部分是這個(gè)教程有趣的地方??纯聪旅娴膭?dòng)畫(huà)。注意當(dāng)使用1到10個(gè)訓(xùn)練樣本時(shí)對(duì)權(quán)重做的可視化了嗎?很明顯,訓(xùn)練數(shù)據(jù)很少的時(shí)候,模型很難有泛化的能力。下面的動(dòng)畫(huà)顯示了權(quán)重是如何隨著訓(xùn)練樣本數(shù)量增加而變化的。你能發(fā)現(xiàn)是怎么變化的嗎?

combined-d7e409c18c787681d5ef03a84450456a

圖9 來(lái)源:Justin Francis

你也可以看出一個(gè)線性分類器的局限性:在某個(gè)數(shù)量點(diǎn)后,用更多的數(shù)據(jù)訓(xùn)練并不能進(jìn)一步提升準(zhǔn)確率。如果我們?cè)噲D去識(shí)別一個(gè)寫(xiě)在這個(gè)方形靠左邊的數(shù)字“1”,你覺(jué)得會(huì)發(fā)生什么?分類器會(huì)很難做出識(shí)別,因?yàn)槲覀兯械挠?xùn)練樣本的數(shù)字1都是在中間附近的。

希望這篇博文能幫助你更好地理解這個(gè)MNIST代碼背后的故事。要注意的是,這個(gè)神經(jīng)網(wǎng)絡(luò)僅僅只有兩層。這不是深度學(xué)習(xí)!想獲得幾近完美的準(zhǔn)確率,我們必須開(kāi)始卷積地深度思考。

如果你想更交互地運(yùn)行這個(gè)會(huì)話,這里是我的GitHub庫(kù),其中包括一個(gè)Jupyter Notebook的版本。在寫(xiě)這個(gè)教程的過(guò)程中我很開(kāi)心,也學(xué)到了很多。非常感謝你的閱讀。真心希望你在看完這篇博文后,一些新的思路能在你的腦海中形成。

Justin Francis

Justin居住在加拿大西海岸的一個(gè)小農(nóng)場(chǎng)。這個(gè)農(nóng)場(chǎng)專注于樸門(mén)道德和設(shè)計(jì)的農(nóng)藝。在此之前,他是一個(gè)非營(yíng)利性社區(qū)合作社自行車商店的創(chuàng)始人和教育者。在過(guò)去的兩年中,他住在一艘帆船上,全職探索和體驗(yàn)加拿大的喬治亞海峽。但現(xiàn)在他的主要精力都放在了學(xué)習(xí)機(jī)器學(xué)習(xí)上。

Numbers 0-9. (source: Denise Krebs on Flickr).