1. 程式人生 > >深度學習筆記(4):1.1-1.3 邊緣檢測(edge detection)

深度學習筆記(4):1.1-1.3 邊緣檢測(edge detection)

第四課開始,我們開始學習卷積神經網路。

1.1 計算機視覺(computer vision)

深度學習在計算機視覺方面的應用非常振奮人心,一方面是該應用使許多不可能變成了可能,另一方面是深度學習在計算機視覺方面的應用能夠給深度學習在其他方面的應用帶來一些方法的改進和思考,比如語音識別等。

計算機視覺包含哪些問題呢?如下圖所示:

比如圖片分類,判斷一個圖片是否是貓;或者目標識別,比如在無人駕駛任務中,識別路上其他的車以及距離,以便無人駕駛能夠安全執行;還有就是圖片風格轉化,比如我們有一個美女的照片(是吳老師的妻子,哈哈)和一個畢加索的繪畫,把二者融合起來,就可以得到人像的輪廓和畢加索的風格。

比如在圖片分類中,我們使用的圖片可能是小圖片,比如畫素是64*64,加上顏色的三個channel(RGB channels),該圖片作為輸入是一個64*64*3=12288維的向量,還好。但若是大圖片呢?比如一個畫素為1000*1000的圖片,那該圖片作為輸入就是3m(3百萬)維的向量,假設第一層隱藏節點有1000個,且在完全連線的情況下,第一層的權重矩陣就是1000*3m維的矩陣,相當於第一層有30億的權重,這時很難有足夠多的樣本去訓練這麼多的權重,容易發生過擬合,同時這麼多的權重還會對記憶體有一定要求,而且我們不想僅限於處理小圖片。為了解決衍生出來的這麼多問題,我們需要使用卷積運算,見下節。

1.2 邊緣檢測例子(edge detection example)

卷積運算是卷積神經網路最基本的組成部分。這節課我們通過邊緣檢測例子來學習卷積運算,如下圖所示:

在神經網路模型中,前幾層神經網路能檢測到邊界,後幾層可能檢測到物體小部分,再後面幾層可能檢測到具體的物體,在這個例子中就是人臉。接下來我們講如何在圖片中識別邊界,也就是為何神經網路前幾層能夠檢測到圖片中的邊界。

假設我們有上圖中這樣一個照片,我們可以通過垂直邊緣檢測器和水平邊緣檢測器分別檢測出圖片中的垂直和水平邊緣,檢測器檢測出的結果如上圖所示。但是這些檢測器是如何工作的呢?我們以垂直檢測器為例。在介紹垂直檢測器之前,我們先介紹一種運算,卷積運算(Convolution operation),如下圖所示:

假設我們的圖片如上圖左側矩陣所示,這是一個6*6的矩陣,因為我們沒有考慮彩色,這僅僅是一個黑白圖片,所以不存在RGB通道,這裡圖片是6*6*1的向量,接下來我們對其作卷積運算。

首先介紹一下中間的3*3矩陣,我們稱之為‘核(kernel)’或‘過濾器(filter)’,中間‘*’號表示卷積運算,這與我們在程式中使用方法不同,一般‘*’在程式中都表示乘法,或者說是element-wise的乘法。

那麼卷積運算怎麼做呢?我曾在深度學習書中看過這樣一種比喻,我覺得比較恰當,在這裡跟大家分析一下,想象你是一個探險家,在黑暗中找到一幅畫卷,為了仔細看清畫卷內容,於是你開啟手電筒從畫的左上角還是掃描直至畫的右下角,過濾器做的就是類似手電筒的工作。計算也非常簡單,就是element-wise,首先將filter對應於左上角九宮格,然後按上圖中紅色式子進行計算,就是對這兩個3*3矩陣進行element-wise乘法再求和,我們得到-5,寫於右側矩陣的(1,1)位置,就這樣從左到右,從上到下,最終得到一個4*4的矩陣,其中最後(4,4)位置對應的-16是由左側紫色框內矩陣和filter做卷積計算所得。

瞭解了卷積運算,接下來我們介紹垂直邊緣檢測器,如下圖所示:

