1. 程式人生 > >卷積神經網路——轉自譯智社

卷積神經網路——轉自譯智社

 文   | DISHASHREE GUPTA

翻譯 | FontTian

編輯 | strongnine

譯者注:

內容有部分增加與補充,可以閱讀原文,地址:

https://www.analyticsvidhya.com/blog/2017/06/architecture-of-convolutional-neural-networks-simplified-demystified/

原作者的文章其實更利於讀者對卷積本身的理解,但是實際上作者對卷積的現實意義的理解並沒有解釋的十分清楚,甚至可能不利於讀者的理解,也正因為如此我在翻譯過程中可能對原文部分內容進行了比較大的改動或增刪,希望這對你有幫助。

實際上卷積神經網路的靈感是來自神經學的研究,其計算過程實際上模擬了視覺神經系統的運算過程。這一部分內容請翻閱其他文章。

TensorFlow 中該部分的內容可以參考我的部落格:

卷積函式:

https://link.zhihu.com/?target=http%3A//blog.csdn.net/fontthrone/article/details/76652753

池化函式:

https://link.zhihu.com/?target=http%3A//blog.csdn.net/fontthrone/article/details/76652762

介紹

我曾經很懊悔過去一段時間沒時間真正去理解深度學習。 過去一段時間通過話題上的研究論文和文章,感覺這是一個非常複雜的話題。 我試著理解神經網路及其各種型別,但它似乎很困難。

然後有一天,我決定要一步一個腳印,從頭構建基礎。 我決定要打破這些技術應用的步驟,做手工(計算)的步驟,直到我理解它們是如何工作的。 是時候採取如此大的努力了,但收穫同樣是驚人的。

現在,我不僅可以瞭解深度學習的範圍,甚至我想出更好的方法,畢竟我的基礎已經達到了。

今天,我要與你分享我的學習心得。 我將向您展示如何理解卷積神經網路。我將帶您親歷的我曾經的旅程,並通過這使你深刻的理解 cnn 是如何工作的。

在這篇文章中我將討論卷積神經網路背後的架構,這是為了解決影象識別和分類問題。

本文假設你對經網路是如何工作的有一個基本的瞭解。 如果你不確定你的知識儲備足夠閱讀這篇文章,那麼或許另外一篇文章對你會有幫助。

英文原文:

https://link.zhihu.com/?target=https%3A//www.analyticsvidhya.com/blog/2017/05/neural-network-from-scratch-in-python-and-r/

1. 機器如何「看到」一個影象?

人類的大腦是一個非常強大的機器。 我們看到每秒鐘(捕捉)多個影象並處理處理它們,卻又從未意識到這其中其實已經進行了極其複雜的運算,而對於機器而言顯然沒有這麼容易。 其中影象處理的第一步是理解:如何表示一幅影象使得機器也可以讀圖。

其表示方法為,每一個影象點(畫素)的以矩陣的形式進行儲存。 如果你改變訂單或顏色的畫素,影象也會改變。 讓我們舉一個例子。 讓我們說,你想要儲存和讀取一幅寫有數字 4 的圖片。

機器會打「閱讀」影象畫素的矩陣和儲存每個畫素的顏色程式碼代表的位置。 在下面的描述中,1 號是白色的,256 是最黑暗的陰影綠色(實際上應該是黑色,但是為了便於表示每個畫素的編號都以一種顏色,綠色的深淺程度進行表示)。

圖片的數字化展示

一旦確定了影象的儲存格式,下一個挑戰是我們的神經網路理解的安排和模式。

2. 我們如何幫助一個神經網路來識別影象?

一個號碼是由畫素排列的不同組合表示。

首先,假設我們嘗試使用一個傳統的完全連線網路來識別它嗎,效果會怎樣呢?

完全連線網路:全連線神經網路, fully connected network. 

完全連線網路將這張照片作為陣列通過壓縮和考慮畫素值作為特徵來預測數字影象。 結果如下:

這是一個表示數字 4。 我們已經完全失去了畫素的空間排列,其結果好像是人類無法理解的。

而實際上我們應該做些什麼呢?我們應該做的是從影象中提取特徵,並儲存其空間分佈,這樣才算是使機器學會了「看懂」影象。那麼我們到底應該怎麼做呢?或許下面的案例可以幫助我們理解機器「看懂」影象的方法。

案例 1:

這裡我們使用了一個權重乘以最初的畫素值。

