yolo_v3

一.概述

YOLO算法的基本思想是:首先通過特徵提取網絡對輸入圖像提取特徵,得到一定size的feature map,比如13*13,然後將輸入圖像分成13*13個grid cell,接着如果ground truth中某個object的中心座標落在哪個grid cell中,那麼就由該grid cell來預測該object,因爲每個grid cell都會預測固定數量的bounding box(YOLO v1中是2個,YOLO v2中是5個,YOLO v3中是3個,這幾個bounding box的初始size是不一樣的),那麼這幾個bounding box中最終是由哪一個來預測該object?答案是:這幾個bounding box中只有和ground truth的IOU最大的bounding box纔是用來預測該object的。可以看出預測得到的輸出feature map有兩個維度是提取到的特徵的維度,比如13*13,還有一個維度(深度)是B*(5+C),注:YOLO v1中是(B*5+C),其中B表示每個grid cell預測的bounding box的數量,比如YOLO v1中是2個,YOLO v2中是5個,YOLO v3中是3個,C表示bounding box的類別數(沒有背景類,所以對於VOC數據集是20),5表示4個座標信息和一個置信度(objectness score)。

算法在速度和精度上的提升可以看Figure1。
                        

二.詳解

A Fully Convolutional Neural Network

yolo_v3只使用了卷積層,沒有使用任何形式的pooling,其一共有75個卷積層,再結合skip connections和下采樣層。用stride=2的卷積操作去代替pooling。

yolo_v3按理說是可以不用限制輸入圖片的大小的,但是爲了batch的並行化計算,所以對輸入圖像的大小做了限制。

Interpreting the output

輸入尺寸爲416*416,圖像的下采樣率爲32,則最後的用於預測的featuremap尺寸爲13*13。

                                 

將輸入圖像劃分爲13*13的grid cell,其目的在於這個grid cell與featuremap上的13*13的grid cell一一對應(感受野)。

featuremap上的每一個grid cell預測3個bbox,在訓練時,如果一個目標的中心落入某個grid cell中,則該grid cell中的3個bbox與該目標相關,其中與gt有最高iou的bbox負責預測該目標。

Anchor Boxes

直接預測最後的w和h容易導致梯度的不穩定性,因爲不同的目標可能尺度差異比較大,所以這裏引入anchor,利用anchor的先驗位置,求取相對於其的offset來解決這個問題。

這裏的anchor只是爲了提供先驗,即下面公式中的pw,ph。

Making Predictions

 yolo_v3的預測方式與yolo_v2一樣,如下所示:

                                                      

 tx, ty, tw, th是網絡的輸出,cx,cy是當前grid cell的左上角的點的座標,pw,ph是anchor的尺寸。

Center Coordinates

以上的座標預測使用了sigmoid激活函數,使得座標值被歸一化到了0-1之間。

就拿上面那副圖來舉例子,紅色的cell的左上角座標是(6,6),如果tx,ty經過sigmoid函數的作用後的值爲(0.4,0.7),那麼這個bbox的座標值cx,cy爲(6.4,6.7)。

這裏有一個細節需要注意,即爲什麼使用sigmoid函數處理tx,ty。因爲tx,ty的值如果大於1,則再加上cx,cy會超出原來的cell,所以這裏用sigmoid將其限制在0-1之間。

Dimensions of the Bounding Box

bw,bh是經過圖像的w和h歸一化處理過的, 如果預測得到的bw和bh在featuremap上是(0.3,0.8)的話,那麼在featuremap上實際得到的w和h是(13 x 0.3, 13 x 0.8)。

Objectness Score

Object score代表了該bounding box包含目標的可能性,在紅色的cell和其周圍的cell,這個值接近1,而其他cell則接近0。這個Object score也是經過sigmoid函數處理的,使得其值位於0-1之間,代表了有目標的可能性。

Class Confidences

用sigmoid分類代替softmax分類,因爲softmax分類的概率輸出總和爲1,有類間相關性,所以yolo_v3使用sigmoid分類代替。

Prediction across different scales

