丁香五月天婷婷久久婷婷色综合91|国产传媒自偷自拍|久久影院亚洲精品|国产欧美VA天堂国产美女自慰视屏|免费黄色av网站|婷婷丁香五月激情四射|日韩AV一区二区中文字幕在线观看|亚洲欧美日本性爱|日日噜噜噜夜夜噜噜噜|中文Av日韩一区二区

您正在使用IE低版瀏覽器,為了您的雷峰網(wǎng)賬號安全和更好的產(chǎn)品體驗(yàn),強(qiáng)烈建議使用更快更安全的瀏覽器
此為臨時(shí)鏈接,僅用于文章預(yù)覽,將在時(shí)失效
人工智能開發(fā)者 正文
發(fā)私信給AI研習(xí)社
發(fā)送

0

從理論到實(shí)踐,手把手教你如何用 TensorFlow 實(shí)現(xiàn) CNN

本文作者: AI研習(xí)社 2017-05-08 16:56
導(dǎo)語:如何用 TensorFlow 實(shí)現(xiàn) CNN ?

雷鋒網(wǎng)按:本文作者宋傳標(biāo),原文載于作者個(gè)人博客,雷鋒網(wǎng)已獲授權(quán)。

  一、CNN的引入

在人工的全連接神經(jīng)網(wǎng)絡(luò)中,每相鄰兩層之間的每個(gè)神經(jīng)元之間都是有邊相連的。當(dāng)輸入層的特征維度變得很高時(shí),這時(shí)全連接網(wǎng)絡(luò)需要訓(xùn)練的參數(shù)就會增大很多,計(jì)算速度就會變得很慢,例如一張黑白的 28×28 的手寫數(shù)字圖片,輸入層的神經(jīng)元就有784個(gè),如下圖所示: 

從理論到實(shí)踐,手把手教你如何用 TensorFlow 實(shí)現(xiàn) CNN

若在中間只使用一層隱藏層,參數(shù) w 就有 784×15=11760 多個(gè);若輸入的是28×28 帶有顏色的RGB格式的手寫數(shù)字圖片,輸入神經(jīng)元就有28×28×3=2352 個(gè)…… 。這很容易看出使用全連接神經(jīng)網(wǎng)絡(luò)處理圖像中的需要訓(xùn)練參數(shù)過多的問題。

而在卷積神經(jīng)網(wǎng)絡(luò)(Convolutional Neural Network,CNN)中,卷積層的神經(jīng)元只與前一層的部分神經(jīng)元節(jié)點(diǎn)相連,即它的神經(jīng)元間的連接是非全連接的,且同一層中某些神經(jīng)元之間的連接的權(quán)重 w 和偏移 b 是共享的(即相同的),這樣大量地減少了需要訓(xùn)練參數(shù)的數(shù)量。

卷積神經(jīng)網(wǎng)絡(luò)CNN的結(jié)構(gòu)一般包含這幾個(gè)層:

● 輸入層:用于數(shù)據(jù)的輸入

● 卷積層:使用卷積核進(jìn)行特征提取和特征映射

● 激勵(lì)層:由于卷積也是一種線性運(yùn)算,因此需要增加非線性映射

● 池化層:進(jìn)行下采樣,對特征圖稀疏處理,減少數(shù)據(jù)運(yùn)算量。

● 全連接層:通常在CNN的尾部進(jìn)行重新擬合,減少特征信息的損失

● 輸出層:用于輸出結(jié)果

當(dāng)然中間還可以使用一些其他的功能層:

● 歸一化層(Batch Normalization):在CNN中對特征的歸一化

● 切分層:對某些(圖片)數(shù)據(jù)的進(jìn)行分區(qū)域的單獨(dú)學(xué)習(xí)

● 融合層:對獨(dú)立進(jìn)行特征學(xué)習(xí)的分支進(jìn)行融合

  二、CNN的層次結(jié)構(gòu)

輸入層:

在CNN的輸入層中,(圖片)數(shù)據(jù)輸入的格式 與 全連接神經(jīng)網(wǎng)絡(luò)的輸入格式(一維向量)不太一樣。CNN的輸入層的輸入格式保留了圖片本身的結(jié)構(gòu)。

對于黑白的 28×28 的圖片,CNN的輸入是一個(gè) 28×28 的的二維神經(jīng)元,如下圖所示:

從理論到實(shí)踐,手把手教你如何用 TensorFlow 實(shí)現(xiàn) CNN

