乡下人产国偷v产偷v自拍,国产午夜片在线观看,婷婷成人亚洲综合国产麻豆,久久综合给合久久狠狠狠9

  • <output id="e9wm2"></output>
    <s id="e9wm2"><nobr id="e9wm2"><ins id="e9wm2"></ins></nobr></s>

    • 分享

      卷積神經(jīng)網(wǎng)絡(luò)簡(jiǎn)介

       蠟燭916 2019-01-24

      一、卷積




      如果我們?cè)?2 維上說(shuō)話(huà)。有兩個(gè) 

      的函數(shù) f(x, y) 和 g(x, y) 。所謂 f 和 g 的卷積就是一個(gè)新的 

      的函數(shù) c(x, y) 。通過(guò)下式得到:


      這式子的含義是:遍覽從負(fù)無(wú)窮到正無(wú)窮的全部 s 和 t 值,把 g 在 (x-s, y-t) 上的值乘以 f 在 (s, t) 上的值之后再“加和”到一起(積分意義上),得到 c 在 (x, y) 上的值。說(shuō)白了卷積就是一種“加權(quán)求和”:以 f 為權(quán),以 (x, y) 為中心,把 g 距離中心 (-s, -t) 位置上的值乘上 f 在 (s, t) 的值,最后加到一起。把卷積公式寫(xiě)成離散形式就更清楚了:

      第二個(gè)等號(hào)成立是因?yàn)樵谶@里我們每隔單位長(zhǎng)度 1 一采樣,△s和△t都是 1 ??梢粤?G 表示一幅 100 x 100 大小的灰度圖像。G(x, y) 取值 [0,255] 區(qū)間內(nèi)的整數(shù),是圖像在 (x, y) 的灰度值。x 和 y 坐標(biāo)取 [0, 99] ,其它位置上 G 值全取 0 。令 F 在 s 和 t 取 {-1, 0, 1} 的位置為特定值,其他位置全取 0 。F 可以看作是一個(gè) 3 x 3 的網(wǎng)格。如圖 1.1

      圖 1.1


      圖 1.1 中 G 每個(gè)小格子里的值就是圖像在 (x, y) 的灰度值。F 每個(gè)小格子里的值就是 F 在 (s, t) 的取值。

      圖 1.2


      如圖 1.2 所示,將 F 的中心 (0, 0) 對(duì)準(zhǔn) G 的 (6, 6) 。把 F 和 G 對(duì)應(yīng)的 9 個(gè)位置上各自的值相乘,再將 9 個(gè)乘積加在一起,就得到了卷積值 C(6, 6) 。對(duì) G 的每一個(gè)位置求 C 值,就得到了一幅新的圖像。其中注意三點(diǎn):


      1. F 是上下左右翻轉(zhuǎn)后再與 G 對(duì)準(zhǔn)的。因?yàn)榫矸e公式中 F(s, t) 乘上的是 G(x-s, y-t) 。比如 F(-1, -1) 乘上的是 G(7, 7) ;

      2. 如果 F 的所有值之和不等于 1.0,則 C 值有可能不落在 [0, 255] 區(qū)間內(nèi),那就不是一個(gè)合法的圖像灰度值。所以如果需要讓結(jié)果是一幅圖像,就得將 F 歸一化——令它的所有位置之和等于 1.0 ;

      3. 對(duì)于 G 邊緣上的點(diǎn),有可能它的周?chē)恢贸隽藞D像邊緣。此時(shí)可以把圖像邊緣之外的值當(dāng)做 0 ?;蛘咧挥?jì)算其周?chē)疾怀吘壍狞c(diǎn)的 C 。這樣計(jì)算出來(lái)的圖像就比原圖像小一些。在上例中是小了一圈,如果 F 覆蓋范圍更大,那么小的圈數(shù)更多。


      上述操作其實(shí)就是對(duì)數(shù)字圖像進(jìn)行離散卷積操作,又叫濾波。F 稱(chēng)作卷積核濾波器。不同的濾波器起不同的作用。想象一下,如果 F 的大小是 3 x 3 ,每個(gè)格子里的值都是 1/9 。那么濾波就相當(dāng)于對(duì)原圖像每一個(gè)點(diǎn)計(jì)算它周?chē)?3 x 3 范圍內(nèi) 9 個(gè)圖像點(diǎn)的灰度平均值。這應(yīng)該是一種模糊。看看效果。

      圖 1.3


      左圖是 lena 灰度原圖。中圖用 3 x 3 值都為 1/9 的濾波器去濾,得到一個(gè)輕微模糊的圖像。模糊程度不高是因?yàn)闉V波器覆蓋范圍小。右圖選取了 9 x 9 值為 1/81 的濾波器,模糊效果就較明顯了。濾波器還有許多其他用處。例如下面這個(gè)濾波器:



      注意該濾波器沒(méi)有歸一化(和不是 1.0 ),故濾出來(lái)的值可能不在 [0, 255] 之內(nèi)。通過(guò)減去最小值、除以最大/最小值之差、再乘以 255 并取整,把結(jié)果值歸一到 [0, 255] 之內(nèi),使之成為一幅灰度圖像?,F(xiàn)在嘗試用它來(lái)濾 lena 圖。

      圖 1.4


      該濾波器把圖像的邊緣檢測(cè)出來(lái)了。它就是 Sobel 算子。邊緣檢測(cè)、圖像模糊等等都是人們?cè)O(shè)計(jì)出來(lái)的、有專(zhuān)門(mén)用途的濾波器。如果搞一個(gè) 9 x 9 的隨機(jī)濾波器,會(huì)是什么效果呢?

      圖 1.5


      如上圖,效果也類(lèi)似于模糊。因?yàn)榘岩粋€(gè)像素點(diǎn)的值用它周?chē)?9 x 9 范圍的值隨機(jī)加權(quán)求和,相當(dāng)于“搗漿糊”。但可以看出模糊得并不潤(rùn)滑。

      這時(shí)我們不禁要想,如果不是由人來(lái)設(shè)計(jì)一個(gè)濾波器,而是從一個(gè)隨機(jī)濾波器開(kāi)始,根據(jù)某種目標(biāo)、用某種方法去逐漸調(diào)整它,直到它接近我們想要的樣子,可行么?這就是卷積神經(jīng)網(wǎng)絡(luò)(Convolutional Neural Network, CNN)的思想了??烧{(diào)整的濾波器是 CNN 的“卷積”那部分;如何調(diào)整濾波器則是 CNN 的“神經(jīng)網(wǎng)絡(luò)”那部分。





      二、神經(jīng)網(wǎng)絡(luò)




      人工神經(jīng)網(wǎng)絡(luò)(Neural Network, NN)作為一個(gè)計(jì)算模型,其歷史甚至要早于計(jì)算機(jī)。 W.S. McCulloch 和 W. Pitts 在四十年代就提出了人工神經(jīng)元模型。但是單個(gè)人工神經(jīng)元甚至無(wú)法計(jì)算異或。多個(gè)人工神經(jīng)元連接成網(wǎng)絡(luò)就可以克服無(wú)法計(jì)算異或的問(wèn)題。但是對(duì)于這樣的網(wǎng)絡(luò)——多層感知機(jī)網(wǎng)絡(luò),當(dāng)時(shí)的人們沒(méi)有發(fā)現(xiàn)訓(xùn)練它的方法。人工智能領(lǐng)域的巨擘馬文.明斯基認(rèn)為這個(gè)計(jì)算模型是沒(méi)有前途的。直到 7、80 年代,人們發(fā)現(xiàn)了訓(xùn)練多層感知機(jī)網(wǎng)絡(luò)的反向傳播算法(BP)。BP 的本質(zhì)是梯度下降算法。多層感知機(jī)網(wǎng)絡(luò)梯度的計(jì)算乍看十分繁瑣,實(shí)則有規(guī)律。


      人工神經(jīng)元就是用一個(gè)數(shù)學(xué)模型簡(jiǎn)單模擬神經(jīng)細(xì)胞。神經(jīng)細(xì)胞有多個(gè)樹(shù)突和一個(gè)伸長(zhǎng)的軸突。一個(gè)神經(jīng)元的軸突連接到其他神經(jīng)元的樹(shù)突,并向其傳導(dǎo)神經(jīng)脈沖。神經(jīng)元會(huì)根據(jù)來(lái)自它的若干樹(shù)突的信號(hào)決定是否從其軸突向其他神經(jīng)元發(fā)出神經(jīng)脈沖。

      圖 2.1


      一個(gè)人工神經(jīng)元就是對(duì)生物神經(jīng)元的數(shù)學(xué)建模(下文中“神經(jīng)元”就指人工神經(jīng)元,“神經(jīng)網(wǎng)絡(luò)”就指人工神經(jīng)網(wǎng)絡(luò))。見(jiàn)圖 2.2 。

      圖 2.2


      p1,p2,...,pn 是神經(jīng)元的輸入。a 是神經(jīng)元的輸出。神經(jīng)元將輸入 p1,p2,...,pn 加權(quán)求和后再加上偏置值 b ,最后再施加一個(gè)函數(shù) f ,即:

      上式最后是這個(gè)式子的向量形式。P 是輸入向量,W 是權(quán)值向量,b 是偏置值標(biāo)量 。f 稱(chēng)為激活函數(shù)( Activation Function )。激活函數(shù)可以采用多種形式。圖 2.3 展示了一些常用的激活函數(shù)。

      圖 2.3


      這是單個(gè)神經(jīng)元的定義。神經(jīng)網(wǎng)絡(luò)就是把許多這樣的神經(jīng)元連接成一個(gè)網(wǎng)絡(luò):一個(gè)神經(jīng)元的輸出作為另一個(gè)神經(jīng)元的輸入。神經(jīng)網(wǎng)絡(luò)可以有多種多樣的拓?fù)浣Y(jié)構(gòu)。其中最簡(jiǎn)單的就是“多層全連接前向神經(jīng)網(wǎng)絡(luò)”。它的輸入連接到網(wǎng)絡(luò)第一層的每個(gè)神經(jīng)元。前一層的每個(gè)神經(jīng)元的輸出連接到下一層每個(gè)神經(jīng)元的輸入。最后一層神經(jīng)元的輸出就是整個(gè)神經(jīng)網(wǎng)絡(luò)的輸出。


      圖 2.4 是一個(gè)三層神經(jīng)網(wǎng)絡(luò)。它接受 10 個(gè)輸入,也就是一個(gè) 10 元向量。第一層和第二層各有 12 個(gè)神經(jīng)元。最后一層有 6 個(gè)神經(jīng)元,就是說(shuō)這個(gè)神經(jīng)網(wǎng)絡(luò)輸出一個(gè) 6 元向量。神經(jīng)網(wǎng)絡(luò)最后一層稱(chēng)為輸出層,中間的層稱(chēng)為隱藏層。

      圖 2.4


      整個(gè)神經(jīng)網(wǎng)絡(luò)的計(jì)算可以用矩陣式給出。我們給出神經(jīng)網(wǎng)絡(luò)單層的式子。每層的神經(jīng)元個(gè)數(shù)不一樣,輸入/輸出維度也就不一樣,計(jì)算式中的矩陣和向量的行列數(shù)也就不一樣,但形式是一致的。假設(shè)我們考慮的這一層是第 i 層。它接受 m 個(gè)輸入,擁有 n 個(gè)神經(jīng)元( n 個(gè)輸出),那么這一層的計(jì)算如下式所示:

      上標(biāo) i 表示第 i 層。 

      是輸出向量,n 元,因?yàn)榈?i 層有 n 個(gè)神經(jīng)元。第 i 層的輸入,即第 i-1 層的輸出,是 m 元向量。權(quán)值矩陣 W 是 n x m 矩陣:n 個(gè)神經(jīng)元,每個(gè)神經(jīng)元有 m 個(gè)權(quán)值。W 乘以第 i - 1 層輸出的 m 向量,得到一個(gè) n 向量,加上 n 元偏置向量 b ,再對(duì)結(jié)果的每一個(gè)元素施以激活函數(shù) f ,最終得到第 i 層的 n 元輸出向量。


      若不嫌繁瑣,可以將第 i - 1 層的輸出也展開(kāi),最終能寫(xiě)出一個(gè)巨大的式子。它就是整個(gè)全連接前向神經(jīng)網(wǎng)絡(luò)的計(jì)算式。可以看出整個(gè)神經(jīng)網(wǎng)絡(luò)其實(shí)就是一個(gè)向量到向量的函數(shù)。至于它是什么函數(shù),就取決于網(wǎng)絡(luò)拓?fù)浣Y(jié)構(gòu)和每一個(gè)神經(jīng)元的權(quán)值和偏置值。如果隨機(jī)給出權(quán)值和偏置值,那么這個(gè)神經(jīng)網(wǎng)絡(luò)是無(wú)用的。我們想要的是有用的神經(jīng)網(wǎng)絡(luò)。它應(yīng)該表現(xiàn)出我們想要的行為。


      要達(dá)到這個(gè)目的,首先準(zhǔn)備一個(gè)從目標(biāo)函數(shù)采樣的包含若干“輸入-輸出對(duì)”的集合——訓(xùn)練集。把訓(xùn)練集的輸入送給神經(jīng)網(wǎng)絡(luò),得到的輸出肯定不是正確的輸出。因?yàn)橐婚_(kāi)始這個(gè)神經(jīng)網(wǎng)絡(luò)的行為是隨機(jī)的。


      把一個(gè)訓(xùn)練樣本輸入給神經(jīng)網(wǎng)絡(luò),計(jì)算輸出與目標(biāo)輸出的(向量)差的模平方(自己與自己的內(nèi)積)。再把全部 n 個(gè)樣本的差的模平方求平均,得到 e :

      e 稱(chēng)為均方誤差 mse 。全部輸出向量和目標(biāo)輸出向量之間的距離(差的模)越小,則 e 越小。e 越小則神經(jīng)網(wǎng)絡(luò)的行為與想要的行為越接近。


      目標(biāo)是使 e 變小。在這里 e 可以看做是全體權(quán)值和偏置值的一個(gè)函數(shù)。這就成為了一個(gè)無(wú)約束優(yōu)化問(wèn)題。如果能找到一個(gè)全局最小點(diǎn),e 值在可接受的范圍內(nèi),就可以認(rèn)為這個(gè)神經(jīng)網(wǎng)絡(luò)訓(xùn)練好了。它能夠很好地?cái)M合目標(biāo)函數(shù)。這里待優(yōu)化的函數(shù)也可以是 mse 外的其他函數(shù),統(tǒng)稱(chēng) Cost Function,都可以用 e 表示。


      經(jīng)典的神經(jīng)網(wǎng)絡(luò)的訓(xùn)練算法是反向傳播算法(Back Propagation, BP)。BP 算法屬于優(yōu)化理論中的梯度下降法(Gradient Descend)。將誤差 e 作為全部權(quán)值和全部偏置值的函數(shù)。算法的目的是在自變量空間內(nèi)找到 e 的全局極小點(diǎn)。


      首先隨機(jī)初始化全體權(quán)值和全體偏置值,之后在自變量空間中沿誤差函數(shù) e 在該點(diǎn)的梯度方向的反方向前進(jìn)一個(gè)步長(zhǎng)。梯度的反方向上函數(shù)方向?qū)?shù)最小,函數(shù)值下降最快。步長(zhǎng)稱(chēng)為學(xué)習(xí)速率(Learning Rate, LR)。如此反復(fù)迭代,最終(至少是期望)解運(yùn)動(dòng)到誤差曲面的全局最小點(diǎn)(請(qǐng)參考專(zhuān)欄文章:神經(jīng)網(wǎng)絡(luò)之梯度下降與反向傳播(上))。


      圖 2.5 是用 matlab 訓(xùn)練一個(gè)極簡(jiǎn)單的神經(jīng)網(wǎng)絡(luò)。它只有單輸入單輸出。輸入層有兩個(gè)神經(jīng)元,輸出層有一個(gè)神經(jīng)元。整個(gè)網(wǎng)絡(luò)有 4 個(gè)權(quán)值加 3 個(gè)偏置。圖中展示了固定其他權(quán)值,只把第一層第一個(gè)神經(jīng)元的權(quán)值

      和偏置

      做自變量時(shí)候的 e 曲面,以及隨著算法迭代,解的運(yùn)動(dòng)軌跡。

      圖 2.5



      最終算法沒(méi)有收斂到全局最優(yōu)解(紅 +)。但是解已經(jīng)運(yùn)動(dòng)到了一個(gè)峽谷的底部。由于底部過(guò)于平緩,解“走不動(dòng)”了。所得解比最優(yōu)也差不到哪去。


      對(duì)于一個(gè)稍復(fù)雜的神經(jīng)網(wǎng)絡(luò),e 對(duì)權(quán)值和偏置值的函數(shù)是一個(gè)復(fù)雜的函數(shù)。求梯度需要計(jì)算 e 對(duì)每一個(gè)權(quán)值和偏置值的偏導(dǎo)數(shù)。所幸的是求偏導(dǎo)的公式不會(huì)因?yàn)檫@個(gè)權(quán)值或偏置值距離輸出層越遠(yuǎn)而越復(fù)雜。對(duì)于每個(gè)神經(jīng)元可以計(jì)算一個(gè)值 delta ,稱(chēng)“局部誤差”或“靈敏度”。得到了每個(gè)神經(jīng)元的 delta 就很容易計(jì)算 e 對(duì)任何一個(gè)權(quán)值或偏執(zhí)值的偏導(dǎo)數(shù)。


      計(jì)算某神經(jīng)元的 delta 用到該神經(jīng)元激活函數(shù)的導(dǎo)函數(shù),對(duì)于輸出層用到輸出與目標(biāo)輸出的差;對(duì)于隱藏層用到下一層各神經(jīng)元的 delta 。每個(gè)神經(jīng)元將其 delta 傳遞給前一層的各神經(jīng)元。前一層的各神經(jīng)元收集后一層的神經(jīng)元的 delta 計(jì)算自己的 delta 。這就是“反向傳播”名稱(chēng)的由來(lái)——“局部誤差”或“靈敏度” delta 沿著反向向前傳,逐層計(jì)算所有權(quán)值和偏置值的偏導(dǎo)數(shù),最終得到梯度。詳細(xì)推導(dǎo)可參考書(shū)籍[1]第八章、[2]第十一章、[3]第四章、[4]第三章或[5]第十一章(或參考專(zhuān)欄文章:神經(jīng)網(wǎng)絡(luò)之梯度下降與反向傳播(下))。


      梯度下降法有很多變體。通過(guò)調(diào)整學(xué)習(xí)速率 LR 可以提高收斂速度;通過(guò)增加沖量可以避免陷入局部最優(yōu)點(diǎn)以及減少震蕩。還可以每一次不計(jì)算全部樣本的 e ,而是隨機(jī)取一部分樣本,根據(jù)它們的 e 更新權(quán)值。梯度下降是基于誤差函數(shù)的一階性質(zhì)。還有其他方法基于二階性質(zhì)進(jìn)行優(yōu)化,比如牛頓法等等。優(yōu)化作為一門(mén)應(yīng)用數(shù)學(xué)學(xué)科是機(jī)器學(xué)習(xí)的一個(gè)重要理論基礎(chǔ),在理論和實(shí)現(xiàn)上均有眾多結(jié)論和方法。參考[1]。





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




      現(xiàn)在把卷積濾波器和神經(jīng)網(wǎng)絡(luò)兩個(gè)思想結(jié)合起來(lái)。卷積濾波器無(wú)非就是一套權(quán)值。而神經(jīng)網(wǎng)絡(luò)也可以有(除全連接外的)其它拓?fù)浣Y(jié)構(gòu)。可以構(gòu)造如圖 3.1 所示意的神經(jīng)網(wǎng)絡(luò)。

      圖 3.1


      該神經(jīng)網(wǎng)絡(luò)接受 n x n 個(gè)輸入,產(chǎn)生 n x n 個(gè)輸出。圖中左邊的平面包含 n x n 個(gè)格子,每個(gè)格子中是一個(gè) [0, 255] 的整數(shù)值。它就是輸入圖像,也是這個(gè)神經(jīng)網(wǎng)絡(luò)的輸入。右邊的平面也是 n x n 個(gè)格子,每個(gè)格子是一個(gè)神經(jīng)元。每個(gè)神經(jīng)元連接到輸入上它對(duì)應(yīng)位置周?chē)?3 x 3 范圍內(nèi)的值。每個(gè)連接有一個(gè)權(quán)值。所有神經(jīng)元都如此連接(圖中只畫(huà)了一個(gè),出了輸入圖像邊緣的連接就認(rèn)為連接到常數(shù) 0 )。右邊層的每個(gè)神經(jīng)元將與它連接的 3 x 3 個(gè)輸入的值乘上連接權(quán)重并加和,得到該神經(jīng)元的輸出。n x n 個(gè)神經(jīng)元的輸出就是該神經(jīng)網(wǎng)絡(luò)的輸出。


      這個(gè)神經(jīng)網(wǎng)絡(luò)有兩點(diǎn)與全連接神經(jīng)網(wǎng)絡(luò)不同。首先它不是全連接的。右層的神經(jīng)元并非連接上全部輸入,而是只連接了一部分。這里的一部分就是輸入圖像的一個(gè)局部區(qū)域。我們常聽(tīng)說(shuō) CNN 能夠把握?qǐng)D像局部特征就是這個(gè)意思。這樣一來(lái)權(quán)值少了很多,因?yàn)檫B接少了。權(quán)值其實(shí)還更少,因?yàn)槊恳粋€(gè)神經(jīng)元的 9 個(gè)權(quán)值都是和其他神經(jīng)元共享的。全部 n x n 個(gè)神經(jīng)元都用這共同的一組 9 個(gè)權(quán)值,并且不要偏置值。那么這個(gè)神經(jīng)網(wǎng)絡(luò)其實(shí)一共只有 9 個(gè)參數(shù)需要調(diào)整。


      看了第一節(jié)的同學(xué)們都看出來(lái)了,這個(gè)神經(jīng)網(wǎng)絡(luò)所進(jìn)行的計(jì)算不就是一個(gè)卷積濾波器么?只不過(guò)卷積核的參數(shù)未定,需要我們?nèi)ビ?xùn)練——它是一個(gè)“可訓(xùn)練濾波器”。這個(gè)神經(jīng)網(wǎng)絡(luò)其實(shí)就是一個(gè)只有一個(gè)卷積層、且該卷積層只有一個(gè)濾波器(通道)的 CNN 。


      試著用 Sobel 算子濾出來(lái)的圖片作為目標(biāo)值去訓(xùn)練這個(gè)神經(jīng)網(wǎng)絡(luò)。給神經(jīng)網(wǎng)絡(luò)的輸入是灰度 lena 圖,目標(biāo)輸出是經(jīng)過(guò) Sobel 算子濾波的 lena 圖,見(jiàn)圖 1.4 。這唯一的一對(duì)輸入輸出圖片就構(gòu)成了訓(xùn)練集。神經(jīng)網(wǎng)絡(luò)權(quán)值隨機(jī)初始化,訓(xùn)練 2000 輪。如圖 3.7 。

      圖 3.2


      從左上到右下依次為:初始隨機(jī)濾波器輸出、每個(gè) 200 輪訓(xùn)練后的濾波器輸出( 10 幅)、最后一幅是 Sobel 算子的輸出,也就是用作訓(xùn)練的目標(biāo)圖像??梢钥吹浇?jīng)過(guò)最初 200 輪后,神經(jīng)網(wǎng)絡(luò)的輸出就已經(jīng)和 Sobel 算子的輸出看不出什么差別了。后面那些輪的輸出基本一樣。輸入與輸出的均方誤差 mse 隨著訓(xùn)練輪次的變化。如圖 3.3 。

      圖 3.3


      1500 輪過(guò)后,mse 基本就是 0 了。訓(xùn)練完成后網(wǎng)絡(luò)的權(quán)值是:

      與 Sobel 算子比較一下:

      注意訓(xùn)練出來(lái)的濾波器負(fù)數(shù)列在右側(cè)而不是左側(cè)。因?yàn)橛?jì)算卷積是把濾波器上下左右翻轉(zhuǎn)反著扣上去的。這并不重要,本質(zhì)是相同的。關(guān)鍵是一正列、一負(fù)列,中間零值列。非零值列三個(gè)值之比近似 1:2:1 。我們得到的就是一個(gè)近似的 Sobel 算子。我們以訓(xùn)練神經(jīng)網(wǎng)絡(luò)的方式把一個(gè)隨機(jī)濾波器訓(xùn)練成了 Sobel 算子。這就是優(yōu)化的魔力(代碼見(jiàn)本文最后)。


      在 CNN 中,這樣的濾波器層叫做卷積層。一個(gè)卷積層可以有多個(gè)濾波器,每一個(gè)叫做一個(gè) channel 。圖像是二維信號(hào)。信號(hào)也可以是其他維度的,比如一維、三維乃至更高維度。那么濾波器相應(yīng)的也有各種維度。回到二維圖像的例子,實(shí)際上一個(gè)卷積層面對(duì)的是多個(gè) channel 的 “一摞” 二維圖像。比如一幅 100 x 100 大小的彩色圖就會(huì)有 RGB 三個(gè) channel ,其數(shù)據(jù)維度是 3 x 100 x 100 。那么直接連接彩色圖像輸入的卷積層面對(duì)的是 3 x 100 x 100 的數(shù)據(jù),這時(shí)它的濾波器是 3 維度,第一維等于輸入 channel 數(shù)(這里是 3)。第 2、3 維度是指定的濾波器大小,例如 5 x 5 。卷積層把輸入的多 channel 的一摞二維圖像用三維濾波器濾出一幅二維圖像。假如這層有 32 個(gè)濾波器,那么這層輸出 32 個(gè) channel ,每個(gè) channel 是一個(gè)二維圖像。


      激活函數(shù)構(gòu)成 CNN 的一種層——激活層,這樣的層沒(méi)有可訓(xùn)練的參數(shù)。它為輸入施加激活函數(shù),例如 Sigmoid 、Tanh 等。


      還有一種層叫做 Pooling 層(池化層)。它也沒(méi)有參數(shù),起到降維的作用。將輸入切分成不重疊的一些 n x n 區(qū)域。每一個(gè)區(qū)域就包含 n x n 個(gè)值。從這 n x n 個(gè)值計(jì)算出一個(gè)值。計(jì)算方法可以是求平均、取最大等等。假設(shè) n = 2,那么 4 個(gè)輸入變成一個(gè)輸出。輸出圖像就是輸入圖像的 1/4 大小。若把 2 維的層展平成一維向量,后面可再連接一個(gè)全連接前向神經(jīng)網(wǎng)絡(luò)。


      通過(guò)把這些組件進(jìn)行組合就得到了一個(gè) CNN 。它直接以原始圖像為輸入,以最終的回歸或分類(lèi)問(wèn)題的結(jié)論為輸出,內(nèi)部兼有濾波圖像處理和函數(shù)擬合,所有參數(shù)放在一起訓(xùn)練。這就是卷積神經(jīng)網(wǎng)絡(luò)。



      四、舉個(gè)栗子




      手寫(xiě)數(shù)字識(shí)別。數(shù)據(jù)集中一共有 42000 個(gè) 28 x 28 的手寫(xiě)數(shù)字灰度圖片。十個(gè)數(shù)字( 0~9 )的樣本數(shù)量大致相等。為減少訓(xùn)練時(shí)間,隨機(jī)抽取其中 10000 個(gè)。圖 4.1 展示其中一部分。

      圖 4.1


      將樣本集合的 75% 用作訓(xùn)練,剩下的 25% 用作測(cè)試。構(gòu)造一個(gè)結(jié)構(gòu)如圖 4.2 的 CNN 。

      圖 4.2


      該 CNN 共有 9 層(不包括輸入層)。它接受 784 元向量作為輸入,就是一幅 28 x 28 的灰度圖片。并沒(méi)有將圖片先變形成 28 x 28 再輸入,因?yàn)樵?CNN 的第一層放了一個(gè) reshape 層。該層負(fù)責(zé)將 784 元的輸入向量變形成 1 x 28 x 28 的陣列。最開(kāi)始那個(gè) 1 x 表示只有一個(gè)通道 ,因?yàn)檫@是灰度圖像。如果是彩色圖像,就有 RGB 三個(gè)通道 。


      接下來(lái)放一個(gè)卷積層。它包含 32 個(gè) 3 x 3 的濾波器,所以它的輸出維度是 32 x 28 x 28 。32 個(gè)濾波器搞出來(lái) 32 幅圖像(通道),每個(gè)都是 28 x 28 大小。后續(xù)一個(gè) 2 x 2 的取平均值 Pooling 層把維度減小一半:32 x 14 x 14 。


      接著是第二個(gè)卷積層。它包含 64 個(gè) 32 x 3 x 3 的濾波器。它的輸出維度是 64 x 14 x 14 。注意該卷積層的輸入是 32 個(gè) channel ,每個(gè) 14 x 14 大小??梢钥醋?32 x 14 x 14 的一個(gè) 3 維輸入。該層的濾波器是 32 x 3 x 3 的一個(gè) 3 維濾波器。該層的輸出維度是 64 x 14 x 14 。后面再續(xù)一個(gè) 2 x 2 的取平均值 Pooling 層,輸出維度:64 x 7 x 7 。


      接著是一個(gè)展平層,沒(méi)有運(yùn)算也沒(méi)有參數(shù),只變化一下數(shù)據(jù)形狀:把 64 x 7 x 7 展平成了 3136 元向量。該 3136 元向量送給后面一個(gè)三層的全連接神經(jīng)網(wǎng)絡(luò)。該網(wǎng)絡(luò)的結(jié)構(gòu)是 1000 x 1000 x 10 。兩個(gè)隱藏層各有 1000 個(gè)神經(jīng)元,最后的輸出層有 10 個(gè)神經(jīng)元,代表 10 個(gè)數(shù)字。假如第六個(gè)輸出為 1 ,其余輸出為 0 ,就表示網(wǎng)絡(luò)判定這個(gè)手寫(xiě)數(shù)字為 “5”(數(shù)字 “0” 占第一個(gè)輸出,所以 “5” 占第六個(gè)輸出)。數(shù)字 “5” 就編碼成了:

      訓(xùn)練集和測(cè)試集的數(shù)字標(biāo)簽都這么編碼( one-hot 編碼)。


      全連接神經(jīng)網(wǎng)絡(luò)的隱藏層的激活函數(shù)采用 Sigmoid ,輸出層的激活函數(shù)采用 Linear 。誤差函數(shù)采用均方誤差 mse 。優(yōu)化算法采用隨機(jī)梯度下降 SGD 。SGD 是梯度下降的一個(gè)變體。它并不是用全體樣本計(jì)算 e 的梯度,而是每次迭代使用隨機(jī)選擇的一部分樣本來(lái)計(jì)算。學(xué)習(xí)速率 LR 初始為 0.01 ,每次迭代以 1e-6 的比例衰減。以 0.9 為參數(shù)設(shè)置沖量。訓(xùn)練過(guò)程持續(xù) 10 輪( epoch )。注意這里 10 輪不是指當(dāng)前解在解空間只運(yùn)動(dòng) 10 步。一輪是指全部 7500 個(gè)訓(xùn)練樣本都送進(jìn)網(wǎng)絡(luò)迭代一次。每次權(quán)值更新以 32 個(gè)樣本為一個(gè) batch 提交給算法。


      圖 4.3 展示了隨著訓(xùn)練進(jìn)行,mse 以及分類(lèi)正確率( accuracy )的變化情況( 橫坐標(biāo)取了 log )。

      圖 4.3


      該 CNN 在測(cè)試集上的正確率( accuracy )是 96.12%,各數(shù)字的準(zhǔn)確率( precision ) / 召回率( recall )/ f1-score 如下:


      precision    recall  f1-score   support


      0       0.96      0.98      0.97       252

      1       0.99      0.99      0.99       281

      2       0.98      0.94      0.96       240

      3       0.97      0.95      0.96       258

      4       0.96      0.92      0.94       239

      5       0.98      0.95      0.97       219

      6       0.96      0.99      0.97       273

      7       0.97      0.97      0.97       259

      8       0.92      0.96      0.94       231

      9       0.91      0.97      0.94       248

      avg / total       0.96      0.96      0.96      2500


      訓(xùn)練完成神經(jīng)網(wǎng)絡(luò)后,最有趣的是將其內(nèi)部權(quán)值以某種方式展現(xiàn)出來(lái)??粗切┥衩氐?、不明所以的連接強(qiáng)度最后竟產(chǎn)生表觀上有意義的行為,不由讓我們聯(lián)想起大腦中的神經(jīng)元連接竟構(gòu)成了我們的記憶、人格、情感 ... 引人遐思。


      在 CNN 上就更適合做這種事情。因?yàn)榫矸e層訓(xùn)練出來(lái)的是濾波器。用這些濾波器把輸入圖像濾一濾,看看 CNN 到底“看到”了什么。圖 4.4 是該 CNN 第一卷積層對(duì)一個(gè)手寫(xiě)數(shù)字 “5” 的 32 個(gè)輸出。

      圖 4.4


      接下來(lái)看一看第二卷積層輸出的 64 幅圖像。

      圖 4.5


      這些就是 CNN 經(jīng)兩步濾波后“看到”的信息。現(xiàn)在將展平層的 3136 元輸出呈現(xiàn)出來(lái)。呈現(xiàn)方式是:“0”~“9” 十個(gè)數(shù)字各取 100 個(gè)(共 1000 個(gè)),將對(duì)每一個(gè)樣本的輸出作為一行,得到一副 1000 x 3136 大小的圖像,根據(jù)數(shù)值用偽彩色呈現(xiàn)出來(lái)。如圖 4.6 。

      圖 4.6


      是否能從中看到 10 個(gè)條帶,每個(gè)條帶對(duì)應(yīng)同一個(gè)數(shù)字的 100 個(gè)樣本?再把兩個(gè)全連接層的輸出以同樣的方式顯示出來(lái),是兩個(gè) 1000 x 1000 的偽彩色圖。如圖 4.7 。


      圖 4.7


      經(jīng)過(guò)各卷積層、采樣層和全連接層,信息表示的抽象程度逐層提高。CNN 就這樣“認(rèn)出”了手寫(xiě)數(shù)字。多層的 CNN 逐層提高了“邏輯深度”,這就是 “Deep Learning” 的含義。

      最后把代碼附上。CNN 實(shí)現(xiàn)使用的是 keras 庫(kù)。數(shù)據(jù)集來(lái)自 kaggle :這里。


      import pandas as pd

      from keras.models import Sequential

      from keras.layers import Dense, Flatten, Reshape, AveragePooling2D, Convolution2D, Activation

      from keras.utils.np_utils import to_categorical

      from keras.utils.visualize_util import plot

      from sklearn.model_selection import train_test_split

      from sklearn.metrics import classification_report, accuracy_score, confusion_matrix

      from keras.callbacks import Callback

      from keras.optimizers import SGD


      class LossHistory(Callback):

      def __init__(self):

      Callback.__init__(self)

      self.losses = []

      self.accuracies = []


      def on_train_begin(self, logs=None):

      pass


      def on_batch_end(self, batch, logs=None):

      self.losses.append(logs.get('loss'))

      self.accuracies.append(logs.get('acc'))


      history = LossHistory()

      data = pd.read_csv('train.csv')data = data.sample(n=10000, replace=False)digits = data[data.columns.values[1:]].valueslabels = data.label.values

      train_digits, test_digits, train_labels, test_labels = train_test_split(digits, labels)

      train_labels_one_hot = to_categorical(train_labels)test_labels_one_hot = to_categorical(test_labels)

      model = Sequential()model.add(Reshape(target_shape=(1, 28, 28), input_shape=(784,)))model.add(

      Convolution2D(nb_filter=32, nb_row=3, nb_col=3, dim_ordering='th', border_mode='same', bias=False, init='uniform'))model.add(AveragePooling2D(pool_size=(2, 2), dim_ordering='th'))model.add(

      Convolution2D(nb_filter=64, nb_row=3, nb_col=3, dim_ordering='th', border_mode='same', bias=False, init='uniform'))model.add(AveragePooling2D(pool_size=(2, 2), dim_ordering='th'))model.add(Flatten())model.add(Dense(output_dim=1000, activation='sigmoid'))model.add(Dense(output_dim=1000, activation='sigmoid'))model.add(Dense(output_dim=10, activation='linear'))

      with open('digits_model.json', 'w') as f:

      f.write(model.to_json())

      plot(model, to_file='digits_model.png', show_shapes=True)

      opt = SGD(lr=0.01, decay=1e-6, momentum=0.9, nesterov=True)model.compile(loss='mse', optimizer=opt, metrics=['accuracy'])

      model.fit(train_digits, train_labels_one_hot, batch_size=32, nb_epoch=10, callbacks=[history])

      model.save_weights('digits_model_weights.hdf5')

      predict_labels = model.predict_classes(test_digits)

      print(classification_report(test_labels, predict_labels))print(accuracy_score(test_labels, predict_labels))print(confusion_matrix(test_labels, predict_labels))



      用 lena 圖訓(xùn)練 sobel 算子的代碼:


      from keras.models import Sequentialfrom keras.layers import Convolution2Dfrom keras.callbacks import Callbackfrom PIL import Imageimport numpy as npfrom scipy.ndimage.filters import convolve


      class LossHistory(Callback):

      def __init__(self):

      Callback.__init__(self)

      self.losses = []


      def on_train_begin(self, logs=None):

      pass


      def on_batch_end(self, batch, logs=None):

      self.losses.append(logs.get('loss'))


      lena = np.array(Image.open('lena.png').convert('L'))lena_sobel = np.zeros(lena.shape)

      # sobel 算子。sobel = np.array([

      [-1, 0, 1],

      [-2, 0, 2],

      [-1, 0, 1]])

      # 計(jì)算卷積:用 sobel 算子濾波。結(jié)果保存在 lena_sobel 中。convolve(input=lena, output=lena_sobel, weights=sobel, mode='constant', cval=1.0)

      # 將像素值調(diào)整到 [0,255] 區(qū)間并保存 sobel 算子濾波后的 lena 圖。lena_tmp = np.uint8((lena_sobel - lena_sobel.min()) * 255 / (lena_sobel.max() - lena_sobel.min()))Image.fromarray(lena_tmp).save('lena_sobel.png')

      # 將原始 lena 圖和 sobel 濾波 lena 圖轉(zhuǎn)換成 (1, 1, width, height) 尺寸。第一個(gè) 1 表示訓(xùn)練集只有一個(gè)樣本。第二個(gè) 1 表示樣本只有一個(gè) channel 。X = lena.reshape((1, 1) + lena.shape)Y = lena_sobel.reshape((1, 1) + lena_sobel.shape)

      # 建一個(gè)神經(jīng)網(wǎng)絡(luò)模型。model = Sequential()

      # 只添加一個(gè)卷積層。卷積層只有一個(gè)濾波器。濾波器尺寸 3x3 。輸入維度順序是 'th' 表示 (channel, width, height) 。輸入尺寸是 (channel, width, height) 。不要偏執(zhí)置。model.add(

      Convolution2D(nb_filter=1, nb_row=3, nb_col=3, dim_ordering='th', input_shape=X.shape[1:], border_mode='same',

      bias=False, init='uniform'))

      # 代價(jià)函數(shù)取 mse 。優(yōu)化算法取 rmsprop 。model.compile(loss='mse', optimizer='rmsprop', metrics=['accuracy'])

      history = LossHistory()

      # 訓(xùn)練 10 輪,每輪保存一下當(dāng)前網(wǎng)絡(luò)輸出圖像。for i in np.arange(0, 10):

      lena_tmp = model.predict(X).reshape(lena.shape)

      lena_tmp = np.uint8((lena_tmp - lena_tmp.min()) * 255 / (lena_tmp.max() - lena_tmp.min()))

      Image.fromarray(lena_tmp).save('lena_sobel_stage_{:d}.png'.format(i))

      print('lena_sobel_stage_{:d}.png saved'.format(i))


      model.fit(X, Y, batch_size=1, nb_epoch=200, verbose=1, callbacks=[history])

      print('Epoch {:d}'.format(i + 1))

      lena_tmp = model.predict(X).reshape(lena.shape)lena_tmp = np.uint8((lena_tmp - lena_tmp.min()) * 255 / (lena_tmp.max() - lena_tmp.min()))Image.fromarray(lena_tmp).save('lena_sobel_stage_final.png')










      雷課:

             讓教育更有質(zhì)量,

             讓教育更有想象!




        本站是提供個(gè)人知識(shí)管理的網(wǎng)絡(luò)存儲(chǔ)空間,所有內(nèi)容均由用戶(hù)發(fā)布,不代表本站觀點(diǎn)。請(qǐng)注意甄別內(nèi)容中的聯(lián)系方式、誘導(dǎo)購(gòu)買(mǎi)等信息,謹(jǐn)防詐騙。如發(fā)現(xiàn)有害或侵權(quán)內(nèi)容,請(qǐng)點(diǎn)擊一鍵舉報(bào)。
        轉(zhuǎn)藏 分享 獻(xiàn)花(0

        0條評(píng)論

        發(fā)表

        請(qǐng)遵守用戶(hù) 評(píng)論公約

        類(lèi)似文章 更多