從多尺度的featuremap上獲取預測結果。yolo_v3是從三種尺度的featuremap上獲取預測結果,這三種尺度分別爲32,16和8,由於輸入是416*416,所以對應的三種featuremap的大小分別爲13 x 13, 26 x 26 and 52 x 52。

具體做法如下:

首先一直下采樣,到13*13的featuremap,然後將其上採樣2倍,與之前26*26的featuremap相連,然後再上採樣2倍,與之前52*52的featuremap相連。在每一個scale的featuremap上,每一個cell都用3個anchor預測3個bounding box。由於3個尺度對應的anchor也不同,所以每一個cell在三種featuremap上總共得到9個anchor。

                                                  

 這種上採樣結合之前較大featuremap做最後預測的方式,可以提升對小目標的檢測能力,所以yolo_v3對於小物體的檢測效果還是不錯的。

 Output Processing

對於大小爲416*416的Input image,yolo_v3總共預測(52*52+26*26+13*13)*3總共10647 個bounding box。

考慮我們上面的圖像,只有1個目標--狗,那麼如果將這麼多的檢測結果降低爲最後的1個檢測框呢?

Thresholding by Object Confidence

篩掉boject conifidence低於一定閾值的bounding box。

Non-maximum Suppression

nms負責解決對於同一目標的重複預測問題。例如紅色cell的三個bounding box可以檢測到同一個目標,或者相鄰的cell可以檢測到同一個目標。

                             

三.總結

訓練時:

輸入圖片尺寸416*416,stride=32,所以最後用於預測的featuremap=13*13,對於每一個grid cell引入3個尺寸的anchor,對於gt,每一個目標中心所在的那個cell負責該目標,在這個cell中有3個預先設置的anchor尺寸,即pw,ph,選擇其中與gt的wh_iou最大的那個anchor作爲best_anchor(即形狀最相似的anchor)。

對於gt,target[:,2:6]中存儲的是各個目標中心點的gx,gy,gw,gh,這些都是在0-1之間的值,因爲原圖被劃分爲13*13的grid cell,gw和gh是目標的gt除以原圖的大小,即爲416所得到的歸一化值,gx,gy是目標的中心點座標減去所在cell的左上角座標歸一化得到的值,全都在0-1之間,下面做如下處理:

target_boxes = target[:, 2:6] * nG

ng是相應的featuremap的尺寸(例如13),這樣target_boxes中存儲的即爲在相應的featuremap上的gx,gy,gw,gh,然後求取相應的tx,ty,如下式,其中floor表示取整數部分,即得到相對於當前cell的左上角座標的offset。

tx[b, best_n, gj, gi] = gx - gx.floor()
ty[b, best_n, gj, gi] = gy - gy.floor()

 對於gw,gh,求取其相對於best_anchor的w和h的尺度offset爲tw,th。

tw[b, best_n, gj, gi] = torch.log(gw / anchors[best_n][:, 0] + 1e-16)
th[b, best_n, gj, gi] = torch.log(gh / anchors[best_n][:, 1] + 1e-16)

最後在計算loss的時候,計算關於tx,ty,tw,th的loss值。

對於預測得到的confidence和cls,用sigmoid函數處理,使其位於0-1之間。

 對於所有的目標中心所在的cell,將其對應的best_anchor的位置的obj_mask設爲1,即該cell的該mask負責預測該目標的位置和計算該目標的回傳loss。

obj_mask[b, best_n, gj, gi] = 1
noobj_mask[b, best_n, gj, gi] = 0
​

將wh_iou超過閾值的anchor的位置的noobj_mask值設爲0,即爲該cell位置處的該種尺度的anchor與best_anchor的wh_iou超過一定閾值,一般爲0.5,有一定的干擾作用,不參與noobj的confidence的loss回傳。

# Set noobj mask to zero where iou exceeds ignore threshold
for i, anchor_ious in enumerate(ious.t()):
    noobj_mask[b[i], anchor_ious > ignore_thres, gj[i], gi[i]] = 0

對於分類,進行one-hot編碼,用於計算loss。