而對于RGB格式的28×28圖片,CNN的輸入則是一個(gè) 3×28×28 的三維神經(jīng)元(RGB中的每一個(gè)顏色通道都有一個(gè) 28×28 的矩陣),如下圖所示:

從理論到實(shí)踐,手把手教你如何用 TensorFlow 實(shí)現(xiàn) CNN

卷積層:

在卷積層中有幾個(gè)重要的概念:

local receptive fields(感受視野)

shared weights(共享權(quán)值)

假設(shè)輸入的是一個(gè) 28×28 的的二維神經(jīng)元,我們定義5×5 的 一個(gè) local receptive fields(感受視野),即 隱藏層的神經(jīng)元與輸入層的5×5個(gè)神經(jīng)元相連,這個(gè)5*5的區(qū)域就稱之為Local Receptive Fields,如下圖所示:

從理論到實(shí)踐,手把手教你如何用 TensorFlow 實(shí)現(xiàn) CNN

可類似看作:隱藏層中的神經(jīng)元 具有一個(gè)固定大小的感受視野去感受上一層的部分特征。在全連接神經(jīng)網(wǎng)絡(luò)中,隱藏層中的神經(jīng)元的感受視野足夠大乃至可以看到上一層的所有特征。

而在卷積神經(jīng)網(wǎng)絡(luò)中,隱藏層中的神經(jīng)元的感受視野比較小,只能看到上一次的部分特征,上一層的其他特征可以通過平移感受視野來得到同一層的其他神經(jīng)元,由同一層其他神經(jīng)元來看:

從理論到實(shí)踐,手把手教你如何用 TensorFlow 實(shí)現(xiàn) CNN

設(shè)移動的步長為1:從左到右掃描,每次移動 1 格,掃描完之后,再向下移動一格,再次從左到右掃描。

具體過程如動圖所示:

從理論到實(shí)踐,手把手教你如何用 TensorFlow 實(shí)現(xiàn) CNN

從理論到實(shí)踐,手把手教你如何用 TensorFlow 實(shí)現(xiàn) CNN

可看出 卷積層的神經(jīng)元是只與前一層的部分神經(jīng)元節(jié)點(diǎn)相連,每一條相連的線對應(yīng)一個(gè)權(quán)重 w 。

一個(gè)感受視野帶有一個(gè)卷積核,我們將 感受視野 中的權(quán)重 w 矩陣稱為 卷積核 ;將感受視野對輸入的掃描間隔稱為步長(stride);當(dāng)步長比較大時(shí)(stride>1),為了掃描到邊緣的一些特征,感受視野可能會“出界”,這時(shí)需要對邊界擴(kuò)充(pad),邊界擴(kuò)充可以設(shè)為 0 或 其他值。步長 和 邊界擴(kuò)充值的大小由用戶來定義。

卷積核的大小由用戶來定義,即定義的感受視野的大??;卷積核的權(quán)重矩陣的值,便是卷積神經(jīng)網(wǎng)絡(luò)的參數(shù),為了有一個(gè)偏移項(xiàng) ,卷積核可附帶一個(gè)偏移項(xiàng) b ,它們的初值可以隨機(jī)來生成,可通過訓(xùn)練進(jìn)行變化。

因此 感受視野 掃描時(shí)可以計(jì)算出下一層神經(jīng)元的值為:

從理論到實(shí)踐,手把手教你如何用 TensorFlow 實(shí)現(xiàn) CNN

對下一層的所有神經(jīng)元來說,它們從不同的位置去探測了上一層神經(jīng)元的特征。

我們將通過 一個(gè)帶有卷積核的感受視野 掃描生成的下一層神經(jīng)元矩陣 稱為 一個(gè)feature map (特征映射圖),如下圖的右邊便是一個(gè) feature map:

從理論到實(shí)踐,手把手教你如何用 TensorFlow 實(shí)現(xiàn) CNN

因此在同一個(gè) feature map 上的神經(jīng)元使用的卷積核是相同的,因此這些神經(jīng)元 shared weights,共享卷積核中的權(quán)值和附帶的偏移。一個(gè) feature map 對應(yīng) 一個(gè)卷積核,若我們使用 3 個(gè)不同的卷積核,可以輸出3個(gè)feature map:(感受視野:5×5,布長stride:1)

從理論到實(shí)踐,手把手教你如何用 TensorFlow 實(shí)現(xiàn) CNN

