引言
本文是吳恩達深度學習第四課:卷積神經網絡。本次課程將會告訴大家如何構造卷積神經網絡並應用到圖像數據上。從中你會學到如何構建一個卷積神經網絡、如何應用卷積神經網絡到圖像識別和目標檢測上、學習如何使用神經風格轉換去生成藝術作品、能將這些算法應用到更廣泛的圖像應用上,比如2D、3D數據和視頻。
第四課有以下四個部分,本文是第一部分。
- 卷積神經網絡基礎
- 深度卷積模型:實例分析
- 目標檢測
- 特殊應用:人臉識別&神經風格轉換
目標定位
在實現目標檢測(對象檢測)之前,我們先了解一下目標定位。
在圖像分類中我們可以知道這張圖片中有沒有汽車。
而定位分類問題不僅要判斷圖片中是否有汽車,如果有的話還要在圖片中標出它的位置。
而檢測問題是,當圖片中有多個對象時,應該如何檢測它們並確定出位置。
在對象檢測問題中,圖片中可以含有多個對象。
先看下圖像分類
圖像分類問題我們已經很熟悉了,可以用卷積神經網絡來做,這裏比如有四個類別,分別是行人、汽車、摩托和背景。
那如果還想定位圖片中汽車的位置,應該如何做呢
我們可以改變上面分類網絡的輸出,讓它輸出一個邊框(bounding box)。
具體的就是輸出四個數:。
左上角的座標定爲,右下角定爲。
邊框的中間點座標爲,邊框的高和寬爲和。
然後就可以使用監督學習算法輸出一個分類標籤,還有這四個數值,從而給出被檢測對象的邊框位置。
在這個例子中約爲,因爲它在x軸方向中間位置,約爲,表示汽車位於距離圖片底部的位置。
表示邊框高度是圖像高度的倍,同理表示寬度爲圖片寬度的倍。
下面定義下輸出向量,第一個元素表示是否含有目標對象,如果圖片中含有行人、汽車或摩托則,否則。
接下來是邊框的四個數值。
然後如果,那麼還要輸出圖片中包含3個類別的概率:
這裏我們先假設圖片中只含有一個對象。
下面我們來看幾個例子。
這個圖片中有汽車,所以,然後是邊框值,汽車屬於第二個類別,因此,其他都爲零。
那如果圖片中沒有要檢測的類別呢?
此時,那麼其他值就無意義了,因此我們不關心其他元素值。
我們可以根據這樣的方式定義訓練集。
最後介紹一個訓練神經網絡的損失函數。
如果採用平方誤差,若,就有下面的式子:
因爲我們輸出的有8個元素,比如第一個元素是,最後一個元素是。此時用平方誤差可以減少這8個元素值與實際輸出值結果之間的差值平方。
若,那麼損失爲
因爲這種情況下,我們不考慮其他元素。
以上就是利用神經網絡解決對象分類和定位問題的過程,結果證明,利用神經網絡輸出批量實數來識別圖片中的對象是個非常有用的算法。
下節和大家分享另一種思路,把神經網絡輸出的實數集作爲一個迴歸任務。
特徵點檢測
神經網絡可以輸出圖片上特徵點的座標來實現母特徵的識別。
(這是吳恩達夫人)
假設你希望算法可以給出四個眼角的具體位置,你可以讓神經網路多輸出8個值,代表眼角的座標,從左到右。
也許除了這四個特徵點,你還想得到更多的特徵點輸出值,
比如眼睛和鼻子嘴巴的特徵點。這樣可以判斷人物是在微笑還是皺眉。
你可以設定特徵點的個數,這裏假設有64個。可以包括更多的信息,比如臉頰的位置。
選定特徵點的個數,並生成包含這些特徵點的標籤訓練集,然後利用神經網絡輸出臉部關鍵特徵點的位置。
用卷積神經網絡來做的話,也是輸出是否含有人臉,接着是這64個特徵點的座標。這個例子中有個輸出。
由此可以實現對圖片的人臉檢測和定位。
檢測臉部特徵點也是計算機圖形效果的一個關鍵構造模塊,可以實現頭戴皇冠和臉部扭曲等特效。
顯然要訓練這樣一個網絡,需要訓練數據集,訓練集中的特徵點都是人爲辛苦標註的。
如果對人體姿態感興趣,還可以標出人體姿態的一些關鍵特徵點。
值得一提的是,所有圖片中的特徵點要保持一致,比如第一個特徵點是左眼的左邊眼角,第二個特徵點是左眼的右邊眼角座標。
目標檢測
現在我們來構建一個目標檢測算法。我們要用卷積網絡進行目標檢測,採用的是基於滑動窗口的目標檢測算法。
假設你想構建一個汽車檢測算法,首先你需要創建一個標籤訓練集。
其中表示適當剪切的汽車圖片樣本,
對於這個訓練集,你一開始可以使用適當剪切的圖片,就是整張圖片幾乎都是汽車。
有了這個訓練集,你就可以開始訓練卷積神經網絡了。
輸入是適當剪切了的圖片,輸出就是是否爲汽車。訓練完這個卷積網絡,就可以用它來實現滑動窗口目標檢測。
假設這是一張測試圖片,首先選定一個特徵大小的窗口(滑動窗口),比如上圖那個紅框。然後將這個紅框輸入到這個卷積神經網絡中,然後只取這個小框內的圖像。把這個小框內的圖像輸入到上面學習的卷積神經網絡中,讓卷積網絡預測這個小框內是否有汽車。
接下里要做的是移動小框的位置,輸入第二個小框內的圖像。用卷積網絡判斷其中是否含有汽車。
以此類推,知道滑動窗口遍歷了圖像中的所有位置。
現在用這個滑動窗口遍歷完圖像之後,再用更大的窗口來遍歷一次。
遍歷完了之後還可以用一個更大的窗口再遍歷一次。
我們希望,只要圖像彙總某處有一輛車,就會有某個窗口輸入到卷積神經網絡中得到。比如希望這個窗口輸出
這樣就檢測到這裏有一輛汽車。這就是滑動窗口算法。
不過,滑動窗口檢測算法有一個很大的缺點,就是它的計算成本。因爲你裁剪出了很多不同的正方形圖像。並讓每個圖像都單獨通過卷積神經網絡進行運算,如果你使用一個很大的步長,那麼窗口數就會減少。
但是比較粗的粒度可能會影響算法的表現。如果你用了較小的步長,就會得到很多窗口。將它們全部通過卷積神經網絡意味着很高的計算成本。
幸運的是,這個計算成本的問題有一個很好的解決方案。我們下節介紹。
卷積的滑動窗口實現
我們先看下如何將卷積網絡中的全連接層轉化爲卷積層。
假設有一個這樣的卷積神經網絡,這裏用softmax輸出四個類別。
現在來展示如何將上圖紅線中的這些層轉換爲卷積層。
這是一個卷積神經網絡,前幾層和之前相同。現在實現這一層全連接層的一個方式是用步長爲1大小爲(400個)的過濾器代替之前的全連接層。
拿的圖像和的過濾器做卷積操作,所以輸出大小爲。
從數學上來講,這和一個全連接層是一樣的。
因爲這400個節點中每個節點都有一個的過濾器,所以每個值都是上一層這些激活值經過某個任意線性函數的輸出結果。
接着再添加另一個(400個)的卷積層,在這400個過濾器的作用下,下一層的大小是。
最後通過過濾器的處理,得到一個softmax激活值。
以上就是用卷積層代替全連接層的過程。
我們再看看如何通過卷積實現滑動窗口對象檢測算法。
內容借鑑了 OverFeat: Integrated Recognition, Localization and Detection using Convolutional Networks
假設像滑動窗口卷積網絡輸入的圖片,爲了簡化。
假設你測試集圖片是。
在最初的滑動窗口算法中,你會把紅框這部分藍色方塊輸入到卷積網絡,得到0或1分類。
接着滑動窗口,步長爲2,得到下面這個綠框方塊,讓後將其輸入到卷積網絡中得到輸出。
繼續滑動,接着輸入下面黃框方塊到卷積網絡,得到輸出。
再一次向右移動,得到紫框方塊,輸入卷積網絡得到分類輸出。
所以我們在這個的圖像上滑動窗口,讓卷積網絡運行了4次,輸出了4個標籤。
但是,這4次卷積操作中的很多計算都是重複的,滑動窗口卷積方式的實現是讓這4次卷積神經網絡的前運算共享計算過程。
具體的你可以這麼做,你可以運行這個卷積神經網絡,用同樣的參數和相同的16個的過濾器,得到一個的輸出。
然後像之前一樣,做最大池化,得到。接着使用相同的400個的過濾器得到一個的卷積輸出。
再經過一個的過濾器得到另一個的輸出,再做一次同樣的操作就可以得到的輸出。
最終在輸出層這4個子方塊中,藍色的是圖像左上部分(紅框方塊)的輸出。
同理其他3個方塊對應不同顏色區域的輸出。
如果具體想看某一塊方塊的運算過程,比如綠框方塊,它就是下面這樣的:
所以該卷積操作的原理是,我們不需要把輸入圖片分割成四個子集,分別執行前向傳播,而是把它們作爲一張圖片輸入給卷積網絡進行計算。
其中公共區域可以共享很多計算。
再來看一個輸入圖像更大的例子。
最終輸出矩陣的最左上子方塊對應着輸入的這塊區域。
然後以步長爲2不停的移動,就可以得到整個輸出。
以上就是在卷積層上應用滑動窗口算法的內容,它提高了整個算法的效率。
不過這個算法仍然有一個缺點,就是邊框的位置可能不夠準確。
下節來學習如何解決這個問題。
邊框預測
在滑動窗口中,你取這些離散的位置集合,此時這些邊界框沒有一個能完美匹配汽車位置。
也許上圖這個框是最匹配的了。
但是它的真實值可能不是一個方向,而是一個矩形。那有沒有辦法讓這算法輸出更精準的邊框呢
其中一個能得到更精準的邊框的算法是YOLO(you only look once)算法。該算法是這麼做的,
假設你的圖像是的,在上面放一個(這裏只是爲了演示,實際上可能取)的網格。
然後使用圖像分類和定位算法應用到這9個格子中。
此時你需要這樣定義訓練標籤,對於9個格子中的每一個,指定一個標籤,
像前面介紹的一樣,頂一個一個8維向量。
這張圖有9個格子,每個格子都有這樣一個向量。
我們看下左上方這個格子,裏面沒有要檢測的對象,所以它的輸出是
我們直接來看有對象的格子,這張圖裏面共有兩個要檢測對象。YOLO算法做的是取這個對象的中點,然後將這個對象分配給包含對象中點的格子。
這兩輛車的中點分別在綠色和黃色格子裏面,它們中間的那個格子即使同時包含兩輛車的一部分,也不會說它有要檢測的對象。
所以每個格子都有一個8維的輸出向量,總的輸出大小爲。
這個算法的優點是可以輸出精確的邊框,所以測試的時候,只要喂入測試圖像,然後正向傳播就能得到輸出。
我們現在學習的還是一個格子中只有一個對象的問題。
YOLO算法和圖像分類和定位算法非常像,即能顯示地輸出邊框座標,但是可以具有任意高寬比,並且能輸出更精確的座標。
並且這是一個卷積實現,使用卷積網絡可以有很多共享計算步驟,所以這個算法的效率很高。
如何編碼實現呢,
以黃框裏面的格子爲例,它的輸出會是右邊這樣的。還是指定左上角的座標爲,右下角的座標爲。
這裏(在之間)說的是目標對象中點位置左邊,而(可能大於)是相對格子大小的比例。這裏只是一種編碼約定,其實還有其他更加複雜的方式。
交併比
在對象檢測任務中,我們希望也能同時定位到對象。
如果對象的實際邊框是紅色,我們的算法給出的是紫色。那麼如何評價這個結果的好壞呢。可以用交併比來做。
交併比(IoU,intersection over union)做的是計算兩個邊框交集和並集之比。
這兩個對象的並集是綠色填充的這一區域。
而交集是黃色較小的區域。那麼交併比就是計算交集的大小除以並集的大小。
一般約定交併比的結果不小於就是檢測正確的。如果預測結果和實際邊框完美重疊,則交併比取最大值。
IoU越大說明定位越精確。
非極大值抑制
現在爲止我們學到的對象檢測中的一個問題是,我們的算法可能對同一個對象作出多次檢測。
而最大值抑制這個方法可以確保算法對每個對象只檢測一次。
假設我們要在這張圖裏面檢測行人和汽車,我們放一個的網格,這張圖裏面有兩輛車,每輛車都只有一箇中點。
假設中點如上圖所示,理論上應該只有兩個格子作出有車的預測。但實際當你跑分類和定位算法時,可能會有多個格子預測有車,如下圖,每個對象區域內都有3個格子預測有車。
現在我們看一下非最大值抑制是怎麼生效的,因爲要在個格子上都跑一次圖像檢測和定位算法,那麼可能很多格子都會說它這個格子裏面有車的概率很高。
而實際上這幅圖應該只有兩個格子能檢測到對象。
所以當你的算法對同一個對象作出多次檢測時,此時應用非最大值抑制做的就是清理這些檢測結果。
首先看每個格子報告有目標的概率是多大,這裏上圖中的數字就是這個概率。
然後找到概率最大的那個,然後非最大值抑制就會一一檢測剩下的矩形,所有和這個最大的邊框有很高交併比(高度重疊)的其他邊框都會被抑制,
所以分別是和的兩個暗藍色矩陣和的矩陣重疊程度很高,都會被抑制。
同理左邊的車,概率爲的矩形就會被抑制(變暗)。此時如果拋棄變暗的矩形,最後就得到了兩個預測結果。
所以這就是非最大值抑制,意味着只輸出概率最大的結果。
下面來看一下這個算法的細節。首先在這個的網格上跑一下算法,就會得到的輸出尺寸。
這個例子我們簡化一下輸出,假設只做汽車檢測,也就是去掉了。
現在要實現非最大值抑制,做的第一件事情是去掉所有不大於某個閾值的邊框,這裏閾值假設是。
接下來在剩下的邊框中,
只要還有剩餘邊框(循環):
- 重複地選擇概率最大的邊框,當成輸出邊框,預測結果
- 丟掉其他剩餘邊框,這些邊框都和輸出邊框有很高的的IoU(上面介紹的變暗的那些邊框)
直到每個邊框都判斷過了,它們有的作爲輸出結果,有的被丟掉了。
錨框
到目前爲止,對象檢測中存在的一個問題是,每個格子只能檢測出一個對象。
如果你想讓一個格子檢測出多個對象,那麼就要使用錨框(anchor box)。
還是從例子開始介紹,假設你有張這樣的圖片:
行人的中點和汽車的中點幾乎處在相同的位置。所以對於中點所在的這個格子,
將不知道輸出哪一個,因爲必須從兩個結果中選一個。
而anchor box的思路是預先定義兩個不同形狀的anchor box形狀:
你要做的就是將預測結果與這兩個anchor box關聯起來。此時的輸出定義成這樣,即同時輸出兩個邊框信息:
使用anchor box後,每個對象都被分配到對象中點所在的格子中,和一個IoU值最高、具有對象形狀的anchor box中。
比如你有個對象時紅框形狀的,你有兩個anchor box,此時IoU值最高的anchor就是豎着的那個。
下面舉個實際的例子,
這個格子有兩個對象,它的輸出如上圖右邊那個向量所示,首先是行人形狀的anchor box1,下面接着一個汽車形狀的anchor box2。
那假設這個圖像中只有汽車,沒有行人,那輸出會是怎樣的呢,還是假設汽車的形狀是anchor box2那樣的。
就是anchor box2的輸出還是一樣的,但anchor box1的,我們不關心其他值的輸出了。
雖然我們把anchor box當成處理兩個對象中點都一樣的情形,但實際上出現這種情形的概率並不高,尤其你用了的格子的時候。
YOLO算法
利用上面所學的知識來介紹一下YOLO算法,先來看下如何定義訓練集。
如果是一個的格子,兩個anchor box的話,那麼就有的輸出。
要構造訓練集,需要遍歷9個格子,每個格子都會輸出。
第一個格子裏面啥都沒有,因此它的輸出應該是上圖右邊這個向量這樣的。
這張圖中大部分格子裏面都沒有物體,除了綠框的這個格子。
假設這兩個anchor box是這樣的,並且anchor box2的交併比更高,因此得到的輸出就是和輸出向量下半部分有關的。
所以遍歷所有的格子,最終得到的輸出大小是
所以訓練集就是這樣的,然後你可以訓練一個卷積神經網絡。
接下來看這個算法是如何進行預測的,
對於左上角這個格子,期望的輸出是兩個都是,此時我們不關心其他值的輸出。而對於綠框的這個格子,期望的輸出是:
第二個anchor輸出的,並且剛好是紅框那個位置。
下面說明一下非最大值抑制,我們看另外一張圖片。
假設有兩個anchor box,這樣每個格子都會有兩個邊框輸出,其中有個更低
假設所有輸出的邊框是這樣的,注意上面有些邊框的大小可以超出所在格子的高度和寬度。
接下來要拋棄所有概率低的預測,
得到了上面這樣的結果,假設你要預測行人、汽車和摩托這三種類別。那麼要做的是,對每個類別,單獨運行非最大值抑制,來處理預測結果是那個類別的邊框。
用非最大值抑制處理汽車類別、行人類別和摩托類別,運行三次來得到最終的預測結果如上。