Table of Contents
Convolutional Neural network 卷積神經網路(part1)
今日的課程來自於: https://youtu.be/5BJDJd-dzzg (0-33分)
為什麼要使用CNN 於影像處理?
CNN vs DNN
我們當然可以使用一般的neural network 來做影像處理,不一定要用CNN。但是我們會遇到一個問題,每一個就是在處理影像辨別時,使用fully connetcted 的 feedforward network來做圖像處裡時,往往需要太多數據。
舉例來說,一張100*100的彩色圖片,他的辨別率才100*100,將他拉成一個vector,他總共有100*100*3(彩色需要三個value)=三萬維了。如果input 是三萬為,假設hidden layer 有1000個neuron,那僅僅是第一層hidden layer的參數就已經有30000*1000個了,這樣太多了。
所以CNN做得事情其實是,用簡化這個neural network的架構,我們根據自己的知識和對圖像處裡的理解,一開始就把某些實際上用不到的參數給過濾掉,我們一開始就使用較少的參數來處理,所以CNN其實是比一般的DNN還要簡單的
雖然CNN看起來比較複雜,但事實上他的模型比DNN還要簡單,我們就是用prior knowledge,去把原來fully conected 的layer 裡面的一些參數拿掉,就變成CNN
Why can we discard some parameters?
為什麼可以減少一些參數呢? 為什麼可以減少參數還可以做圖像處裡?
下面有三點對影像處裡的觀察:
1. Some pattens are much smaller than the whole image
在影像處理中,如果在network的第一層hidden layer裡,那些neuron要做的就是偵測有沒有一種特定的patten出現。所以並不需要看整張image,只需要看這張image 的一小部分,就可以解決這件事情了
舉例來說,假設現在我們有一張鳥的圖片,那第一層的hidden layer的某一個neuron的工作是,偵測有沒有鳥嘴。其實不需要看整張圖片,只需要給neuron看重點就可以了。每一個neuron其實只要連接到一個小塊的區域就好,它不需要連接到整張完整的圖,因此也對應更少的參數
2. The same patterns appear in different regions
同樣的patten,可能會出現在image的不同部位,但是他們有同樣的形狀,因此可以用同樣的neuron,同樣的參數,被同一個detector檢測出來。
舉例來說,圖片中可能有一個處於圖左上角與中間的鳥嘴,這時不需要訓練兩個不同的detector去專門偵測左上角有沒有鳥嘴和中間有沒有鳥嘴,我們需要cost down(降低成本),所以我們可以要求這些功能幾乎一致的neuron共用一組參數,他們share同一組參數就可以減少參數的量
3. Subsampling the pixels will not change the object
我們可以對一張image 做subsampling( 二次抽樣),將image 抽掉奇數行、偶數列拿掉,變成原來的十分之一。這不會影響我們對圖片的理解,因此我們可以利用subsampling 這個概念把image 變小,從而減少需要用到的參數量
CNN的架構
整個CNN的架構是這樣的,收到一張圖片之後,重複 Concolution和max pooling (這兩個步驟可以進行多次,重複次數需要先決定),這個過程就是network的架構,就像network會有好幾層一樣。
之後要做的是Flatten(將矩陣拉直),在將flatten output丟到一般的Fully connected network,最終得到影像辨識的結果。
我們基於之前提到三個對影像處理的觀察:
- 偵測不需要整張image,只需要一部分
- 同樣的patten會出現在一張圖片的不同區域,可以使用同樣的參數
- 我們可以對整張image做subsampling
前面兩點的特性是用convolution 的layer來處理的,最後的特性是用max pooling 來處理
Convolution
假設現在我們network的input是一張6*6的image。圖片是黑白的,所以每個pixel只需要一個value來表示。而在convolution layer裡面,有一堆Filter,這裡的每一個Fliter,其實就等同於是Fully connected layer 裡的一個neuron
Property1
每一個Fliter 就是一個matrix ,這個matrix 裡面每一個element的值,就跟那些neuron的weight和bias一樣,是network的parameter,他們都是通過training data學出來的,而不是人去設計的
所以每個Fliter裡面的值是甚麼,要做什麼事情,都是自動學出來的,下圖中的filter是3*3的size,意味著他在偵測一個3*3的patten。當她偵測的時候,並不會去看整張image,他只看一個3*3裡的pixel,就可以判斷某一個patten有沒有出現,這就是考慮property 1 了
Property 2
這個filter是從image的左上角開始,做一個slide window,每次向右移動一個距離,這個距離就叫做stride,由你自己設定,每次filter停下來的是侯就跟對應的3*3matrix做一個內積。這裡設定stride=1 ,那麼我們的filter每次移動一格,到最右邊就從下一行最左邊重複進行上述操作,經過一整個convolution的process,最終得到下圖所示的4*4 matrix
觀察上圖的filter 1 ,它的斜對角是1,1,1,所以這個fliter的工作就是找出有沒有連續的從左上角到右下角的1,1,1出現在這個image裡面。 檢測到的結果已在上左圖用藍色標示出來,此時fliter得到的和積在左上和左下得到最大的值。這就是說,該fliter所要偵測的pattern出現在image的左上角和左下角
同一個pattern出現在image左上角的位置和左下角的位置,並不需要用到不同的filter,我們用filter1就可以偵測出來,這就考慮property 2
Feature map
在一個convolution的layer裡面,他會有一堆filter,每一個filter做完會得到一個4*4matrix,將所有的filter做完之後,就會得到很多個4*4matrix,將這些matrix合起來,就叫做Feature Map
CNN 對不同scale的相同pattern的處理上存在一定的困難,因為現在每一個filter size都是一樣的。這意味著,如果有同一個pattern,它有不同的size,但CNN並不夠自動處裡這個問題;DeepMind曾經發過一篇paper,上面提到當你input一張image的時候,他在CNN面前,再接到另一個network,這個network做的事情是,他會output一些scalar,告訴你這個image的裡面的那些位置要做旋轉or縮放,再丟到CNN裡面,這樣你其實會得到比較好的performance
Colorful image
剛剛的例子是黑白的image,所以你input的是一個matrix,如果今天是彩色的image就必須由RGB組成。所以彩色的image就是好幾個matrix疊再一起,是一個立方體,如果今天要處理彩色的image,要怎麼做呢?
這個時候你的filter 就不在是一個matrix了,他也會是一個立方體,如果你今天是RGB這三個顏色來表示一個pixel的話,那你的input就是6*6*3,你的filter 就是3*3*3,你的filter 的高就是3,你在做convolution的時候,就是把這個filter的9個值跟這個image裡面的9個值最內積,可以想像成filter的每一層都分別跟image的三層做內積,得到的也是一個三層的output,每一個filter同時就考慮了不同顏色所代表的channel
Convolution vs Fully Connected
filter 是特殊的 ”neuron”
convolution 跟 fully connected 有什麼關係。其實convolution就是一個neural network。
convolution這件事情,其實就是fully connected 的layer把一些weight拿掉而已,下圖的綠色方框標示出的feature map 的output ,其實就是hidden later 的 neuron的output ( 可以將矩陣拉直,沒有使用的weight 給零)
每個 “neuton” 只檢測 image的部分區域
比照fully connected 的neuron是必須連接到所有36個input上的,但是我們現在只用連接9 個input ,因為我們知道要detect一個patten,不用看整張image,看9個input pixel就夠了,所以當我們這麼做的時候,就用了比較少的參數
“neuton” 之間共享參數
在fully connected layer裡面,每一個neuron應該都有自己獨立的weight。但是當我們做這個convolution的時候,首先我們把每一個neuron前面連接的weight減少了,然後我們強迫某些neuron 要共享一組weight,雖然這兩個neuron連接到的pixel對象各不相同,但他們的weight都必須是一樣的,等於filter裡面的元素值,就叫做weight share。
當我們做這件事的時候,用的參數又比之前更少。
conclusion
因此我們可以這樣想,有這樣一些特殊的neuron,它們只連接著9條帶weight的線。當filter在image matrix上移動做convolution的時候,每次移動做的事情實際上是去檢測這個地方有沒有某一種pattern,對於Fully connected layer來說,它是對整張image做detection的,因此每次去檢
測image上不同地方有沒有pattern其實是不同的事情,所以這些neuron都必須連接到整張image的所有pixel上,並且不同neuron的連線上的weight都是相互獨立的。
那對於 convolution layer來說,首先它是對 image的一部分做 detection的,因此它的 neuron只需要連接到 image的部分 pixel上,對應連線所需要的 weight參數就會減少;其次由於是用同一個 filter去檢測不同位置的 pattern,所以這對 convolution layer來說,其實是同一件事情,因此不同的 neuron,雖然連接到的 pixel對象各不相同,但是在”做同一件事情”的前提下,也就是用同一個 filter的前提下,這些 neuron所使用的 weight參數都是相同的,通過這樣一張 weight share的方式,再次減少 network所需要用到的 weight參數
CNN的本質,就是減少參數的過程
Max pooling
operation of max pooling
相較於convolution,max pooling是比較簡單的,它就是做subsampling,根據filter 1,我們得到一個4*4的matrix,根據filter 2,你得到另外一個4*4的matrix,接下來,我們要做什麼事呢?
我們把output四個分為一組,每一組裡面通過選取平均值或最大值的方式,把原來4個value合成一個 value,這件事情相當於在image每相鄰的四塊區域內都挑出一塊來檢測,這種subsampling的方式就可以讓你的image縮小!
講到這裡你可能會有一個問題,如果取Maximum放到network裡面,不就沒法微分了嗎? max這個東西,感覺是沒有辦法對它微分的啊,其實是可以的,後面的章節會講到Maxout network,會告訴你怎麼用微分的方式來處理它
Convolution + Max pooling
做完一次convolution加一次max pooling,我們就把原來6*6的image,變成了一個2*2的image;至於這個2*2的image,它每一個pixel的深度,也就是每一個pixel用幾個value來表示,就取決於你有幾個filter。幾個filter 代表深度有幾維。
所以,這是一個新的比較小的image,它表示的是不同區域上提取到的特徵,實際上不同的filter檢測的是該image同一區域上的不同特徵屬性,所以每一層channel(通道)代表的是一種屬性,一塊區域有一種不同的屬性,就有一層不同的channel,對應的就會有一個不同的filter對其進行convolution操作。
這件事情可以重複很多次,可以把得到的這個比較小的image,再次進行convolution 和 max pooling ,得到更小的image ,以此類推
這裡有一個問題: 假設我第一個convolution有25個filter ,通過這些filter得到25個feature map ,然後repeat的時候第二個convolution也有25個filter,那麼做完之後是不是會得到25² 個feature map ?
其實不是這樣的,你這邊做完一次convolution,得到25個feature map 之後再做一次convolution,還是會得到25個feature map,因為convolution在考慮input的時候,是會考慮深度的,他並不是每一個channel分開考慮,而是一次考慮所有的channel,所以你 convolution這邊有多少個 filter,再次output就會有多少個 channel
因此你這邊有25個 channel,經過含有25個 filter 的 convolution之後 output還會是25個 channel,只是這邊的每一個 channel,他都是一個cubic,他的高有25個 value這麼高
Flatten
做完convolution 和 max pooling 之後,就是Flattne 和 Fully connected Feedforward 的部分
Flatten 的意思是,把左邊的feature map 拉直,然後丟進一個 Fully connected Feedforward network,然後就結束了。也就是說,我們之前通過CNN提出了image的feature,他相較於原先一整個image的vector,少了很大一部分的內容,因此需要的參數也大量的減少了,但最終,也還是要丟到一個Fully connected 的network中去做最後的分類工作
CNN in Keras
內容簡介
接下來就來講一下,如何用Keras來implement CNN,實際上在compile、training和fitting的部分,內容和DNN是一樣的。對CNN來說,唯一需要改變的是network structure,以及input的format
本來在DNN裡,input是一個由image拉直展開而成的vector,但現在如果是CNN的話,他會考慮input image的幾何空間的,所以不能直接input一個vector,而是imput一個tensor給他(tensor就是高維的vector),這裡你要給他一個三維的vector,一個image的長寬各式一維,如果是彩色的話,RGB就是第三維,所以你要assign一個三維的matrix,這個高維的matrix就叫做tensor
怎麼implement一個convolution的layer呢?
model12.add( Convolution2D (25,3,3, input_shape=(28,28,1)))
還是用model.add增加CNN的layer,將原先的Dense改成Convolution2D,參數25代表你有25個 filter,參數3,3代表你的filter都是3*3的matrix,此外你還需要告訴model,你input的image的shape是什麼樣的,假設我現在要做手寫數字識別,input就是28*28的image,又因為它的每一個pixel都只有單一顏色,因此input_shape的值就是(28,28,1),如果是RGB的話,1就要改成3
然後增加一層Max Pooling的layer
model12.add( Maxpooling2D(2,2))
這裡參數(2,2)指的是,我們把通過convolution得到的feature map,按照2*2的方式分割成一個個區域,每次選取最大的那個值,並將這些值組成一個新的比較小的image,作為subsampling的結果
過程描述
- 假設我們input是一個1*28*28的image
- 通過25個filter的convolution layer以後你得到的output,會有25個channel,又因為filter的size是3*3,因此如果不考慮image邊緣處的處理的話,得到的channel會是26*26的,因此通過第一個convolution得到25*26*26的cubic image(這裡把這張image想像成長寬為26,高為25的cubic)
- 接下來就是做Max pooling,把2*2的pixel分為一組,然後從裡面選一個最大的組成新的image,大小為25*13*13(cubic長寬各被砍掉一半)
- 再做一次convolution,假設這次選擇50個filter,每個filter size是3*3的話,output的channel就變成有50個,那13*13的image,通過3*3的filter,就會變成11*11,因此通過第二個convolution得到50*11*11的image(得到一個新的長寬為11,高為50的cubic)
- 再做一次Max Pooling,變成50*5*5
在第一個convolution裡面,每一個filter都有9個參數,它就是一個3*3的matrix;但是在第一個convolution layer裡面,雖然每一個filter都是3*3,但它其實不是3*3個參數,因為它的input是一個
25*13*13的cubic,這個cubic的channel有25個,所以要用同樣高度的cubic filter對它進行卷積,於是我們的filter實際上是一個25*3*3的cubic,所以這邊每個filter共有225個參數(225=3*3*25
通過兩次convolution和max pooling的組合,最終的image變成了50*5*5的size,然後使用Flatten將這個image拉直,變成一個1250維的vector,再把它丟到一個Fully Connected Feedforward network
裡面,network structure就搭建完成了
一個重要的問題
看到這裡,你可能會有一個疑惑,第一次convolution的input是25*13*13的cubic,且50個3*3的filter卷積後,得到的輸出時應該是50個cubic,且每個cubic的尺寸為25*11*11,那麼max pooling把長寬各砍掉一半後就是50層25*5*5的cubic,那flatten後不應該就是50*25*5*5嗎?
其實不是這樣的,在第一次做convolution的時候,我們是用25*3*3的cubic filter對25*13*13的cubic input進行卷積操作的,filter的每一層和input cubic中對應的每一層(也就是每一個channel),它們進行內積後,還要把cubic的25個channel的內積值進行求和,作為這個“neuron”的output,它是一個scalar,這個cubic filter對整個cubic input做完一遍卷積操作後,得到的是一層scalar,然後有50個cubic filter,對應著50層scalar,因此最終得到的output是一個50*11*11的cubic!
這裡的關鍵是filter和image都是cubic,每個cubic filter有25層高,它和同樣有25層高的cubic image做卷積,並不是單單把每個cubic對應的channel進行內積,還會把這些內積求和! ! !最終變為1層,因此兩個矩陣或者tensor做了卷積後,不管之前的維數如何,都會變為一個scalor! ,故如果有50個Filter,無論input是什麼樣子的,最終的output還會是50層