因此在CNN的卷積層,我們需要訓(xùn)練的參數(shù)大大地減少到了 (5×5+1)×3=78個(gè)。

假設(shè)輸入的是 28×28 的RGB圖片,即輸入的是一個(gè) 3×28×28 的的二維神經(jīng)元,這時(shí)卷積核的大小不只用長和寬來表示,還有深度,感受視野也對應(yīng)的有了深度,如下圖所示:

從理論到實(shí)踐,手把手教你如何用 TensorFlow 實(shí)現(xiàn) CNN

由圖可知:感受視野: 3×2×2 ; 卷積核: 3×2×2 ,深度為3;下一層的神經(jīng)元的值為:b+∑2d=0∑1i=0∑1j=0wdijxdij . 卷積核的深度和感受視野的深度相同,都由輸入數(shù)據(jù)來決定,長寬可由自己來設(shè)定,數(shù)目也可以由自己來設(shè)定,一個(gè)卷積核依然對應(yīng)一個(gè) feature map 。

注:“stride=1”表示在長和寬上的移動間隔都為1,即 stridewidth=1 且 strideheight=1

激勵(lì)層:

激勵(lì)層主要對卷積層的輸出進(jìn)行一個(gè)非線性映射,因?yàn)榫矸e層的計(jì)算還是一種線性計(jì)算。使用的激勵(lì)函數(shù)一般為ReLu函數(shù):

f(x)=max(x,0)

卷積層和激勵(lì)層通常合并在一起稱為“卷積層”。

池化層:

當(dāng)輸入經(jīng)過卷積層時(shí),若感受視野比較小,布長stride比較小,得到的feature map (特征圖)還是比較大,可以通過池化層來對每一個(gè) feature map 進(jìn)行降維操作,輸出的深度還是不變的,依然為 feature map 的個(gè)數(shù)。

池化層也有一個(gè)“池化視野(filter)”來對feature map矩陣進(jìn)行掃描,對“池化視野”中的矩陣值進(jìn)行計(jì)算,一般有兩種計(jì)算方式:

Max pooling:取“池化視野”矩陣中的最大值

Average pooling:取“池化視野”矩陣中的平均值

掃描的過程中同樣地會涉及的掃描布長stride,掃描方式同卷積層一樣,先從左到右掃描,結(jié)束則向下移動布長大小,再從左到右。如下圖示例所示:

從理論到實(shí)踐,手把手教你如何用 TensorFlow 實(shí)現(xiàn) CNN

其中“池化視野”filter: 2×2;布長stride:2。(注:“ 池化視野”為個(gè)人叫法)

最后可將 3 個(gè) 24×24 的 feature map 下采樣得到 3 個(gè) 24×24 的特征矩陣:

從理論到實(shí)踐,手把手教你如何用 TensorFlow 實(shí)現(xiàn) CNN

歸一化層:

1. Batch Normalization

Batch Normalization(批量歸一化)實(shí)現(xiàn)了在神經(jīng)網(wǎng)絡(luò)層的中間進(jìn)行預(yù)處理的操作,即在上一層的輸入歸一化處理后再進(jìn)入網(wǎng)絡(luò)的下一層,這樣可有效地防止“梯度彌散”,加速網(wǎng)絡(luò)訓(xùn)練。

Batch Normalization具體的算法如下圖所示: 

從理論到實(shí)踐,手把手教你如何用 TensorFlow 實(shí)現(xiàn) CNN

每次訓(xùn)練時(shí),取 batch_size 大小的樣本進(jìn)行訓(xùn)練,在BN層中,將一個(gè)神經(jīng)元看作一個(gè)特征,batch_size 個(gè)樣本在某個(gè)特征維度會有 batch_size 個(gè)值,然后在每個(gè)神經(jīng)元 xi 維度上的進(jìn)行這些樣本的均值和方差,通過公式得到 xi∧,再通過參數(shù) γ 和 β 進(jìn)行線性映射得到每個(gè)神經(jīng)元對應(yīng)的輸出 yi 。在BN層中,可以看出每一個(gè)神經(jīng)元維度上,都會有一個(gè)參數(shù) γ 和 β ,它們同權(quán)重w一樣可以通過訓(xùn)練進(jìn)行優(yōu)化。

在卷積神經(jīng)網(wǎng)絡(luò)中進(jìn)行批量歸一化時(shí),一般對 未進(jìn)行ReLu激活的 feature map進(jìn)行批量歸一化,輸出后再作為激勵(lì)層的輸入,可達(dá)到調(diào)整激勵(lì)函數(shù)偏導(dǎo)的作用。