同樣是做卷積運算,不過我們在這裡對filter做了‘手腳’,使其能夠檢測出圖片中的垂直邊界,怎麼說呢?

在原圖中,也就是左矩陣中,我們用0來表示灰色(或者你認為黑色都可以),10來表示白色,即數值越大顏色越亮,我們想檢測出白色和灰色中間那條邊界,怎麼做呢?我們使用了一個3*3的filter,它的第一列都為1,第二列為0,第三列為-1,經過卷積運算我們得到了一個4*4的矩陣,中間兩列值都為30,兩邊為0,即我們清晰地找出了邊界。

首先為什麼能夠找出邊界,背後的思想我們可以這樣認為,邊界兩側的數值肯定是有很大差異的,不是邊界的數值差異不大,所以kernel這樣取值就能使數值差異不大的地方通過卷積運算得出來的值近似為0,而當數值有很大差異時,使用該kernel就無法抵消,這樣就可以找出邊界,當然這裡要注意我們設定kernel的維度要注意原圖的維度以及邊界的寬度,比如這裡最後的出來的邊界看起來很寬,那是因為原圖太小了,僅僅是6*6,如果是1000*1000,邊界效果就會很好了。

1.3 更多邊緣檢測內容(more edge detection)

這小節我們將學習更多邊緣檢測的內容,比如學會如何區分正邊和反邊,也就是區分由亮到暗和由暗到亮的區別,如下圖所示:

還是之前那個例子,假設我們將圖片左右翻轉一下,現在左側是暗的,右側是亮的,但是我們還使用同一個filter,所以自然會得到一個相反的數值,如上圖所示,表示邊界的值由30變為-30,這裡數值的變化就就能夠告知我們一些準確的資訊,比如30告訴我們這個邊界是正邊,即顏色是由亮到暗,而-30就告訴我們這個邊界是負邊,及顏色是由暗到亮,當然如果你不care正邊還是負邊可以直接對卷積計算結果取絕對值,即只確定邊界並不考慮其顏色是如何變化的。

除了垂直邊緣檢測,我們還可以進行水平邊緣檢測,如下圖所示:

思想很簡單,將垂直邊緣檢測的kernel作轉置我們就可以得到水平邊緣檢測的kernel了。套用在例子中如上圖所示,假設我們現在有一個這樣的6*6矩陣,其對應圖片為左下部和右上部偏暗,顯然這個圖片既存在水平邊緣也存在垂直邊緣,現在我們使用水平邊緣檢測的kernel去檢測水平邊緣,結果如上圖所示,10和-10的出現在這裡是因為垂直邊緣的影響,同樣,因為我們這裡舉例子的圖片太小(6*6),所以這裡顯得10和-10佔了很大比重,如果我們是1000*1000的圖片,結果就可以不考慮10和-10的影響了。

對於kernel中的數值選取,很多學者在文獻中公平地討論過該如何搭配資料才是合理的,如下圖所示:

除了第一列都是1,第三列都是-1這種filter,我們還可以對資料做其他改變,比如第二行都乘上2,我們稱之為sobel filter,相當於在原來基礎上進行了加權,它的優點在於增加了中間一行的權重,也就是處在中間的畫素,這樣可以增加結果的魯棒性(robust),還有另一種filter,將第一行和第三行都乘上3,第二行乘上10,我們稱之為scharr filter,這樣改變也會改進一些效能。

但實際中,我們一般將這九個值設為九個引數,然後通過神經網路的反向傳播去學習,為啥呢麼這樣做呢?首先是之前的filter過於簡單,針對的僅僅是垂直或水平邊緣的情況,即90度,且數值是實驗前已經設定好的,不一定適合每個問題,而實際問題要複雜得多,比如上圖中所示的情況,所以我們希望filter中的數值能夠作為引數從資料集中學習而得到,這樣一方面是準確,一方面是我們可以應對任何複雜的情況,不論是45度、70度或是73度的邊緣我們都可以檢測出來。

通過反向傳播去學習kernel中的引數已經成為計算機視覺中最有效的思想之一。接下來我們會學習如何使用反向出傳播去學習這九個引數,但在此之前,我們會先學習一下有關卷積運算的基礎知識,詳見下節。