它為肉眼識別變得容易,這是一個 4。 但再次傳送這張照片到完全連線網路,其就會變一維陣列。 這種方法無法儲存影象的空間排列

看來這種方式並不能幫助機器學習「看懂」影象。

案例 2:

通過上面的案例我們可以看到,一維化的影象完全破壞了它的空間排列。我們需要設計一種方法,將影象傳送到一個網路,而不需要將影象拉平,並保留其空間佈局。

讓我們嘗試一次獲取影象的兩個畫素值,而不是隻計算一個。這將為網路提供一個很好的視角來了解相鄰的兩個畫素是怎樣的。現在我們每次取兩個畫素,同樣的我們也要取兩個權重值來進行計算。

我希望你們注意到,影象現在從 4 列排列開始變成了一個 3 列排列。因為我們每次移動兩個畫素(畫素在每個移動中得到共享),所有影象變得更小了。另外,要意識到的一個重要事實是,因此這裡只考慮水平排列,我們要連續使用兩個連續的水平畫素,而當我們考慮垂直元素時,我們將會使用兩個在垂直方向上連續的權值(譯者加)。

這是一種從影象中提取特徵的方法。 我們觀察影象處理後的不同部分,其中右邊不像原來那樣清晰了。 這是由兩個原因造成的:

  1. 左邊和右邊的角落影象畫素只乘了權重一次。

  2. 左側部分顏色仍然很深,因為權重值較高,而右側部分顏色由於較低的權重而略有下降

現在我們有兩個問題,我們有兩個解決方案來解決這些問題。

案例 3:

遇到的問題是影象的左和右角落正在通過的權重只有一次。 解決方案使左右邊緣畫素和圖片中的其它畫素一樣能夠與權重進行多次相乘。

我們有一個簡單的解決方案來解決這個問題: 影象兩邊加上數值全部為零的列

如圖所示,通過新增數值為零的列,邊緣資訊得以保留,影象的大小也隨之變大。 當我們不想要影象大小減小時,我們可以使用上面這種方法。

同樣的我們也可以通過在圖片周圍提前增加數值為零的列來使輸入輸出的影象大小一致,這種兩種不同的卷積方式,在 TensorFlow 中都可以通過簡單的引數控制來實現,輸入輸出影象的大小計算方法,在下文中會提及。(譯者加)

案例 4:

我們在這裡要解決的問題是,右側角落的較小權重值會降低畫素值,從而使我們難以識別。我們能做的是,我們在一個回合中採用多個重量值並將它們組合在一起。

權重 (1, 0.3) 給了我們一個輸出的形式:

然後權重 (0.1, 5) 會給我們另外一個輸出的形式:

這兩個影象的組合版本將給我們一個非常清晰的圖片。因此,我們所做的是簡單地使用多個權重,而不是隻使用一個權重來嘗試保留關於影象的更多資訊。而本例子中的最終輸出將是上述兩個影象的組合版本。

案例 5:

直到現在我們使用的權重一起處理水平畫素。 但在大多數情況下,我們需要在水平和垂直方向保留影象的空間排列。 我們可以用權重的二維矩陣在水平和垂直方向與畫素同時相乘。 同時,請記住,因為我們兩個水平和垂直運動的權重,輸出是一個畫素在水平和垂直方向維度都更低的影象,也就是輸出的影象比輸入影象小了。

特別感謝傑里米·霍華德的鼓舞我建立這些視覺效果。

上面的案例中,我們到底做了什麼呢?

上面我們所做的是,試圖從影象中提取特徵,並保留影象的空間排列。 理解影象的極其重要一點就是的瞭解畫素排列。 而上面我們所做的其實就是卷積神經網路所做的事情。 我們可以把輸入影象用我們定義的權值矩陣(卷積核)進行卷積操作,從而獲取我們想要的結果。

這種方法有另一個好處是,它減少了引數的數量。

3. 定義一個卷積神經網路

我們需要三個基本元件來定義一個基本卷積網路。

  1. 卷積的層

  2. 池層(可選)

  3. 輸出層

讓我們看看這些詳細:

3.1 卷積層

在這一層,就是我們看到的在案例五即之後之後的例子。 假設我們有一個影象的大小 6 * 6。 我們定義了一個權重矩陣中提取影象的某些特性:

我們已經初始化了體重 3 * 3 矩陣。 這個權重應當對每個畫素都進行運算,給一個卷積的輸出:

6 * 6 的影象現在轉換成一個 4 * 4 的形象。 把權重矩陣像畫筆畫一堵牆。想象一下重量矩陣就像油漆刷畫牆一樣。畫筆首先水平地畫出牆壁中的一行,然後向下,在水平地畫下第二行,然後向下畫出第三行,直到整面牆壁都被粉刷完畢。而當權重矩陣沿著影象移動時,畫素值再次被使用。 再次當權重矩陣沿著影象畫素才一次被使用。 這個特性允許在卷積神經網路中進行引數共享。

讓我們看看真實的效果。

權重矩陣的行為像一個過濾器的影象從原始影象中提取特定的資訊矩陣。重量組合可能是提取邊緣,而另一個可能是量化一個特定的顏色,而另一個可能只是提取模糊不需要的噪聲。通過不同的卷積核操作,我們通過計算機實現了對影象不同特徵的提取或者其他操作(譯者加)

權重是這樣學習的:最小化類似於一個 MLP 的損失函式。因此,從原來的影象中提取出一些特徵來幫助網路進行正確的預測。當我們有多個卷積層時,初始層會提取更多的泛型特徵,而隨著網路的深入,權重矩陣提取的特徵變得越來越複雜,同時也更適合於影象的識別與處理。

步長和填充(補零)的概念

在我們之前的案例中,過濾器或權重矩陣,在整個影象移動的一次只移動 一個畫素。 其移動的畫素數量,我們稱之為步長,下圖是步長為 2 的例子:

正如你所看到的影象大小的繼續減少當我們增加步長的值。 而在影象中增加為零的維度則幫助我們解決了這個問題。 如下:

我們可以看到影象的初始形狀是如何保留在我們用零填充影象。 這就是所謂的 相同的填充 由於輸出影象具有相同的大小作為輸入。

通過這種方式,我們保留了更多的來自影象邊界的資訊,並保留了圖片的大小。

多個過濾器和啟用對映

要記住的一件事是,深度尺寸的權重和輸入影象的深度尺寸一樣。 權重延伸到整個輸入影象的深度。 因此,與單個權重卷積矩陣與一個輸出卷積結果的深度維度。 同時因為在大多數情況下我們有相同的多個卷積核一起應用,那麼我們將會獲取的影象數量也會隨著卷積核數量的增加而增加。

每個過濾器的輸出是堆疊在一起形成的深度尺寸卷積影象。 假設我們有一個輸入影象的大小32 * 32 * 3。 我們應用 10 個大小為 5 * 5 * 3 的卷積核對其進行卷積(方式為不填充數值為 0 的維度)。那麼卷積層的輸出會維度將會是 28 * 28 * 10。

你可以想象這是:

3.2 池化層

有時候圖片太大,我們需要減少可訓練的引數。這時候我們可以在不同的卷積層之間新增池層。 池化的唯一目的是減少影象的空間大小。 池化是獨立在每個深度尺寸,因此影象的深度保持不變。 最常見的池化層一般採用最大池化(另外一種方式為平均池化)。

同時池化層也強化了神經網路的魯棒性(抗干擾性),使得目標影象在影象位置中的輕微形變對神經網路最終預測的影響變小(譯者加)

這裡我們已經大步,而池大小也是 2。 最大池化操作應用於每個深度維度的卷積的輸出。 正如你所看到的,4 * 4 卷積後輸出已成為 2 * 2 馬克斯池操作。

讓我們看看最大池化的實際應用。

正如你所看到的我已經複雜的影象,應用最大池化。 最大池化後的影象仍然保留資訊,這是一個汽車在一條街上。 如果你仔細看,其尺寸影象已經減半。 這可以在很大程度上減少運算。

類似的其他形式的池化比如平均池化或 L2 範數池化。

輸出尺寸

上面的內容可能會使你混淆每一層的輸出尺寸。 所以我決定使用下面的內容讓你能夠識別輸出尺寸。 在卷積層中,有三個關鍵控制著輸出尺寸的大小:

  1. 過濾器的數量 —— 輸出音量的深度就等於濾波器應用的數量。 每個濾波器(卷積核)可以輸出一個圖片,卷積核增加,輸出圖片的數量增加;

  2. 步長 —— 控制著卷積核向下移動的畫素值。 高步值長時我們跨過的畫素值,因此產生較小的輸出量;

  3. 補零 —— 這有助於我們保持輸入影象的大小。 如果只在原始影象周圍新增一個補零的層數,並且步長為一,那麼輸出將保留原始影象的大小。