一種做法是將 feature map 中的神經(jīng)元作為特征維度,參數(shù) γ 和 β 的數(shù)量和則等于 2×fmapwidth×fmaplength×fmapnum,這樣做的話參數(shù)的數(shù)量會變得很多;

另一種做法是把 一個(gè) feature map 看做一個(gè)特征維度,一個(gè) feature map 上的神經(jīng)元共享這個(gè) feature map的 參數(shù) γ 和 β ,參數(shù) γ 和 β 的數(shù)量和則等于 2×fmapnum,計(jì)算均值和方差則在batch_size個(gè)訓(xùn)練樣本在每一個(gè)feature map維度上的均值和方差。

注:fmapnum指的是一個(gè)樣本的feature map數(shù)量,feature map 跟神經(jīng)元一樣也有一定的排列順序。

Batch Normalization 算法的訓(xùn)練過程和測試過程的區(qū)別:

在訓(xùn)練過程中,我們每次都會將 batch_size 數(shù)目大小的訓(xùn)練樣本 放入到CNN網(wǎng)絡(luò)中進(jìn)行訓(xùn)練,在BN層中自然可以得到計(jì)算輸出所需要的 均值 和 方差 ;

而在測試過程中,我們往往只會向CNN網(wǎng)絡(luò)中輸入一個(gè)測試樣本,這是在BN層計(jì)算的均值和方差會均為 0,因?yàn)橹挥幸粋€(gè)樣本輸入,因此BN層的輸入也會出現(xiàn)很大的問題,從而導(dǎo)致CNN網(wǎng)絡(luò)輸出的錯(cuò)誤。所以在測試過程中,我們需要借助訓(xùn)練集中所有樣本在BN層歸一化時(shí)每個(gè)維度上的均值和方差,當(dāng)然為了計(jì)算方便,我們可以在 batch_num 次訓(xùn)練過程中,將每一次在BN層歸一化時(shí)每個(gè)維度上的均值和方差進(jìn)行相加,最后再進(jìn)行求一次均值即可。

2. Local Response Normalization

近鄰歸一化(Local Response Normalization)的歸一化方法主要發(fā)生在不同的相鄰的卷積核(經(jīng)過ReLu之后)的輸出之間,即輸入是發(fā)生在不同的經(jīng)過ReLu之后的 feature map 中。

LRN的公式如下:

從理論到實(shí)踐,手把手教你如何用 TensorFlow 實(shí)現(xiàn) CNN

其中: 

a(i,x,y) 表示第i個(gè)卷積核的輸出(經(jīng)過ReLu層)的feature map上的 (x,y) 位置上的值。 

b(i,x,y) 表示 a(i,x,y) 經(jīng)LRN后的輸出。 

N 表示卷積核的數(shù)量,即輸入的 feature map的個(gè)數(shù)。 

n 表示近鄰的卷積核(或feature map)個(gè)數(shù),由自己來決定。 

k,α,β是超參數(shù),由用戶自己調(diào)整或決定。

與BN的區(qū)別:BN依據(jù)mini batch的數(shù)據(jù),近鄰歸一僅需要自己來決定,BN訓(xùn)練中有學(xué)習(xí)參數(shù);BN歸一化主要發(fā)生在不同的樣本之間,LRN歸一化主要發(fā)生在不同的卷積核的輸出之間。

切分層:

在一些應(yīng)用中,需要對圖片進(jìn)行切割,獨(dú)立地對某一部分區(qū)域進(jìn)行單獨(dú)學(xué)習(xí)。這樣可以對特定部分進(jìn)行通過調(diào)整 感受視野 進(jìn)行力度更大的學(xué)習(xí)。

融合層:

融合層可以對切分層進(jìn)行融合,也可以對不同大小的卷積核學(xué)習(xí)到的特征進(jìn)行融合。

例如在GoogleLeNet 中,使用多種分辨率的卷積核對目標(biāo)特征進(jìn)行學(xué)習(xí),通過 padding 使得每一個(gè) feature map 的長寬都一致,之后再將多個(gè) feature map 在深度上拼接在一起: 

從理論到實(shí)踐,手把手教你如何用 TensorFlow 實(shí)現(xiàn) CNN

融合的方法有幾種,一種是特征矩陣之間的拼接級聯(lián),另一種是在特征矩陣進(jìn)行運(yùn)算 (+,-,x,max,conv)。