# One-hot encoding of label
tcls[b, best_n, gj, gi, target_labels] = 1

 如果目標中心所在的cell中的best_anchor的預測類別的分數中最大的值所對應的類別與標籤一致,即預測的類別正確,則該位置的class_mask值爲1,不參與類別loss計算,否則爲0,計算分類loss。

iou_scores中存儲的是目標中心所在的cell中的best_anchor與相應的目標gt的iou值。

class_mask[b, best_n, gj, gi] = (pred_cls[b, best_n, gj, gi].argmax(-1) == target_labels).float()
iou_scores[b, best_n, gj, gi] = bbox_iou(pred_boxes[b, best_n, gj, gi], target_boxes, x1y1x2y2=False)

 接下來開始計算loss值:

1.計算目標中心所在的cell中的best_anchor所對應的tx,ty,tw,th的mse_loss。

loss_x = self.mse_loss(x[obj_mask], tx[obj_mask])
loss_y = self.mse_loss(y[obj_mask], ty[obj_mask])
loss_w = self.mse_loss(w[obj_mask], tw[obj_mask])
loss_h = self.mse_loss(h[obj_mask], th[obj_mask])

2.計算有沒有目標所對應的confidence score,兩者的權重爲1和100.

loss_conf_obj = self.bce_loss(pred_conf[obj_mask], tconf[obj_mask])
loss_conf_noobj = self.bce_loss(pred_conf[noobj_mask], tconf[noobj_mask])
loss_conf = self.obj_scale * loss_conf_obj + self.noobj_scale * loss_conf_noobj

3.計算分類的loss

loss_cls = self.bce_loss(pred_cls[obj_mask], tcls[obj_mask])

4.計算總的loss

total_loss = loss_x + loss_y + loss_w + loss_h + loss_conf + loss_cls

                        

                          

即不是best_anchor,但是與gt的iou大於閾值,則我們捨棄該預測,即不考慮其noobj的confidence的loss計算,如果不是best_anchor,我們不考慮其座標loss和cls loss,僅僅考慮其noobj的confidence loss。 

 

測試時:

output = torch.cat(
            (
                pred_boxes.view(num_samples, -1, 4) * self.stride,
                pred_conf.view(num_samples, -1, 1),
                pred_cls.view(num_samples, -1, self.num_classes),
            ),
            -1,
        )

對output做出如下的處理:

detections = model(input_imgs)
detections = non_max_suppression(detections, opt.conf_thres, opt.nms_thres)

首先刪除那些confidence<conf_thres=0.5的檢測結果。

然後再進一步進行nms,得到最後的輸出結果。即爲每一個目標只有一個框輸出。

四.網絡結構詳解

1.新的網絡結構Darknet-53

在基本的圖像特徵提取方面,YOLO3採用了稱之爲Darknet-53的網絡結構(含有53個卷積層),它借鑑了殘差網絡residual network的做法,在一些層之間設置了快捷鏈路(shortcut connections)。

從第0層一直到74層,一共有53個卷積層,其餘爲res層。這就是Joseph Redmon大神提出的darknet-53經典的卷積層了。作爲yolov3特徵提取的主要網絡結構。預訓練(以imagenet數據集爲訓練基礎)的權重文件可以通過官網下載。該結構使用一系列的3*3和1*1的卷積的卷積層。這些卷積層是從各個主流網絡結構選取性能比較好的卷積層進行整合得到。它比darknet-19效果好很多,同時,它在效果更好的情況下,是resnet-101效率的1.5倍,幾乎與resnet-152的效果相同的情況下,保持2倍於resnet-152的效率。

res層(shortcut操作):
layer filters size input output
4 res 1 208 x 208 x 64 -> 208 x 208 x 64
res層:
輸入與輸出:輸入與輸出一般保持一致,並且不進行其他操作,只是求差。
處理操作:res層來源於resnet,爲了解決網絡的梯度彌散或者梯度爆炸的現象,提出將深層神經網絡的逐層訓練改爲逐階段訓練,將深層神經網絡分爲若干個子段,每個小段包含比較淺的網絡層數,然後用shortcut的連接方式使得每個小段對於殘差進行訓練,每一個小段學習總差(總的損失)的一部分,最終達到總體較小的loss,同時,很好的控制梯度的傳播,避免出現梯度消失或者爆炸等不利於訓練的情形。

 2.YOLO部分