我們可以應用一個簡單的公式來計算輸出尺寸。 輸出影象的空間大小可以計算 (W - F + 2 p / S) +  1。 這裡,W 是輸入圖片大小,F 是卷積核的大小,P 是填充應用的數量和 S 是步長的數量。 假設我們有一個輸入影象的大小 32 * 32 * 3,我們應用 10 過濾器的大小 3 * 3 * 3,與單步和補零。

W = 32,F = 3,P = 0 和 S = 1。 輸出深度等於過濾器應用的數量即 10。

輸出音量的大小將 ( 32 - 3 + 0 ) / 1 + 1 = 30。 因此,輸出音量將 30 * 30 * 10。

3.3 輸出層

以影象識別為例,多層的卷積和池化之後,我們需要輸出一個類別的形式。 卷積和池化層只是從原始影象中提取了特徵,然而想要生成最終的輸出,我們需要在卷積層之後加入一個全連線層,並使全連線層的輸出等於我們的實際的影象分類的類別。對於卷積層最後的影象我們只需要輸出其是否屬於一個特定的類。 輸出層有一個像分類交叉熵那樣的損失函式,來計算預測中的誤差。一旦分類完成,反向傳播就開始更新權重和偏差的錯誤和減少損失。

4. 把它們放在一起,整個網路如何看起來像什麼?

CNN 現在可以看到由各種卷積和池化層。 讓我們來看看網路的樣子。

  1. 我們首先通過一個輸入影象卷積層。 獲得複雜的輸出作為一個啟用地圖。 卷積過濾器應用於層從輸入影象中提取相關特徵進一步通過;

  2. 每個過濾器應當給予不同的特性來幫助預測正確的類。 以防我們需要保留影象的大小,我們使用相同的填充(補零),其他明智有效填充,因為它有助於減少使用的數量特徵

  3. 池層然後進一步減少引數的數量

  4. 幾個卷積和池層新增之前的預測。 卷積層幫助提取特徵。 網路中我們更深更具體的特性提取相比淺網路特徵提取更通用;

  5. CNN 如前所述的輸出層是一個完全連線層,其他層的輸入在這裡被變成一維資料,傳送輸出轉換成類的數量,所期望的網路;

  6. 然後生成的輸出通過輸出層和輸出層的誤差比較。 其中定義的一個損失函式是完全連線輸出層計算均方損失。 然後計算誤差的梯度;

  7. 錯誤然後 backpropagated 更新過濾器(權重)和偏差值

  8. 一個訓練週期完成在一個向前和向後傳遞

5. 在 KERAS 中使用 CNN 分類影象

讓我們嘗試以一個例子,我們輸入一些貓和狗的圖片,我們試著對這些影象進行分類成各自的動物種類。 這是一個典型的影象識別和分類的問題。 這臺機器需要做什麼是看到圖片並理解的各種特性,從而判斷其是否一隻貓或狗

下面是一些影象資料集的例子。

我們首先需要調整這些影象的大小以使它們全部處於相同的形狀。這是我們在處理影象時通常需要做的事情,因為在捕獲影象時,不可能捕獲相同大小的所有影象。

為了簡化您的理解,我剛剛使用了單個卷積層和單個池化層來進行講解,而通常我們是不會定義這種簡單的神經網路結構的。下面程式碼示例中使用的資料集可以從原文提供的地址下載:

https://link.zhihu.com/?target=http%3A//files.fast.ai/data/dogscats.zip

在這個模型中,我只使用了一個卷積層和池層,可訓練的引數是 219, 801。如果我在這種情況下使用了一個 MLP,我將會有多少輸出結果呢?您可以通過新增更多的卷積和池層來進一步減少引數的數量。我們新增的更多的卷積層網路結構和訓練將會更復雜,但是同樣的結果也會更好。

最後指出

我希望通過這篇文章能讓你們對卷積神經網路有一個直觀的認識。我沒有深入研究 CNN 的複雜數學。如果你喜歡理解同樣的東西 —— 請繼續收看,你會有更多的選擇。嘗試建立你自己的 CNN 網路,瞭解它是如何運作的,並對影象做出預測。你也可以請使用評論部分告訴我您的發現和方法(譯者補充,你也可以點選閱讀全文在知乎上給我留言)。

↓ 點選全文檢視完整程式碼和連結,還可以給我留言哦!

閱讀原文