全連接層和輸出層

全連接層主要對特征進(jìn)行重新擬合,減少特征信息的丟失;輸出層主要準(zhǔn)備做好最后目標(biāo)結(jié)果的輸出。例如VGG的結(jié)構(gòu)圖,如下圖所示: 

從理論到實(shí)踐,手把手教你如何用 TensorFlow 實(shí)現(xiàn) CNN

  三、典型的卷積神經(jīng)網(wǎng)絡(luò)

LeNet-5模型

第一個(gè)成功應(yīng)用于數(shù)字?jǐn)?shù)字識別的卷積神經(jīng)網(wǎng)絡(luò)模型(卷積層自帶激勵(lì)函數(shù),下同):

從理論到實(shí)踐,手把手教你如何用 TensorFlow 實(shí)現(xiàn) CNN

卷積層的卷積核邊長都是5,步長都為1;池化層的窗口邊長都為2,步長都為2。

AlexNet 模型

具體結(jié)構(gòu)圖:

從理論到實(shí)踐,手把手教你如何用 TensorFlow 實(shí)現(xiàn) CNN

從AlexNet的結(jié)構(gòu)可發(fā)現(xiàn):經(jīng)典的卷積神經(jīng)網(wǎng)絡(luò)結(jié)構(gòu)通常為:

輸入層 → (卷積層+→池化層?)+→全連接層+→輸出層

AlexNet卷積層的卷積核邊長為5或3,池化層的窗口邊長為3。具體參數(shù)如圖所示:

從理論到實(shí)踐,手把手教你如何用 TensorFlow 實(shí)現(xiàn) CNN

VGGNet 模型

VGGNet 模型 和 AlexNet模型 在結(jié)構(gòu)上沒多大變化,在卷積層部位增加了多個(gè)卷積層。AlexNet(上) 和 VGGNet (下)的對比如下圖所示:

從理論到實(shí)踐,手把手教你如何用 TensorFlow 實(shí)現(xiàn) CNN

具體參數(shù)如圖所示:其中CONV3-64:表示卷積核的長和寬為3,個(gè)數(shù)有64個(gè);POOL2:表示池化窗口的長和寬都為2,其他類似。 

從理論到實(shí)踐,手把手教你如何用 TensorFlow 實(shí)現(xiàn) CNN

GoogleNet 模型

使用了多個(gè)不同分辨率的卷積核,最后再對它們得到的feature map 按深度融合在一起,結(jié)構(gòu)如圖:

從理論到實(shí)踐,手把手教你如何用 TensorFlow 實(shí)現(xiàn) CNN

其中,有一些主要的模塊稱為 Inception module,例如: 

從理論到實(shí)踐,手把手教你如何用 TensorFlow 實(shí)現(xiàn) CNN

在 Inception module 中使用到了很多 1×1 的卷積核,使用 1×1 的卷積核,步長為1時(shí),輸入的feature map和輸出的feature map長寬不會發(fā)生改變,但可以通過改變 1×1 的卷積核的數(shù)目,來達(dá)到減小feature map的厚度的效果,從而做到一些訓(xùn)練參數(shù)的減少。

GoogleNet還有一個(gè)特點(diǎn)就是它是全卷積結(jié)構(gòu)(FCN)的,網(wǎng)絡(luò)的最后沒有使用全連接層,一方面這樣可以減少參數(shù)的數(shù)目,不容易過擬合,一方面也帶來了一些空間信息的丟失。代替全連接層的是全局平均池化(Global Average Pooling,GAP)的方法,思想是:為每一個(gè)類別輸出一個(gè) feature map ,再取每一個(gè) feature map上的平均值,作為最后的softmax層的輸入。

ResNet模型

在前面的CNN模型中,都是將輸入一層一層地傳遞下去(圖左),當(dāng)層次比較深時(shí),模型不是很好訓(xùn)練。在ResNet模型中,它將低層學(xué)習(xí)到的特征和高層的學(xué)習(xí)到的特征進(jìn)行一個(gè)融合(加法運(yùn)算,圖右),這樣反向傳遞時(shí),導(dǎo)數(shù)傳遞得更快,減少梯度彌散的現(xiàn)象。

注意:F(X)的shape需要等于 X 的shape ,這樣才可以進(jìn)行相加。

從理論到實(shí)踐,手把手教你如何用 TensorFlow 實(shí)現(xiàn) CNN

  四、Tensorflow代碼

