YOLO (You Only Look Once)
一、YOLO
YOLO是一個實時的目標檢測系統。最新的V2版本在Titan X 上可以每秒處理 40-90 張圖片,在VOC 2007上可以取得78.6%的准確率,在COCO上可以取得48.1%准確率。
之間的檢測系統對圖像在不同的尺度、位置上進行多次檢測,需要執行多次神經網絡算法分別得到結果,YOLO只需要執行一次,所以速度上得到了較大的提升。
二、算法
算法發展過程:
RCNN --> SPPNet --> Fast RCNN --> Faster RCNN --> YOLO --> SSD --> YOLO V2
各算法比較:
YOLO V2版本在速度、准確率上都有較好的表現。
1. RCNN
是第一個使用RegionProposal+CNN這一框架。先利用Selective Search在一張圖片上框出上千個可能是目標的區域,分別放到神經網絡里生成特征,也就是一張圖片需要檢測上千次,比較耗時。
生成的特征用來訓練一個分類器,判斷是否是目標。
對所有是目標的特征再訓練一個回歸器,用來微調目標的位置。
RCNN在VOC2007上的mAP是58%左右。
2. SPPNet
Contributtions:
- 金字塔池化
- 復用Feature Map
傳統卷積網絡要保證輸入圖片的大小相等,這是因為想要通過CNN生成一個固定維度的特征送給分類器。作者在最后生成特征(全連接層)之前,加入了一個金字塔池化層,這樣保證最后輸出的特征維度固定(16 + 4 + 1) * 256,也就不需要前面對圖片進行裁剪、縮放生成固定大小的圖片。
SPPNet只進行一次卷積操作,之后再取的特征是根據proposal region在特征圖上提取,節省時間。
3. Fast RCNN
由於RCNN有重復計算問題,作者(R.B.G)根據SPPNet改進了RCNN,稱為Fast RCNN。
Contribution:
Fast RCNN也和SPPNet一樣,將Proposal region 映射到最后一層的feature map上,提高速度。
把bbox regression放進了神經網絡內部,與region分類和並成為了一個multi-task模型,實際實驗也證明,這兩個任務能夠共享卷積特征,並相互促進
在VOC2007上的mAP提高到了68%。
4. Faster RCNN
Faster RCNN也是Proposal Region + CNN模式,只是將前面的Proposal的提取由Selective Search改為使用卷積網絡(RPN)來生成。
本篇論文着重解決了這個系統中的三個問題:
- 如何設計區域生成網絡
- 如何訓練區域生成網絡
- 如何讓區域生成網絡和fast RCNN網絡共享特征提取網絡
用VGG net作為feature extractor時在VOC2007上mAP能到73%。
RPN:
• 在feature map上滑動窗口
• 建一個神經網絡用於物體分類+框位置的回歸
• 滑動窗口的位置提供了物體的大體位置信息
• 框的回歸提供了框更精確的位置
5. YOLO
由於RCNN架構都是對局部區域進行分類,YOLO采用回歸模型,只進行一次網絡傳播,便可以得到整幅圖像的目標,速度快了許多。
作者將圖片划分成SxS(7x7)大小的網格(grid),每個網格預測B(2)個box,每個box包含x, y, w, h 以及其置信度, 另外每個網絡還要預測屬於類別(C = 20)的概率,所以最后生成的維度的是S x S x (B x 5 + C) = 7 x 7 x (2 x 5 + 20) = 1470維,需要預測7 x 7 x 2 = 98個box。
只有當目標中心落入當前網格中,當前網格才為這個目標負責。這個網絡中,IOU最大的box為這個目標負責,即
為1, 否則
為0,
為1。作者設計的loss總共有如下幾個部分組成:
- x,y,w,h的損失
- 包含object目標的confidence損失
- 不包含object目標的confidence損失
- 類別預測損失
loss映射到30維向量的關系如下圖:
因為沒有object的框比較多,含有目標的框比較少,為了平衡兩者的loss貢獻,將沒有目標系數
設為0.5, 包含目標系數
設為5。
檢測階段:
生成了7x7個grid cell,7x7x2=98個box,對於dog類,把所有box按照confidence(置信度)降序排序,先取第一個,然后依次判斷后面的box與第前面記錄box的IOU,超過一定閾值就舍掉(NMS:非極大值抑制),最后保留的就是所有dog的框。同理,處理其它類別,如人、自行車,得到整幅圖像中的框。
Limitations:
一,YOLO的每一個網格只預測兩個boxes,一種類別。這導致模型對相鄰目標預測准確率下降。因此,YOLO對成隊列的目標(如 一群鳥)識別准確率較低。
二,YOLO是從數據中學習預測bounding boxes,因此,對新的或者不常見角度的目標無法識別。
三,YOLO的loss函數對small bounding boxes和large bounding boxes的error平等對待,影響了模型識別准確率。因為對於小的bounding boxes,small error影響更大。
Tiny YOLO 與 YOLO比較:
YOLO每秒45幀, 基於extracting network, 這個網絡是基於GoogleNet,網絡在ImageNet上性能:
Top-1 Accuracy: 72.5%
Top-5 Accuracy: 90.8%
Forward Timing: 6.4 ms/img
CPU Forward Timing: 0.95 s/img
weight file (90 MB)
Tiny YOLO每秒155幀, 基於Darknet reference network, 在CPU上比AlexNet快2倍,這個網絡在ImageNet上性能:
Top-1 Accuracy: 61.1%
Top-5 Accuracy: 83.0%
Forward Timing: 1.5 ms/img
CPU Forward Timing: 0.16 s/img
weight file (28 MB)
6. SSD
Contributions:
- 提出了SSD目標檢測方法,在速度上,比之前最快的YOLO還要快,在檢測精度上,可以和Faster RCNN相媲美
- SSD的核心是在特征圖上采用卷積核來預測一系列default bounding boxes的類別分數、偏移量
- 為了提高檢測准確率,在不同尺度的特征圖上進行預測,此外,還得到具有不同aspect ratio的結果
- 這些改進設計,實現了end-to-end訓練,並且,即使圖像的分辨率比較低,也能保證檢測的精度
- 在不同的數據集,如:PASCAL VOC、MS COCO、ILSVRC,對該方法的檢測速度、檢測精度進行了測試,並且與其他的方法進行了對比。
SSD結合了Anchor Box和Multi-scale Feature,結構上看起來比YOLO還復雜,但速度為什么比YOLO快呢?因為SSD的輸入是300,而YOLO輸入是448x448,另外SSD網絡使用的是VGG,並去掉了全連接層,而YOLO使用的是24層卷積網絡,參數更多。
YOLO的box個數只有98個,而SSD在不同的尺度上生成了8732個box,所以SSD的效果要比YOLO更好。
38x38x4 = 5776
19x19x6 = 2166
10x10x6 = 600
5x5x6 = 150
3x3x4 = 36
1x1x6 = 6
5776 + 2166 + 600 + 150 + 36 + 6 = 8734
SSD對於不同尺度的feature map進行卷積,假設每個feature map(m x n)點產生k(6)個box。每個box需要包含位置偏移(x, y, w, h)和屬於每類(C)概率的信息,所以對於每個點生成的張量維度為kx(C+4),需要的卷積濾波器大小為3 x 3 x (k x (C+4)),feature map生成的張量大小為mxnx(k x (C+4)), 整個網絡輸出大小為
,也就是8732x(C+4)大小的張量。然后在這些8732個box中,利用NMS選擇最優的box。
本文將 default box 與任何的 groundtruth box 配對,只要兩者之間的IOU 大於一個閾值,這里本文的閾值為 0.5。
表示default box i 與ground truth j 之間在p類別上匹配為1, 不匹配為0。loss損失函數由位置損失,置信度損失兩部分加權(交叉驗證:
):
對於位置loss,使用default box對ground truth 進行規一化:
對於confidence loss,
SSD300輸入大小為300x300, SSD512輸入圖片大小為512x512,如下是性能比較:
7. YOLO V2
基於YOLO有2個改進版,一個是YOLO V2, 一個是YOLO9000.
YOLO9000綜合ImageNet數據集和COCO數據集訓練YOLO9000,使之可以實時識別超過9000種物品。
YOLO V2相比於V1算法層面提升較少,主要是使用了更多的trick,使得檢測准確率得到了極大的提升,下面是這些trick提升的結果分析:
1. Batch Norm
CNN在訓練過程中網絡每層輸入的分布一直在改變, 會使訓練過程難度加大,但可以通過normalize每層的輸入解決這個問題。新的YOLO網絡在每一個卷積層后添加batch normalization,通過這一方法,mAP獲得了2%的提升。batch normalization 也有助於規范化模型,可以在舍棄dropout優化后依然不會過擬合。
2. High Resolution Classifier
目前的目標檢測方法中,基本上都會使用ImageNet預訓練過的模型(classifier)來提取特征,如果用的是AlexNet網絡,那么輸入圖片會被resize到不足256 * 256,導致分辨率不夠高,給檢測帶來困難。為此,新的YOLO網絡把分辨率直接提升到了448 * 448,這也意味之原有的網絡模型必須進行某種調整以適應新的分辨率輸入。
對於YOLOv2,作者首先對分類網絡(自定義的darknet)進行了fine tune,分辨率改成448 * 448,在ImageNet數據集上訓練10輪(10 epochs),訓練后的網絡就可以適應高分辨率的輸入了。然后,作者對檢測網絡部分(也就是后半部分)也進行fine tune。這樣通過提升輸入的分辨率,mAP獲得了4%的提升。
3. 全卷積網絡
為了使網絡能夠接受多種尺寸的輸入圖像,yolov2除去了v1網絡結構中的全連層,因為全連接層必須要求輸入輸出固定長度特征向量。將整個網絡變成一個全卷積網絡,能夠對多種尺寸輸入進行檢測。同時,全卷積網絡相對於全連接層能夠更好的保留目標的空間位置信息。
4. 新的基礎卷積網絡
基於Darknet-19。vgg16雖然精度足夠好,但是模型比較大,網絡傳輸起來比較費時間,因此,作者提出了一個自己的模型,Darknet-19。而darknetv2也正式已Darknet-19作為pretrained model訓練起來的。
5. Anchor Boxes
YOLO采用全連接層來直接預測bounding boxes,而Fast R-CNN采用人工選擇的bounding boxes。Fast R-CNN中的 region proposal network僅采用卷積層來預測固定的boxes(anchor boxes)的偏移和置信度。
作者去除了YOLO的全連接層,采用固定框(anchor boxes)來預測bounding boxes。首先,去除了一個pooling層來提高卷積層輸出分辨率。然后,修改網絡輸入尺寸:由448×448改為416,使特征圖只有一個中心。物品(特別是大的物品)更有可能出現在圖像中心。YOLO的卷積層下采樣率為32,因此輸入尺寸變為416,輸出尺寸為13×13。
采用anchor boxes,提升了精確度。
加入了anchor boxes后,可以預料到的結果是召回率上升,准確率下降。我們來計算一下,假設每個cell預測9個建議框,那么總共會預測13 * 13 * 9 = 1521個boxes,而之前的網絡僅僅預測7 * 7 * 2 = 98個boxes。具體數據為:沒有anchor boxes,模型recall為81%,mAP為69.5%;加入anchor boxes,模型recall為88%,mAP為69.2%。這樣看來,准確率只有小幅度的下降,而召回率則提升了7%,說明可以通過進一步的工作來加強准確率,的確有改進空間.
6. Dimension Clusters(維度聚類)
作者在使用anchor的時候遇到了兩個問題,第一個是anchor boxes的寬高維度往往是精選的先驗框(hand-picked priors),雖說在訓練過程中網絡也會學習調整boxes的寬高維度,最終得到准確的bounding boxes。但是,如果一開始就選擇了更好的、更有代表性的先驗boxes維度,那么網絡就更容易學到准確的預測位置。
和以前的精選boxes維度不同,作者使用了K-means聚類方法類訓練bounding boxes,可以自動找到更好的boxes寬高維度。傳統的K-means聚類方法使用的是歐氏距離函數,也就意味着較大的boxes會比較小的boxes產生更多的error,聚類結果可能會偏離。為此,作者采用的評判標准是IOU得分(也就是boxes之間的交集除以並集),這樣的話,error就和box的尺度無關了,最終的距離函數為:
作者通過改進的K-means對訓練集中的boxes進行了聚類,判別標准是平均IOU得分,聚類結果如下圖:
可以看到,從K=1到K=5,IOU曲線上升較快(對應匹配度高),因此從效果和復雜度進行Trade Off, 選定了 Anchor Box個數為5;意味着作者選擇了5種大小的box維度來進行定位預測,這與手動精選的box維度不同。結果中扁長的框較少,而瘦高的框更多(這符合行人的特征),選定了5種不同 寬高比+Scale 的 Anchor Box;對應上圖中的矩形。
當然,作者也做了實驗來對比兩種策略的優劣,如下圖,使用聚類方法,僅僅5種boxes的召回率就和Faster R-CNN的9種相當。說明K-means方法的引入使得生成的boxes更具有代表性,為后面的檢測任務提供了便利。
7. Direct location prediction(直接位置預測)
那么,作者在使用anchor boxes時發現的第二個問題就是:模型不穩定,尤其是在早期迭代的時候。大部分的不穩定現象出現在預測box的(x,y)坐標上了。在區域建議網絡中,預測(x,y)以及tx,ty使用的是如下公式
這個公式的理解為:當預測tx=1,就會把box向右邊移動一定距離(具體為anchor box的寬度),預測tx=-1,就會把box向左邊移動相同的距離。
這個公式沒有任何限制,使得無論在什么位置進行預測,任何anchor boxes可以在圖像中任意一點結束。模型隨機初始化后,需要花很長一段時間才能穩定預測敏感的物體位置。
在此,作者就沒有采用預測直接的offset的方法,而使用了預測相對於grid cell的坐標位置的辦法,作者又把ground truth限制在了0到1之間,利用logistic回歸函數來進行這一限制。
現在,神經網絡在特征圖(13 *13 )的每個cell上預測5個bounding boxes(聚類得出的值),同時每一個bounding box預測5個坐標值,分別為tx,ty,tw,th,to。如果這個cell距離圖像左上角的邊距為(cx,cy)以及該cell對應的box維度(bounding box prior)的長和寬分別為(pw,ph),那么預測值可以表示為:
定位預測值被歸一化后,參數就更容易得到學習,模型就更穩定。作者使用Dimension Clusters和Direct location prediction這兩項anchor boxes改進方法,mAP獲得了5%的提升。
8. Fine gained features
上述網絡上的修改使YOLO最終在13 * 13的特征圖上進行預測,雖然這足以勝任大尺度物體的檢測,但是用上細粒度特征的話,這可能對小尺度的物體檢測有幫助。Faser R-CNN和SSD都在不同層次的特征圖上產生區域建議(SSD直接就可看得出來這一點),獲得了多尺度的適應性。這里使用了一種不同的方法,簡單添加了一個轉移層( passthrough layer),這一層要把淺層特征圖(分辨率為26 * 26,是底層分辨率4倍)連接到深層特征圖。
這個轉移層也就是把高低兩種分辨率的特征圖做了一次連結,連接方式是疊加特征到不同的通道而不是空間位置,類似於Resnet中的identity mappings(對Resnet這一機制幾乎不懂,等看懂了再行補充)。這個方法把26 * 26 * 512的特征圖連接到了13 * 13 * 2048的特征圖,這個特征圖與原來的特征相連接。YOLO的檢測器使用的就是經過擴張的特征圖,它可以擁有更好的細粒度特征,使得模型的性能獲得了1%的提升。
9. Multi-Scale Training
原來的YOLO網絡使用固定的448 * 448的圖片作為輸入,現在加入anchor boxes后,輸入變成了416 * 416。目前的網絡只用到了卷積層和池化層,那么就可以進行動態調整(意思是可檢測任意大小圖片)。作者希望YOLOv2具有不同尺寸圖片的魯棒性,因此在訓練的時候也考慮了這一點。
不同於固定輸入網絡的圖片尺寸的方法,作者在幾次迭代后就會微調網絡。每經過10次訓練(10 epoch),就會隨機選擇新的圖片尺寸。YOLO網絡使用的降采樣參數為32,那么就使用32的倍數進行尺度池化{320,352,…,608}。最終最小的尺寸為320 * 320,最大的尺寸為608 * 608。接着按照輸入尺寸調整網絡進行訓練。(網絡只用到了卷積層和池化層,沒有全連接層,所以可以進行動態調整(檢測任意大小圖片))
這種機制使得網絡可以更好地預測不同尺寸的圖片,意味着同一個網絡可以進行不同分辨率的檢測任務,在小尺寸圖片上YOLOv2運行更快,在速度和精度上達到了平衡。
在小尺寸圖片檢測中,YOLOv2成績很好,輸入為228 * 228的時候,幀率達到90FPS,mAP幾乎和Faster R-CNN的水准相同。使得其在低性能GPU、高幀率視頻、多路視頻場景中更加適用。
三、運行YOLO V2
1. YOLO V2
下載darknet神經網絡框架,darknet是用C寫的輕量級深度學習框架:
windows版本darknet: https://github.com/AlexeyAB/darknet
git clone https://github.com/pjreddie/darknet
cd darknet
make
下載預訓練的權重文件, 大小為195MB:
wget https://pjreddie.com/media/files/yolo.weights
開始進行檢測:
./darknet detect cfg/yolo.cfg yolo.weights data/dog.jpg
輸出如下結果:
在我的CPU上跑需要19.7s,作者在Taitan X上只用了0.016s,如下圖:
另外,可以通過-thresh調整閾值,默認得分大於0.25才認為是目標,如下將閾值設為0:
./darknet detect cfg/yolo.cfg yolo.weights data/dog.jpg -thresh 0
2. Tiny YOLO V2
Tiny YOLO准確率不如YOLO,但快了許多:
下載權重文件, 大小61MB:
wget https://pjreddie.com/media/files/tiny-yolo-voc.weights
檢測:
./darknet detector test cfg/voc.data cfg/tiny-yolo-voc.cfg tiny-yolo-voc.weights data/dog.jpg
結果如下:
可以看到預測的結果沒有YOLO准確,但時間只需要2.3s。
3. 實時檢測
如果安裝了CUDA和OpenCV,可以通過攝像頭實時進行目標檢測:
./darknet detector demo cfg/coco.data cfg/yolo.cfg yolo.weights
也可以對視頻文件進行檢測:
./darknet detector demo cfg/coco.data cfg/yolo.cfg yolo.weights <video file>
4. YOLO用來做人臉檢測
需要根據你的應用場景來判斷是否合適。比如yolov1一個grid只能輸出1個目標物體,那么如果你的場景會有很多人或者畫面中人較小以致於很多人頭部落入一個grid,那么使用yolov1會有很多漏檢測。而且v1的localization的精准性並不高,所以如果對定位精准性要求高的 也不太適合。
四、tensorflow實現
五、目標檢測評估
precision = overlap / detection box
recall = overlap / ground truth box
IOU = overlap / union
使用map:
./darknet detector map cfg/voc.data cfg/yolo-voc.cfg yolo-voc.weights
detections_count = 124124, unique_truth_count = 12032
class_id = 0, name = aeroplane, ap = 77.08 %
class_id = 1, name = bicycle, ap = 81.11 %
class_id = 2, name = bird, ap = 75.97 %
class_id = 3, name = boat, ap = 64.66 %
class_id = 4, name = bottle, ap = 48.74 %
class_id = 5, name = bus, ap = 82.53 %
class_id = 6, name = car, ap = 83.36 %
class_id = 7, name = cat, ap = 87.65 %
class_id = 8, name = chair, ap = 58.95 %
class_id = 9, name = cow, ap = 81.82 %
class_id = 10, name = diningtable, ap = 75.22 %
class_id = 11, name = dog, ap = 86.32 %
class_id = 12, name = horse, ap = 86.38 %
class_id = 13, name = motorbike, ap = 84.21 %
class_id = 14, name = person, ap = 76.48 %
class_id = 15, name = pottedplant, ap = 51.42 %
class_id = 16, name = sheep, ap = 78.77 %
class_id = 17, name = sofa, ap = 77.10 %
class_id = 18, name = train, ap = 85.40 %
class_id = 19, name = tvmonitor, ap = 74.72 %
for thresh = 0.24, precision = 0.68, recall = 0.79, F1-score = 0.73
for thresh = 0.24, TP = 9459, FP = 4450, FN = 2573, average IoU = 52.58 %mean average precision (mAP) = 0.758959, or 75.90 %
Total Detection Time: 132.000000 Seconds
使用reval_voc_py3.py結果:
./darknet detector valid cfg/voc.data cfg/yolo-voc.cfg yolo-voc.weights
python3 scripts/reval_voc_py3.py --year 2007 --classes data/voc.names --image_set test --voc_dir /home/guru_ge/dataset/voc/VOCdevkit/ results
Mean AP = 0.7602
Results:
0.773
0.813
0.759
0.654
0.490
0.825
0.841
0.876
0.592
0.814
0.751
0.863
0.863
0.843
0.767
0.528
0.781
0.770
0.853
0.747
0.760
Referece
- http://blog.csdn.net/cv_family_z/article/details/46832845
- https://pjreddie.com/darknet/yolo/#demo
- http://blog.csdn.net/jesse_mx/article/details/53925356
- http://blog.csdn.net/u013989576/article/details/73439202
- http://blog.csdn.net/hrsstudy/article/details/70305791
- http://blog.csdn.net/linolzhang/article/details/59728206?locationNum=5&fps=1
- https://www.cnblogs.com/skyfsm/p/6806246.html
