基于keras的Yolov3最全詳解
標簽: 目標檢測
參考Github源碼鏈接
Yolov3論文原文鏈接一,0二
Yolov3官網
最近在做Yolov3相關項目,看了很多資料。所以寫一篇總結體會,以便以后回顧查詢。
YOLO,即 You Only Look Once 的縮寫,是一個基于卷積神經網絡(CNN)的目標檢測算法 。
yolo設計理念
yolo算法整體來說是采用CNN對目標進行end-to-end的檢測。流程如圖所示
具體來說(基于YOLOV3)
- 輸入一張任意大小圖片,保持長寬比不變的情況下,縮放至 w 或 h達到416,再覆蓋在416 * 416的新圖上,作為網絡的輸入。即網絡的輸入是一張416 * 416,3通道的RGB圖。
- 運行網絡。YOLO的CNN網絡把圖片分成 S * S 個網格(yolov3多尺度預測,輸出3層,每層 S * S個網格,分別為13 * 13 ,26 * 26 ,52 * 52),然后每個單元格負責去檢測那些中心點落在該格子內的目標,如圖二所示。 每個單元格需要預測3*(4+1+B)個值。如果將輸入圖片劃分為 SS 網格,那么每層最終預測值為 SS3(4+1+B) 大小的張量。類別數(coco集為80類),即B=80. 3 為每層anchorbox數量,4 為邊界框大小和位置(x , y , w ,h )1 為置信度。
- 通過NMS,非極大值抑制,篩選出框boxes,輸出框class_boxes和置信度class_box_scores,再生成類別信息classes,生成最終的檢測數據框,并返回
Yolov3網絡結構圖
下面講一下訓練樣本的設置和loss的計算。
訓練樣本設置
參考上面圖2,對于一個輸入圖像,比如4164163,相應的會輸出 13133 + 26263 + 52523 = 10647 個預測框。我們希望這些預測框的信息能夠盡量準確的反應出哪些位置存在對象,是哪種對象,其邊框位置在哪里。
在設置標簽y(10647個預測框 * (4+1+類別數) 張量)的時候,YOLO的設計思路是,對于輸入圖像中的每個對象,該對象實際邊框(groud truth)的中心落在哪個網格,就由該網格負責預測該對象。不過,由于設計了3種不同大小的尺度,每個網格又有3個先驗框,所以對于一個對象中心點,可以對應9個先驗框。但最終只選擇與實際邊框IOU最大的那個先驗框負責預測該對象(該先驗框的置信度=1),所有其它先驗框都不負責預測該對象(置信度=0)。同時,該先驗框所在的輸出向量中,邊框位置設置為對象實際邊框,以及該對象類型設置為1。
loss計算
loss主要有3個部分,置信度、邊框位置、對象類型。
首先需要注意的還是置信度的問題。上面說到對于一個實際對象,除了與它IOU最大的那個先驗框其置信度設為1,其它先驗框的置信度都是0。但是,還有一些先驗框與該對象實際邊框位置是比較接近的,它們依然有可能檢測到該對象,只不過并非最接近實際邊框。所以,這部分邊框的目標置信度不應該期望輸出0。但YOLO也不希望它們輸出1。所以,在計算loss的時候,就設置一個IOU閾值,超過閾值的(接近目標邊框但又不是IOU最大的)那些邊框不計入loss。低于閾值的那些邊框就要求置信度為0,也就是檢測到背景。
同時,對于檢測到對象的邊框,要計算其邊框位置的loss,以及對象類型的loss。對于那些檢測到背景的邊框,就只計算其置信度loss了,它的邊框位置和對象類型都沒有意義。
另外注意一下的是邊框位置計算要根據論文的設計做一些變換,參考下面圖。
anchor box:
yolov3 anchor box一共有9個,由k-means聚類得到。在COCO數據集上,9個聚類是:(10 * 13);(16 * 30);(33 * 23);(30 * 61);(62 * 45); (59 * 119); (116 * 90); (156 * 198); (373 * 326)。
不同尺寸特征圖對應不同大小的先驗框。
13 * 13feature map對應【(116 * 90),(156 * 198),(373 * 326)】
26 * 26feature map對應【(30 * 61),(62 * 45),(59 * 119)】
52 * 52feature map對應【(10 * 13),(16 * 30),(33 * 23)】
原因:
- 特征圖越大,感受野越小。對小目標越敏感,所以選用小的anchor box。
- 特征圖越小,感受野越大。對大目標越敏感,所以選用大的anchor box。
邊框預測:
預測tx ty tw th
對tx和ty進行sigmoid,并加上對應的offset(下圖Cx, Cy)
對th和tw進行exp,并乘以對應的錨點值
對tx,ty,th,tw乘以對應的步幅,即:416/13, 416 ? 26, 416 ? 52
最后,使用sigmoid對Objectness和Classes confidence進行sigmoid得到0~1的概率,之所以用sigmoid取代之前版本的softmax,原因是softmax會擴大最大類別概率值而抑制其他類別概率值
(tx,ty) :目標中心點相對于該點所在網格左上角的偏移量,經過sigmoid歸一化。即值屬于【0,1】。如圖約(0.3 , 0.4)
(cx,cy):該點所在網格的左上角距離最左上角相差的格子數。如圖(1,1)
(pw,ph):anchor box 的邊長
(tw,th):預測邊框的寬和高
PS:最終得到的邊框坐標值是bx,by,bw,bh.而網絡學習目標是tx,ty,tw,th
Loss
YOLOv3中有一個參數是ignore_thresh,在ultralytics版版的YOLOv3中對應的是train.py文件中的iou_t參數(默認為0.225)。
正負樣本是按照以下規則決定的:
- 如果一個預測框與所有的Ground Truth的最大IoU<ignore_thresh時,那這個預測框就是負樣本。
- 如果Ground Truth的中心點落在一個區域中,該區域就負責檢測該物體。將與該物體有最大IoU的預測框作為正樣本(注意這里沒有用到ignore thresh,即使該最大IoU<ignore thresh也不會影響該預測框為正樣本)
在YOLOv3中,Loss分為三個部分:
- 一個是xywh部分帶來的誤差,也就是bbox帶來的loss ,在ultralytics版版的YOLOv3中,使用的是GIOU
- 一個是置信度帶來的誤差,也就是obj帶來的loss。lobj代表置信度,即該bounding box中是否含有物體的概率。在yolov3代碼中obj loss可以通過arc來指定,有兩種模式:
如果采用default模式,使用BCEWithLogitsLoss,將obj loss和cls loss分開計算:
BCEobj = nn.BCEWithLogitsLoss(pos_weight=ft([h['obj_pw']]), reduction=red)
if 'default' in arc: # separate obj and cls
lobj += BCEobj(pi[..., 4], tobj) # obj loss
# pi[...,4]對應的是該框中含有目標的置信度,和giou計算BCE
# 相當于將obj loss和cls loss分開計算
如果采用BCE模式,使用的也是BCEWithLogitsLoss, 計算對象是所有的cls loss:
BCE = nn.BCEWithLogitsLoss(reduction=red)
elif 'BCE' in arc: # unified BCE (80 classes)
t = torch.zeros_like(pi[..., 5:]) # targets
if nb:
t[b, a, gj, gi, tcls[i]] = 1.0 # 對應正樣本class置信度設置為1
lobj += BCE(pi[..., 5:], t)#pi[...,5:]對應的是所有的class
- 最后一個是類別帶來的誤差,也就是class帶來的loss。如果是單類的情況,cls loss=0,如果是多類的情況,也分兩個模式:
如果采用default模式,使用的是BCEWithLogitsLoss計算class loss。
BCEcls = nn.BCEWithLogitsLoss(pos_weight=ft([h['cls_pw']]), reduction=red)
# cls loss 只計算多類之間的loss,單類不進行計算
if 'default' in arc and model.nc > 1:
t = torch.zeros_like(ps[:, 5:]) # targets
t[range(nb), tcls[i]] = 1.0 # 設置對應class為1
lcls += BCEcls(ps[:, 5:], t) # 使用BCE計算分類loss
如果采用CE模式,使用的是CrossEntropy同時計算obj loss和cls loss。
CE = nn.CrossEntropyLoss(reduction=red)
elif 'CE' in arc: # unified CE (1 background + 80 classes)
t = torch.zeros_like(pi[..., 0], dtype=torch.long) # targets
if nb:
t[b, a, gj, gi] = tcls[i] + 1 # 由于cls是從零開始計數的,所以+1
lcls += CE(pi[..., 4:].view(-1, model.nc + 1), t.view(-1))
# 這里將obj loss和cls loss一起計算,使用CrossEntropy Loss
三部分總結下來就是下圖:
智能推薦
Django 單步調試
為什么80%的碼農都做不了架構師?>>> 最近在用 django 寫 應用,發現不好進行單步調試. 不過總算 找到個可以進行單步調試的 插件Django-Pdb 好了,現在說說這個插件是如何使用的. 這是下載鏈接 首先,下載 下來解壓出來 python setup.py install 安裝好后, 在你應用里面 設置 然后在你需要調試的視圖 ...
在下函數式編程,有何貴干?
聲明:本文CSDN作者原創投稿文章,未經許可禁止任何形式的轉載。 作者:徐鴻福,多年后端及移動端開發經驗,現任MaxLeap UX團隊成員,主要從事于Android相關開發,目前對Kotlin和Ruby有濃厚興趣。 責編: 錢曙光,關注架構和算法領域,尋求報道或者投稿請發郵件q[email protected],另有「CSDN 高級架構師群」,內有諸多知名互聯網公司的大牛架構師,歡迎架構師加微信qsh...
kettle8調度監控平臺(kettle-scheduler)開源
背景 Kettle作為用戶規模最多的開源ETL工具,強大簡潔的功能深受廣大ETL從業者的歡迎。但kettle本身的調度監控功能卻非常弱。Pentaho官方都建議采用crontab(Unix平臺)和計劃任務(Windows平臺)來完成調度功能。所以大家在實施kettle作業調度功能的時候,通常采用以下幾種方式:使用spoon程序來啟動Job,使用crontab或計劃任務,自主開發java程序來調用k...
可持久化數據結構
可持久化的前提:本身拓撲結構不變 可持久化解決問題:記錄數據結構的所有歷史版本 核心思想:只記錄每一個版本與上一個版本不一樣的地方 如線段樹:每次修改最多logn點 可持久化trie樹 上一個版本的trie樹種有這個字母的指針就直接copy過來,沒有當前版本就新開一個指針。 數據最多 2242^{24}224 ,每次最多加 252525 個點,所以開 252525 倍數組 如果超過了題目所限我們可...
猜你喜歡
vscode實用插件和配置
vscode前段實用插件集合 小編進過一段時間的使用得出的最適合剛上手vscode的實用插件如下: 這里對這些插件就不一一的解釋了,大部分為代碼智能提示和補全,有些會使代碼變工整,也有的可以使重要部分改變顏色,以及編輯后瀏覽器打開等等。 順帶附上vscode個人設置的代碼(不知道位置的可以在設置中搜setting,settings.json就是的) 一個是用于ctrl+滾軸可以放大代碼,一個是用于...
品優購項目靜態頁面應用中總結(京東)
1、line-height 行高=高度:垂直居中 行高<高度:文字偏上 行高>高度:文字偏下 2、添加字體圖標 將字體的font文件夾放入根目錄下 在樣式里聲明自定義字體(注意路徑的正確) 利用CSS3偽元素選擇器給元素添加字體圖標,利用子絕父相確定位置...
kNN_約會網站匹配效果改進實現代碼
kNN_約會網站匹配效果改進 【準備數據】數據處理函數 【分析數據】繪制數據散點圖 由數據兩兩對比的三幅散點圖分布可知,取第一列和第二列為x,y軸繪制散點圖(圖一)時,三種類型的人基本分屬于不同的區域。 注:用scatter繪制散點圖時,當數據在列表中未分類時,無法按照顏色給出圖例。 想要顯示圖例,需對數據進行分類,然后分別用不同的scatter繪制,則可有不同分類的圖例。 【準備數據】歸一化特征...
[數據結構]快速排序算法JavaScript版
快排基本思路 找出一個切割點 找到切割點左右部分的切割點,直到每個被分割的小團體只含一個數字 原理講解 在這里我們有一個長度為7的無規則數字數組,我們將用快排的方法將它從小到大排序。 第一步——找到切割點 一般地,我們選用團體中的第一個元素為切割點,在上圖中即為2 第二步——以切割點為主體,逐個比較大小并重新置位 因為我們是比較切割點與其他元素的大小...