主要的函數(shù)說明:

卷積層: 

tf.nn.conv2d(input, filter, strides, padding, use_cudnn_on_gpu=None, data_format=None, name=None)

參數(shù)說明:

● data_format:表示輸入的格式,有兩種分別為:“NHWC”和“NCHW”,默認(rèn)為“NHWC”

● input:輸入是一個(gè)4維格式的(圖像)數(shù)據(jù),數(shù)據(jù)的 shape 由 data_format 決定:當(dāng) data_format 為“NHWC”輸入數(shù)據(jù)的shape表示為[batch, in_height, in_width, in_channels],分別表示訓(xùn)練時(shí)一個(gè)batch的圖片數(shù)量、圖片高度、 圖片寬度、 圖像通道數(shù)。當(dāng) data_format 為“NHWC”輸入數(shù)據(jù)的shape表示為[batch, in_channels, in_height, in_width]

● filter:卷積核是一個(gè)4維格式的數(shù)據(jù):shape表示為:[height,width,in_channels, out_channels],分別表示卷積核的高、寬、深度(與輸入的in_channels應(yīng)相同)、輸出 feature map的個(gè)數(shù)(即卷積核的個(gè)數(shù))。

● strides:表示步長:一個(gè)長度為4的一維列表,每個(gè)元素跟data_format互相對應(yīng),表示在data_format每一維上的移動步長。當(dāng)輸入的默認(rèn)格式為:“NHWC”,則 strides = [batch , in_height , in_width, in_channels]。其中 batch 和 in_channels 要求一定為1,即只能在一個(gè)樣本的一個(gè)通道上的特征圖上進(jìn)行移動,in_height , in_width表示卷積核在特征圖的高度和寬度上移動的布長,即 strideheight 和 stridewidth 。

● padding:表示填充方式:“SAME”表示采用填充的方式,簡單地理解為以0填充邊緣,但還有一個(gè)要求,左邊(上邊)補(bǔ)0的個(gè)數(shù)和右邊(下邊)補(bǔ)0的個(gè)數(shù)一樣或少一個(gè),“VALID”表示采用不填充的方式,多余地進(jìn)行丟棄。具體公式:

“SAME”: output_spatial_shape[i]=(input_spatial_shape[i] / strides[i])

