卷积神经网络(cnn)的体系结构
?
譯者注
內容有部分增加與補充,閱讀原文請點擊這里
?
原作者的文章其實更利于讀者對卷積本身的理解,但是實際上作者對卷積的現實意義的理解并沒有解釋的十分清楚,甚至可能不利于堵著的理解,也正因為如此我在翻譯過程中可能對原文進行了比較大的改動,希望這對你有幫助.
?
實際上上卷積神經網絡是來自神經學的研究,其計算過程實際上模擬了視覺神經系統的運算過程.這一部分內容其翻閱其他文章.
?
TensorFlow中該部分的內容請參考我的博客:卷積函數?和?池化函數
?
介紹
我曾經很懊悔過去一段時間沒時間真正去理解深度學習。 過去一段時間通過話題上的研究論文和文章,感覺這是一個非常復雜的話題。 我試著理解神經網絡及其各種類型,但它似乎很困難。
然后有一天,我決定要一步一個腳印,從頭構建基礎。 我決定要打破這些技術應用的步驟,做手工(計算)的步驟,直到我理解它們是如何工作的。 是時候采取如此大的努力了,但收獲同樣是驚人的。
現在,我不僅可以了解深度學習的范圍,甚至我想出更好的方法,畢竟我的基礎已經達到了。?
今天,我要與你分享我的學習心得。 我將向您展示如何理解卷積神經網絡。 我將帶您親歷的我曾經的旅程,并通過這使你深刻的理解cnn是如何工作的。
在這篇文章中我將討論卷積神經網絡背后的架構,這是為了解決圖像識別和分類問題。
我假設你對經網絡是如何工作的有一個基本的了解神。 如果你不確定你的知識儲備,那么?這篇文章?對你會有幫助(英文原文)。
?
1 機器如何“看到”一個圖像?
人類的大腦是一個非常強大的機器。 我們看到每秒鐘(捕捉)多個圖像并處理處理它們,卻又從未意識到這其中其實已經進行了極其復雜的運算,而對于機器而言顯然沒有這么容易。 其中圖像處理的第一步是理解:如何表示一幅圖像使得機器也可以讀圖
其表示方法為,每一個圖像點(像素)的以矩陣的形式進行存儲。 如果你改變訂單或顏色的像素,圖像也會改變。 讓我們舉一個例子。 讓我們說,你想要存儲和讀取一幅寫有數字4的圖片。
機器會打“閱讀”圖像像素的矩陣和存儲每個像素的顏色代碼代表的位置。 在下面的描述中,1號是白色的,256是最黑暗的陰影綠色(實際上應該是黑色,但是為了便于表示每個像素的編號都以一種顏色,綠色的深淺程度進行表示)。
?
?
一旦確定了圖像的存儲格式,下一個挑戰是我們的神經網絡理解的安排和模式。
?
2? 我們如何幫助一個神經網絡來識別圖像?
一個號碼是由像素排列的不同組合表示。
?
?
首先,假設我們嘗試使用一個傳統的完全連接網絡(全連接神經網絡:fully connected network 譯者注)來識別它嗎,效果會怎樣呢?
完全連接網絡將這張照片作為數組通過壓縮和考慮像素值作為特征來預測數字圖像。 結果如下:
這是一個表示數字4。 我們已經完全失去了像素的空間排列,其結果好像是人類無法理解的。
而實際上我們應該做些什么呢? 我們應該做的是從圖像中提取特征,并保存其空間分布,這樣才算是使機器學會了“看懂”圖像。那么我們到底應該怎么做呢?或許下面的案例可以幫助我們理解機器“看懂”圖像的方法。’
?
案例1:
這里我們使用了一個權重乘以最初的像素值。
?
它為肉眼識別變得容易,這是一個4。 但再次發送這張照片到完全連接網絡,其就會變一維數組。 這種方法無法保存圖像的空間排列。
看來這種方式并不能幫助機器學習“看懂”圖像
?
案例2:
通過上面的案例我們可以看到,一維化的圖像完全破壞了它的空間排列。我們需要設計一種方法,將圖像發送到一個網絡,而不需要將圖像拉平,并保留其空間布局。
讓我們嘗試一次獲取圖像的兩個像素值,而不是只計算一個。這將為網絡提供一個很好的視角來了解相鄰的兩個像素是怎樣的。現在我們每次取兩個像素,同樣的我們也要取兩個權重值來進行計算。
?
?
我希望你們注意到,圖像現在從4列排列開始變成了一個3列排列。因為我們每次移動兩個像素(像素在每個移動中得到共享),所有圖像變得更小了。另外,要意識到的一個重要事實是,,因此這里只考慮水平排列,我們要連續使用兩個連續的水平像素,而當我們考慮垂直元素時,我們將會使用兩個在垂直方向上連續的權值(譯者加)。
這是一種從圖像中提取特征的方法。 我們觀察圖像處理后的不同部分,其中右邊不像原來那樣清晰了。 這是由兩個原因造成的:
現在我們有兩個問題,我們有兩個解決方案來解決這些問題。
?
案例3:
遇到的問題是圖像的左和右角落正在通過的權重只有一次。 解決方案使左右邊緣像素和圖片中的其它像素一樣能夠與權重進行多次相乘。
我們有一個簡單的解決方案來解決這個問題: 圖像兩邊加上數值全部為零的列。
如圖所示,通過添加數值為零的列,邊緣信息得以保留,圖像的大小也隨之變大。 當我們不想要圖像大小減小時,我們可以使用這種方法.
同樣的我們也可以通過補零來使輸入輸出的圖像大小一致,這種兩種不同的卷積方式,在TensorFlow中都可以通過簡單的參數控制來實現,輸入輸出圖像的大小計算方法,在下文中會提及(譯者加)
?
案例4:
我們試圖解決的問題是,一個更小的重量值右邊角落里減少像素值從而使我們的神經網絡難以真的讀讀圖。 我們能做的是使用多個權重值并在計算后把它們放在一起。
權重(0.3)給了我們一個輸出的形式
人后權重(0.1,5)會給我們另外一個輸出的形式
這兩個圖像的組合版本將給我們一個非常清晰的圖片。因此,我們所做的是簡單地使用多個權重,而不是只使用一個權重來嘗試保留關于圖像的更多信息。而本例子中的最終輸出將是上述兩個圖像的組合版本。
?
例5:
直到現在我們使用的權重一起處理水平像素。 但在大多數情況下,我們需要在水平和垂直方向保留圖像的空間排列。 我們可以用權重的二維矩陣在水平和垂直方向與像素同時相乘。 同時,請記住,因為我們兩個水平和垂直運動的權重,輸出是一個像素在水平和垂直方向維度都更低的圖像,也就是輸出的圖像比輸入圖像小了。?
特別感謝杰里米·霍華德的鼓舞我創建這些視覺效果。
上面的案例中,我們到底做了什么呢?
上面我們所做的是,試圖從圖像中提取特征,并保留圖像的空間排列。 理解圖像的極其重要一點就是的了解像素排列。 而,上面我們所做的其實就是卷積神經網絡所做的事情。 我們可以把輸入圖像用我們定義的權值矩陣(卷積核)進行卷積操作,從而獲取我們想要的結果。
這種方法有另一個好處是,它減少了參數的數量
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范數池化。
?
輸出尺寸
上面的內容可能會使你混淆每一層的輸出尺寸。 所以我決定使用下面的內容讓你能夠識別輸出尺寸。 在卷積層中,有三個關鍵控制著輸出尺寸的大小
我們可以應用一個簡單的公式來計算輸出尺寸。 輸出圖像的空間大小可以計算(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現在可以看到由各種卷積和匯聚層。 讓我們來看看網絡的樣子。
- 我們首先通過一個輸入圖像卷積層。 獲得復雜的輸出作為一個激活地圖。 卷積過濾器應用于層從輸入圖像中提取相關特征進一步通過。
- 每個過濾器應當給予不同的特性來幫助預測正確的類。 以防我們需要保留圖像的大小,我們使用相同的填充(補零),其他明智有效填充,因為它有助于減少使用的數量特征。
- 池層然后進一步減少參數的數量
- 幾個卷積和池層添加之前的預測。 卷積層幫助提取特征。 網絡中我們更深更具體的特性提取相比淺網絡特征提取更通用。
- CNN如前所述的輸出層是一個完全連接層,其他層的輸入在這里被變成一維數據,發送輸出轉換成類的數量,所期望的網絡。
- 然后生成的輸出通過輸出層和輸出層的誤差比較。 其中定義的一個損失函數是完全連接輸出層計算均方損失。 然后計算誤差的梯度。
- 錯誤然后backpropagated更新過濾器(權重)和偏差值。
- 一個訓練周期完成在一個向前和向后傳遞。
?
5? ?使用在KERAS CNN分類圖像
讓我們嘗試以一個例子,我們輸入一些貓和狗的圖片,我們試著對這些圖像進行分類成各自的動物種類。 這是一個典型的圖像識別和分類的問題。 這臺機器需要做什么是需要看到圖片和理解的各種特性是否一只貓或狗。這些特性可能是提取邊緣,或提取出貓的胡須等等。卷積層的作用就是提取這些特征。 數據集可以點擊這里
這些都是一些圖像數據集的例子。
???
我們將首先需要調整這些圖片讓他們都在相同的形狀。 這是我們通常需要在處理圖像時,由于在捕捉圖像,是不可能捕獲所有相同大小的圖像。
簡單的你的理解我剛剛使用一個卷積層和一個池層,一般不會發生當我們試圖做出預測。
?
# import各種包import os import numpy as np import pandas as pd import scipy import sklearn import keras from keras.models import Sequential import cv2 from skimage import io %matplotlib inline# 定義文件路徑cat=os.listdir("/mnt/hdd/datasets/dogs_cats/train/cat") dog=os.listdir("/mnt/hdd/datasets/dogs_cats/train/dog") filepath="/mnt/hdd/datasets/dogs_cats/train/cat/" filepath2="/mnt/hdd/datasets/dogs_cats/train/dog/"# 加載圖片images=[] label = [] for i in cat: image = scipy.misc.imread(filepath+i) images.append(image) label.append(0) #for cat imagesfor i in dog: image = scipy.misc.imread(filepath2+i) images.append(image) label.append(1) #for dog images# 確定所有圖像的大小for i in range(0,23000): images[i]=cv2.resize(images[i],(300,300))# 將圖像轉換為數組images=np.array(images) label=np.array(label)# 定義超參數filters=10 filtersize=(5,5)epochs =5 batchsize=128input_shape=(300,300,3)# 將目標變量轉換為所需的大小from keras.utils.np_utils import to_categorical label = to_categorical(label)# 定義模型model = Sequential()model.add(keras.layers.InputLayer(input_shape=input_shape))model.add(keras.layers.convolutional.Conv2D(filters, filtersize, strides=(1, 1), padding='valid', data_format="channels_last", activation='relu')) model.add(keras.layers.MaxPooling2D(pool_size=(2, 2))) model.add(keras.layers.Flatten())model.add(keras.layers.Dense(units=2, input_dim=50,activation='softmax'))model.compile(loss='categorical_crossentropy', optimizer='adam', metrics=['accuracy']) model.fit(images, label, epochs=epochs, batch_size=batchsize,validation_split=0.3)model.summary()?
在這個模型中,我只使用了一個卷積和池層,可訓練的參數是219,801。如果我在這種情況下使用了一個MLP,我將會有多少輸出結果呢?您可以通過添加更多的卷積和池層來進一步減少參數的數量。我們添加的更多的卷積層網絡結構和訓練將會更復雜,但是同樣的結果也會更好。
?
最后指出
我希望通過這篇文章能讓你們對卷積神經網絡有一個直觀的認識。我沒有深入研究CNN的復雜數學。如果你喜歡理解同樣的東西——請繼續收看,你會有更多的選擇。嘗試建立你自己的CNN網絡,了解它是如何運作的,并對圖像做出預測。請讓我知道您的發現和使用評論部分的方法。
總結
以上是生活随笔為你收集整理的卷积神经网络(cnn)的体系结构的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: Python ML环境搭建与学习资料推荐
- 下一篇: 5.2 TensorFlow:模型的加载