從75到105層我爲yolo網絡的特徵交互層,分爲三個尺度,每個尺度內,通過卷積核的方式實現局部的特徵交互,作用類似於全連接層但是是通過卷積核(3*3和1*1)的方式實現feature map之間的局部特徵(fc層實現的是全局的特徵交互)交互。

最小尺度yolo層:

  • 輸入:13*13的feature map ,一共1024個通道。
  • 操作:一系列的卷積操作,feature map的大小不變,但是通道數最後減少爲75個。
  • 輸出;輸出13*13大小的feature map,75個通道,在此基礎上進行分類和位置迴歸。

中尺寸yolo層:

  • 輸入:將79層的13*13、512通道的feature map進行卷積操作,生成13*13、256通道的feature map,然後進行上採樣,生成26*26、256通道的feature map,同時於61層的26*26、512通道的中尺度的feature map合併。再進行一系列卷積操作,
  • 操作:一系列的卷積操作,feature map的大小不變,但是通道數最後減少爲75個。
  • 輸出:26*26大小的feature map,75個通道,然後在此進行分類和位置迴歸。

大尺度的yolo層:

  • 輸入:將91層的26*26、256通道的feature map進行卷積操作,生成26*26、128通道的feature map,然後進行上採樣生成52*52、128通道的feature map,同時於36層的52*52、256通道的中尺度的feature map合併。再進行一系列卷積操作,
  • 操作:一系列的卷積操作,feature map的大小不變,但是通道數最後減少爲75個。
  • 輸出:52*52大小的feature map,75個通道,然後在此進行分類和位置迴歸。

                       

9種尺度的先驗框

隨着輸出的特徵圖的數量和尺度的變化,先驗框的尺寸也需要相應的調整。YOLO2已經開始採用K-means聚類得到先驗框的尺寸,YOLO3延續了這種方法,爲每種下采樣尺度設定3種先驗框,總共聚類出9種尺寸的先驗框。在COCO數據集這9個先驗框是:(10x13),(16x30),(33x23),(30x61),(62x45),(59x119),(116x90),(156x198),(373x326)。

分配上,在最小的13*13特徵圖上(有最大的感受野)應用較大的先驗框(116x90),(156x198),(373x326),適合檢測較大的對象。中等的26*26特徵圖上(中等感受野)應用中等的先驗框(30x61),(62x45),(59x119),適合檢測中等大小的對象。較大的52*52特徵圖上(較小的感受野)應用較小的先驗框(10x13),(16x30),(33x23),適合檢測較小的對象。

感受一下9種先驗框的尺寸,下圖中藍色框爲聚類得到的先驗框。黃色框式ground truth,紅框是對象中心點所在的網格。

                                                          

對象分類softmax改成logistic

預測對象類別時不使用softmax,改成使用logistic的輸出進行預測。這樣能夠支持多標籤對象(比如一個人有Woman 和 Person兩個標籤)。

                

   

不考慮神經網絡結構細節的話,總的來說,對於一個輸入圖像,YOLO3將其映射到3個尺度的輸出張量,代表圖像各個位置存在各種對象的概率。

我們看一下YOLO3共進行了多少個預測。對於一個416*416的輸入圖像,在每個尺度的特徵圖的每個網格設置3個先驗框,總共有 13*13*3 + 26*26*3 + 52*52*3 = 10647 個預測。每一個預測是一個(4+1+80)=85維向量,這個85維向量包含邊框座標(4個數值),邊框置信度(1個數值),對象類別的概率(對於COCO數據集,有80種對象)。

對比一下,YOLO2採用13*13*5 = 845個預測,YOLO3的嘗試預測邊框數量增加了10多倍,而且是在不同分辨率上進行,所以mAP以及對小物體的檢測效果有一定的提升。

 

 

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章