“VALID”: output_spatial_shape[i]=((input_spatial_shape[i]-(spatial_filter_shape[i]-1)/strides[i])

池化層: 

tf.nn.max_pool( value, ksize,strides,padding,data_format=’NHWC’,name=None) 

或者 

tf.nn.avg_pool(…)

參數(shù)說明:

● value:表示池化的輸入:一個(gè)4維格式的數(shù)據(jù),數(shù)據(jù)的 shape 由 data_format 決定,默認(rèn)情況下shape 為[batch, height, width, channels]

● 其他參數(shù)與 tf.nn.cov2d 類型

● ksize:表示池化窗口的大?。阂粋€(gè)長度為4的一維列表,一般為[1, height, width, 1],因不想在batch和channels上做池化,則將其值設(shè)為1。

Batch Nomalization層: 

batch_normalization( x,mean,variance,offset,scale, variance_epsilon,name=None)

● mean 和 variance 通過 tf.nn.moments 來進(jìn)行計(jì)算: 

batch_mean, batch_var = tf.nn.moments(x, axes = [0, 1, 2], keep_dims=True),注意axes的輸入。對于以feature map 為維度的全局歸一化,若feature map 的shape 為[batch, height, width, depth],則將axes賦值為[0, 1, 2]

● x 為輸入的feature map 四維數(shù)據(jù),offset、scale為一維Tensor數(shù)據(jù),shape 等于 feature map 的深度depth。

代碼示例:

通過搭建卷積神經(jīng)網(wǎng)絡(luò)來實(shí)現(xiàn)sklearn庫中的手寫數(shù)字識別,搭建的卷積神經(jīng)網(wǎng)絡(luò)結(jié)構(gòu)如下圖所示: 

從理論到實(shí)踐,手把手教你如何用 TensorFlow 實(shí)現(xiàn) CNN

import tensorflow as tf

from sklearn.datasets import load_digits

import numpy as np

digits = load_digits()

X_data = digits.data.astype(np.float32)

Y_data = digits.target.astype(np.float32).reshape(-1,1)

print X_data.shape

print Y_data.shape

(1797, 64)

(1797, 1)

from sklearn.preprocessing import MinMaxScaler

scaler = MinMaxScaler()

X_data = scaler.fit_transform(X_data)

from sklearn.preprocessing import OneHotEncoder

Y = OneHotEncoder().fit_transform(Y_data).todense() #one-hot編碼

Y

matrix([[ 1.,  0.,  0., ...,  0.,  0.,  0.],

        [ 0.,  1.,  0., ...,  0.,  0.,  0.],

        [ 0.,  0.,  1., ...,  0.,  0.,  0.],

        ..., 

        [ 0.,  0.,  0., ...,  0.,  1.,  0.],

        [ 0.,  0.,  0., ...,  0.,  0.,  1.],

        [ 0.,  0.,  0., ...,  0.,  1.,  0.]])

# 轉(zhuǎn)換為圖片的格式 (batch,height,width,channels)

X = X_data.reshape(-1,8,8,1)

batch_size = 8 # 使用MBGD算法,設(shè)定batch_size為8

def generatebatch(X,Y,n_examples, batch_size):

    for batch_i in range(n_examples // batch_size):

        start = batch_i*batch_size

        end = start + batch_size

        batch_xs = X[start:end]

        batch_ys = Y[start:end]

        yield batch_xs, batch_ys # 生成每一個(gè)batch

tf.reset_default_graph()

# 輸入層

tf_X = tf.placeholder(tf.float32,[None,8,8,1])

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

# 卷積層+激活層

conv_filter_w1 = tf.Variable(tf.random_normal([3, 3, 1, 10]))

conv_filter_b1 =  tf.Variable(tf.random_normal([10]))

relu_feature_maps1 = tf.nn.relu(\

                tf.nn.conv2d(tf_X, conv_filter_w1,strides=[1, 1, 1, 1], padding='SAME') + conv_filter_b1)

# 池化層

max_pool1 = tf.nn.max_pool(relu_feature_maps1,ksize=[1,3,3,1],strides=[1,2,2,1],padding='SAME')

print max_pool1

Tensor("MaxPool:0", shape=(?, 4, 4, 10), dtype=float32)

# 卷積層

conv_filter_w2 = tf.Variable(tf.random_normal([3, 3, 10, 5]))

conv_filter_b2 =  tf.Variable(tf.random_normal([5]))

conv_out2 = tf.nn.conv2d(relu_feature_maps1, conv_filter_w2,strides=[1, 2, 2, 1], padding='SAME') + conv_filter_b2

print conv_out2

Tensor("add_4:0", shape=(?, 4, 4, 5), dtype=float32)

# BN歸一化層+激活層 

batch_mean, batch_var = tf.nn.moments(conv_out2, [0, 1, 2], keep_dims=True)

shift = tf.Variable(tf.zeros([5]))

scale = tf.Variable(tf.ones([5]))

epsilon = 1e-3

BN_out = tf.nn.batch_normalization(conv_out2, batch_mean, batch_var, shift, scale, epsilon)

print BN_out

relu_BN_maps2 = tf.nn.relu(BN_out)

Tensor("batchnorm/add_1:0", shape=(?, 4, 4, 5), dtype=float32)

# 池化層

max_pool2 = tf.nn.max_pool(relu_BN_maps2,ksize=[1,3,3,1],strides=[1,2,2,1],padding='SAME')

print max_pool2

Tensor("MaxPool_1:0", shape=(?, 2, 2, 5), dtype=float32)

# 將特征圖進(jìn)行展開

max_pool2_flat = tf.reshape(max_pool2, [-1, 2*2*5])

# 全連接層

fc_w1 = tf.Variable(tf.random_normal([2*2*5,50]))

fc_b1 =  tf.Variable(tf.random_normal([50]))

fc_out1 = tf.nn.relu(tf.matmul(max_pool2_flat, fc_w1) + fc_b1)

# 輸出層

out_w1 = tf.Variable(tf.random_normal([50,10]))

out_b1 = tf.Variable(tf.random_normal([10]))

pred = tf.nn.softmax(tf.matmul(fc_out1,out_w1)+out_b1)

loss = -tf.reduce_mean(tf_Y*tf.log(tf.clip_by_value(pred,1e-11,1.0)))

train_step = tf.train.AdamOptimizer(1e-3).minimize(loss)

y_pred = tf.arg_max(pred,1)

bool_pred = tf.equal(tf.arg_max(tf_Y,1),y_pred)

accuracy = tf.reduce_mean(tf.cast(bool_pred,tf.float32)) # 準(zhǔn)確率

with tf.Session() as sess:

    sess.run(tf.global_variables_initializer())

    for epoch in range(1000): # 迭代1000個(gè)周期

        for batch_xs,batch_ys in generatebatch(X,Y,Y.shape[0],batch_size): # 每個(gè)周期進(jìn)行MBGD算法

            sess.run(train_step,feed_dict={tf_X:batch_xs,tf_Y:batch_ys})

        if(epoch%100==0):

            res = sess.run(accuracy,feed_dict={tf_X:X,tf_Y:Y})

            print (epoch,res)

    res_ypred = y_pred.eval(feed_dict={tf_X:X,tf_Y:Y}).flatten() # 只能預(yù)測一批樣本,不能預(yù)測一個(gè)樣本

    print res_ypred

(0, 0.36338341)

(100, 0.96828049)

(200, 0.99666113)

(300, 0.99554813)

(400, 0.99888706)

(500, 0.99777406)

(600, 0.9961046)

(700, 0.99666113)

(800, 0.99499166)

(900, 0.99888706)

[0 1 2 ..., 8 9 8]

在第100次個(gè)batch size 迭代時(shí),準(zhǔn)確率就快速接近收斂了,這得歸功于Batch Normalization 的作用!需要注意的是,這個(gè)模型還不能用來預(yù)測單個(gè)樣本,因?yàn)樵谶M(jìn)行BN層計(jì)算時(shí),單個(gè)樣本的均值和方差都為0,會得到相反的預(yù)測效果,解決方法詳見歸一化層。

from sklearn.metrics import  accuracy_score

print accuracy_score(Y_data,res_ypred.reshape(-1,1))

0.998887033945

TensorFlow & 神經(jīng)網(wǎng)絡(luò)算法高級應(yīng)用班” 要開課啦!

從初級到高級,理論 + 實(shí)戰(zhàn),一站式深度了解 TensorFlow!

本課程面向深度學(xué)習(xí)開發(fā)者,講授如何利用 TensorFlow 解決圖像識別、文本分析等具體問題。課程跨度為 10 周,將從 TensorFlow 的原理與基礎(chǔ)實(shí)戰(zhàn)技巧開始,一步步教授學(xué)員如何在 TensorFlow 上搭建 CNN、自編碼、RNN、GAN 等模型,并最終掌握一整套基于 TensorFlow 做深度學(xué)習(xí)開發(fā)的專業(yè)技能。

兩名授課老師佟達(dá)、白發(fā)川身為 ThoughtWorks 的資深技術(shù)專家,具有豐富的大數(shù)據(jù)平臺搭建、深度學(xué)習(xí)系統(tǒng)開發(fā)項(xiàng)目經(jīng)驗(yàn)。

時(shí)間:每周二、四晚 20:00-21:00

開課時(shí)長:總學(xué)時(shí) 20 小時(shí),分 10 周完成,每周 2 次,每次 1 小時(shí)

線上授課地址:http://www.mooc.ai/

雷鋒網(wǎng)(公眾號:雷鋒網(wǎng))相關(guān)閱讀:

CNN 在基于弱監(jiān)督學(xué)習(xí)的圖像分割中的應(yīng)用

三年來,CNN在圖像分割領(lǐng)域經(jīng)歷了怎樣的技術(shù)變革?

雷峰網(wǎng)版權(quán)文章,未經(jīng)授權(quán)禁止轉(zhuǎn)載。詳情見轉(zhuǎn)載須知。

從理論到實(shí)踐,手把手教你如何用 TensorFlow 實(shí)現(xiàn) CNN

分享:
相關(guān)文章

編輯

聚焦數(shù)據(jù)科學(xué),連接 AI 開發(fā)者。更多精彩內(nèi)容,請?jiān)L問:yanxishe.com
當(dāng)月熱門文章
最新文章
請?zhí)顚懮暾埲速Y料
姓名
電話
郵箱
微信號
作品鏈接
個(gè)人簡介
為了您的賬戶安全,請驗(yàn)證郵箱
您的郵箱還未驗(yàn)證,完成可獲20積分喲!
請驗(yàn)證您的郵箱
立即驗(yàn)證
完善賬號信息
您的賬號已經(jīng)綁定,現(xiàn)在您可以設(shè)置密碼以方便用郵箱登錄
立即設(shè)置 以后再說