YOLO目标检测算法
YOLO算法
簡介
本文主要介紹YOLO算法,包括YOLOv1、YOLOv2/YOLO9000和YOLOv3。YOLO算法作為one-stage目標檢測算法最典型的代表,其基于深度神經網絡進行對象的識別和定位,運行速度很快,可以用于實時系統。了解YOLO是對目標檢測算法研究的一個必須步驟。
目標檢測思路
目標檢測屬于計算機視覺的一個中層任務,該任務可以細化為目標定位與目標識別兩個任務,簡單來說,找到圖片中存在某個對象的區域,然后識別出該區域的具體對象是什么。上述這兩個過程就是目標檢測中很常用的two-stage方法(兩階段檢測)。
目標識別(給定一張包含一個目標的圖片,該目標占據圖片大部分區域,要求識別出圖片中目標的類型)屬于計算機視覺的基本任務,這些年以卷積神經網絡為核心的深度識別網絡已經做得很好了。所以剩下的問題就是目標的定位。
當然,目標的定位有個很直接很粗暴的想法:遍歷圖片中所有可能的位置,搜索不同大小、寬高比的所有區域,逐個檢測其中是否存在某個目標,以概率最大的結果作為輸出。顯然,這種思路也許精度還行,但是效率太低。
RCNN系
RCNN極具開創性地提出了候選區的方法(Region Proposals),先從輸入圖像中找到一些可能存在對象的候選區,這個過程稱為Selective Search。在RCNN中這些候選區大概會有2000個,對這些區域進行目標識別即可完成檢測(提出候選區,對候選區進行識別,這就是two-stage的具體兩步)。候選區的提出大大減少了目標定位的時間,提高了目標檢測的效率。
不過。。。
RCNN依然很慢,它為后來實時檢測提供了可能,但也只是可能而已。后續的Fast RCNN和Faster RCNN則將這種可能變為了現實,它們針對網絡結構和候選區算法進行了很多改進,已經可以達到平均0.2秒一張圖片的速度。由于RCNN系并非本文重點,這里不多贅述,具體其效率變化如下表。
| RCNN | 49 |
| Fast RCNN | 2.3 |
| Faster RCNN | 0.2 |
YOLOv1
YOLO算法(全名You Only Look Once,代表只需要看一眼圖片就能完成目標檢測),其作者為Joseph Redmon,被稱為YOLO之父,其本人在2020年初由于自己的開源算法用于軍事和隱私問題,宣布退出CV領域。
YOLO創造性地將候選區和目標識別兩個階段合二為一,look once即可完成目標檢測,也實現了端到端的目標檢測。事實上,YOLO并沒有去掉候選區,而是使用一種預定義的類似候選區的預測區域。它將圖片劃分為S×SS\times SS×S個網格(論文中S=7S=7S=7,下文均使用7為例),也就是49個網格每個網格允許預測出兩個bbox(bounding box,邊界框),共98個。也可以理解為預定義了98個候選區。
為什么這樣做呢?其實也是有理由的。RCNN雖然找到了不少候選區,但是畢竟只是候選區,在完成目標識別之后,還需要對候選區進行調整以獲得更加準確的bbox位置,這個過程就是邊框回歸。YOLO當然就可以這樣想:既然最后總要調整,為什么不一開始就定義一個粗略的區域范圍,費勁找那么多候選區干嘛。
網絡結構
YOLO的網絡結構示意圖如下,就是堆疊了卷積池化最后加了兩層全連接,不過,由于是為了預測bbox等數值信息,并沒有采用softmax作為輸出的激活函數,而是采用了線性激活函數。整體來看,就是一個448*448*3的圖片經過復雜的神經網絡變換得到了一個輸出張量,這個張量的尺寸是7*7*30。所以理解YOLO無需太過在意中間一系列卷積網絡,弄明白輸入輸出的關系就行了。
輸入要求為448*448的圖片大小,這樣才能固定得到輸出張量的大小,因此輸入先縮放到448*448。通過上面的結構不難得到,輸出為一個尺寸為7*7*30的張量。其實不難理解,輸入有49個網格,輸出有49個30維向量,那么輸入時劃分的每一個網格對應輸出張量相應位置的向量為輸出,舉個例子,第一行第一列的網格在輸出張量中就是第一行第一列的向量。
那么如果存在跨網格的對象是不是就難以識別呢,其實不然,經過卷積神經網絡的復雜提取和變換,網格周圍的信息其實也被編碼到這個30維向量中了。
這個30維向量的訓練目標即ground truth是什么呢,也就是說,這30個元素代表什么呢?具體含義如下圖。其中,前20個值代表YOLO設計之初識別的20種目標在該位置存在的概率,記為P(Ci∣Object)P(C_i|Object)P(Ci?∣Object),表示若該網格存在一個目標,則它是CiC_iCi?的概率;最后8個值表示兩個bbox的位置,每個bbox需要四個值來表示,分別為(center_x,center_y,width,height);以及中間兩個值表示兩個bbox的置信度,其計算公式如下。
Confidence=Pr?(Object)?IOUpredtruth\text {Confidence}=\operatorname{Pr}(\text {Object}) * \text {IOU}_{\text {pred}}^{\text {truth}}Confidence=Pr(Object)?IOUpredtruth?
上式含義為bbox的置信度等于該bbox內存在目標的概率和該bbox與實際bbox的IOU乘積。這是針對訓練而言的,也就是用于計算預測準確程度的損失函數的一部分,實際使用訓練好的YOLO算法是沒有實際的bbox進行參考的,因而沒有IOU。簡單說來,bbox的置信度表示它是否包含目標且位置準確的程度。
到此,我們理清了YOLO的網絡結構,可以發現這其實就是一個深度回歸器。它是完全可以進行端到端訓練的,那么依據輸出得到的損失函數是什么呢?就是下面的式子(由于Markdown公式語法,其中顯示可能有點問題)。
λcoord?∑i=0S2∑j=0B1ijobj?[(xi?x^i)2+(yi?y^i)2]+λcoord?∑i=0S2∑j=0B1ijobj?[(wi?w^i)2+(hi?h^i)2]+∑i=0S2∑j=0B1ijobj?(Ci?C^i)2+λnoobj?j∑i=0S2∑j=0B1ijnoobj?(Ci?C^i)2+∑i=0S21iobj?∑c∈classes?(pi(c)?p^i(c))2\begin{array}{c} \lambda_{\text {coord }} \sum_{i=0}^{S^{2}} \sum_{j=0}^{B} \mathbb{1}_{i j}^{\text {obj }}\left[\left(x_{i}-\hat{x}_{i}\right)^{2}+\left(y_{i}-\hat{y}_{i}\right)^{2}\right] \\ +\lambda_{\text {coord }} \sum_{i=0}^{S^{2}} \sum_{j=0}^{B} \mathbb{1}_{i j}^{\text {obj }}\left[(\sqrt{w_{i}}-\sqrt{\hat{w}_{i}})^{2}+(\sqrt{h_{i}}-\sqrt{\hat{h}_{i}})^{2}\right] \\ +\sum_{i=0}^{S^{2}} \sum_{j=0}^{B} \mathbb{1}_{i j}^{\text {obj }}\left(C_{i}-\hat{C}_{i}\right)^{2} \\ +\lambda_{\text {noobj } j} \sum_{i=0}^{S^{2}} \sum_{j=0}^{B} \mathbb{1}_{i j}^{\text {noobj }}\left(C_{i}-\hat{C}_{i}\right)^{2} \\ +\sum_{i=0}^{S^{2}} \mathbb{1}_{i}^{\text {obj }} \sum_{c \in \text { classes }}\left(p_{i}(c)-\hat{p}_{i}(c)\right)^{2} \end{array}λcoord??∑i=0S2?∑j=0B?1ijobj??[(xi??x^i?)2+(yi??y^?i?)2]+λcoord??∑i=0S2?∑j=0B?1ijobj??[(wi???w^i??)2+(hi???h^i??)2]+∑i=0S2?∑j=0B?1ijobj??(Ci??C^i?)2+λnoobj?j?∑i=0S2?∑j=0B?1ijnoobj??(Ci??C^i?)2+∑i=0S2?1iobj??∑c∈?classes??(pi?(c)?p^?i?(c))2?
1iobj?\mathbb{1}_{i}^{\text {obj }}1iobj??表示網格iii中存在對象,1ijobj?\mathbb{1}_{ij}^{\text {obj }}1ijobj??表示網格iii的第jjj個bbox中存在對象,上標為noobj表示不存在對象。
上式第一行表示邊框中心位置誤差((cx,cy)誤差),第二行表示邊框寬度和高度誤差,第三行表示邊框內有目標的置信度誤差,第四行表示邊框內無目標的置信度誤差,最后一行表示目標分類誤差。總的來說,就是網絡輸出與真實標簽的各項內容的誤差平方和作為最后的輸出誤差,上述五項和30維輸出是對應的。λcoord\lambda_{\text {coord}}λcoord?用于調整bbox誤差的權重,YOLO設置為5。
訓練
YOLO現在ImageNet數據集上訓練前20層卷積網絡,讓網絡獲得一部分圖像特征提取能力,然后在Pascal VOC數據集上進行目標檢測的訓練。除了最后一層使用線性激活函數,其他層均使用Leaky Relu,同時采用Dropout和Data Augmention來控制過擬合的發生。
預測
訓練完的YOLO網絡就可以進行目標預測了,在此之前需要明確下面幾個點。原論文的YOLO結構最多識別49個目標;通過調整網絡結構可以識別更多的對象;YOLO中的預定義bbox和Faster RCNN中的Anchor不一樣,并沒有設定bbox的位置和大小,只是表示對一個目標預測兩個bbox,選擇可能性較大的那個,僅此而已。
訓練完成的YOLO網絡就可以進行目標檢測了,不過它的輸出是49個30維向量,表示網格包含的對象類別以及該對象的可能兩個bbox位置和對應的置信度。為了向量中提取最有可能的目標及其位置,YOLO采用NMS(Non-maximal suppression,非極大值抑制算法)來實現。
NMS算法并不復雜,其核心思想非常簡單:選擇score最高的作為輸出,與其重疊的刪除,反復迭代直到處理完所有備選。在YOLO中定義score如下式,表示每個網格中目標CiC_iCi?存在于第jjj個bbox的概率。
scoreij=P(Ci∣Object)?Confidencej\text {score}_{i j}=P\left(C_{i} | O b j e c t\right) * \text { Confidence}_{j}scoreij?=P(Ci?∣Object)??Confidencej?
不難算出,共有20?2?49=196020*2*49=196020?2?49=1960個得分,吳恩達對于nms的思路為分類別進行,所以每個類別是98個score。
NMS步驟如下圖。
總結
YOLO提出時由于one-stage特性,速度很快,FPS可以達到45,總體精度低于FastRCNN。遺憾的是,由于網格稀疏,對小對象預測效果較差。總的來說,為工業實時檢測提供了新的思路。
YOLOv2/YOLO9000
在YOLO系列中是第二個作品,由于原論文標題為YOLO9000,所以更多人愿意稱YOLO2為YOLO9000。作者還是Joseph Redmon,就像論文名YOLO9000:better,faster,stronger一樣,在保持高速處理的前提下,better(精度更高)、faster(速度更快)、stronger(目標更多)三個方面進行優化,目標類別因為加到了9000種,因此稱為YOLO9000。
better
下圖具體描述YOLO9000為了獲得更好的mAP(better),所做的工作的效果。
- Batch Normalization被應用到了網絡中(放棄了Dropout),有著更快的收斂以及更好的防止過擬合效果。
- High resolution classifier(高分辨率圖像分類器)用于預訓練特征提取網絡,文中使用448*448的圖像作為輸入而不是用YOLO1的224*224作為輸入圖像大小。
- Convolutional With Anchor Boxes,參考Fast RCNN的做法,在每個網格設置不同大小、寬高比的先驗框(anchor boxes),作為預定義的候選區在神經網絡中檢測其中是否包含目標以及邊框微調。同時,移除頂部的全連接層以及一個池化層,是的卷積層輸出分辨率較高
- Dimension Clusters,通過基于IOU的邊框聚類從數據集中學習到更加合適的先驗框(anchor box),減少邊框微調的成本。
- Direct location prediction,對bbox中心進行約束至一個網格內,從而是的模型早期學習穩定且更容易訓練。
- Fine-Grained Features,設計passthrough層將pooling之前的信息直接傳遞到最后的輸出特征圖從而保留一些細節上的信息,該方法可以改善小目標識別信息不足的問題。
- Multi-Scale Training,多尺度圖像訓練,因為去掉了全連接層,網絡的固定輸入限制解除了,整個網絡的下采樣倍率為32,訓練是隨機更換訓練的輸入尺寸,使得網絡對各種大小的目標有不錯的檢測效果。
faster
同樣,為了獲得更快的速度(faster),提出了Darknet19網絡結構,該結構包含19個卷積層和5個池化層,相比于VGG16小一些,但精度毫不遜色,且運算量大大減少。其具體結構如下圖。
YOLO2的訓練分為三個階段。首先,是224輸入的Imagenet的Darknet19預訓練(160輪);接著,是調整輸入為448的Imagenet上的Finetune訓練(10輪);最后,移除Darknet最后的卷積層、全局池化層以及Softmax分類層,新增三個卷積核為(3,3,1024)的卷積層和一個passthrough層,最后使用(1,1)的卷積層輸出檢測結果。輸出為對應網格數的向量,向量維度為anchors_num?(5+classes_num)anchors\_num*(5+classes\_num)anchors_num?(5+classes_num),由于anchors為5,對20中對象的VOC數據集輸出為(13,13,125),可以將125為向量理解為5個bbox的預測結果,25個值分別表示bbox的位置和大小以及置信度(tx,ty,tw,th)、Confidence,以及20個值表示的類別結果。
對應的損失函數也調整如下。
loss?t=∑i=0W∑j=0H∑k=0A1MaxIOU<Threshλnoobj?(?bijko)2+1t<12800λprior?∑r?(x,y,w,h)(priorkr?bijkr)2+1ktruth(λcoord?∑re(x,y,w,h)(truthr?bijkr)2+λobj?(IOUtruthk?bijko)2+λclass?(∑c=1c(truthc?bijkc)2))\begin{array}{rl} \operatorname{loss}_{t}=\sum_{i=0}^{W} \sum_{j=0}^{H} \sum_{k=0}^{A} & 1_{\text {Max} IOU<\text {Thresh}} \lambda_{\text {noobj}} \cdot\left(-b_{i j k}^{o}\right)^{2} \\ & +1_{t<12800} \lambda_{\text {prior}} * \sum_{r \epsilon(x, y, w, h)}\left(\text {prior}_{k}^{r}-b_{i j k}^{r}\right)^{2} \\ \\ & +1_{k}^{\text {truth}}\left(\lambda_{\text {coord}} \cdot \sum_{r e(x, y, w, h)}\left(\text {truth}^{r}-b_{i j k}^{r}\right)^{2}\right. \\ & +\lambda_{\text {obj}} *\left(IOU_{\text {truth}}^{k}-b_{i j k}^{o}\right)^{2} \\ & \left.+\lambda_{\text {class}} *\left(\sum_{c=1}^{c}\left(\text {truth}^{c}-b_{i j k}^{c}\right)^{2}\right)\right) \end{array}losst?=∑i=0W?∑j=0H?∑k=0A??1MaxIOU<Thresh?λnoobj??(?bijko?)2+1t<12800?λprior??∑r?(x,y,w,h)?(priorkr??bijkr?)2+1ktruth?(λcoord??∑re(x,y,w,h)?(truthr?bijkr?)2+λobj??(IOUtruthk??bijko?)2+λclass??(∑c=1c?(truthc?bijkc?)2))?
stronger
至于更強(stronger)的算法能力則依賴大量數據集,采用Imagenet和VOC數據集進行分類模型和檢測模型聯合訓練的方法實現9000中對象的檢測,具體可以查閱原論文。
總結
YOLO2在參考RCNN系列檢測的前提下,自行設計了網絡結果和訓練優化手段,取得了不錯的效果,為很多檢測算法提供了新的思路。
YOLOv3
YOLO3可能是現在目標檢測領域提的最多的YOLO系算法,因為它比較新且是之前YOLO算法的集大成者。作者依舊是Joseph Redmon,并且開源了代碼和模型參數,由于作者個人原因,這應該是YOLO系列最后一個作品。但是相比于之前的兩個YOLO版本,這個版本反而是突破最少的,主要是借鑒了一些CV中好的方法集成到了自己的算法中,尤其對于微小目標的識別有了更好的效果,所以YOLO3的論文其實非常簡短,單看YOLO3是不可能了解YOLO算法的。
網絡結構
借鑒ResNet的做法,設計了新版本的Darknet網絡,由于含有53個卷積層,又稱為Darknet53,其配置如下圖。主要是加入了一些殘差模塊。
多尺度特征
當然也不能放過這幾年很火的多尺度特征融合,通過下采樣和上采樣聯合的操作,對幾個尺度的特征圖進行融合(concatenation),以獲取不同的感受野信息,通過三種尺度的特征融合分別獲得了小、中、大目標的檢測能力,這是對YOLO2中passthrough層的進一步拓展。也是拓展,是的算法對于各種大小的目標有了更強的檢測能力。
分類激活函數
由原來的Softmax改為Logistic函數以支持多標簽分類。
總結
相比于YOLO2,YOLO3沒有什么太突破的成果,參照ResNet加深了網絡結構,使用比較流行的多尺度融合提升了小目標檢測效果。如果只考慮推理時間,在同等精度的情況下,YOLO3的速度是其他算法的3倍以上,具體如下圖。不過,若是考慮具體精度(以mAP為metric的話),YOLO3相比其他算法還是差了一些,但這不妨礙它作為一個高速實時檢測算法。
補充說明
本文主要介紹了YOLO系的目標檢測算法,包括YOLOv1、YOLOv2/YOLO9000以及現在很實用的YOLOv3。由于YOLO3是對YOLO的補充優化,所以了解YOLO3必須要了解YOLO以及YOLO2。由于YOLO算法作者已經開源并且也有很多不同框架的實現開源在Github上,我并沒有具體進行代碼實現。本文的資源文件可以在該博文資源的Github倉庫找到,歡迎star或者fork。
總結
以上是生活随笔為你收集整理的YOLO目标检测算法的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: Docker教程-文件传输
- 下一篇: WRN详述