(寫在前面:若是你想 run 起來,立馬想看看效果,那就直接跳轉到最後一張,動手實踐,看告終果再來往前看吧,開始吧······)python
這裏再也不贅述,以前的個人一個 GitChat 詳盡的講述了整個代碼段的含義,以及如何一步步的去實現它linux
V1 版本的缺陷和不足,就是 V2 版本出現的源泉與動力,而 V1 版本究竟在哪些地方是它的短板之處呢:算法
V1 缺陷之處:shell
- 輸入尺寸固定:因爲輸出層爲全鏈接層,所以在檢測時,YOLO 訓練模型只支持與訓練圖像相同的輸入分辨率。其它分辨率須要縮放成此固定分辨率;
- 佔比較小的目標檢測效果很差:雖然每一個格子能夠預測 B 個 bounding box,可是最終只選擇只選擇 IOU 最高的 bounding box 做爲物體檢測輸出,即每一個格子最多隻預測出一個物體。當物體佔畫面比例較小,如圖像中包含畜羣或鳥羣時,每一個格子包含多個物體,但卻只能檢測出其中一個。
2.1 anchor box 的思想引入網絡
爲提升物體定位精準性和召回率,YOLO 做者提出了 《YOLO9000: Better, Faster, Stronger》 (Joseph Redmon, Ali Farhadi, CVPR 2017, Best Paper Honorable Mention),也就是 YOLOv2 的論文全名,相比 v1 提升了訓練圖像的分辨率;引入了 faster rcnn 中 anchor box 的思想,對網絡結構的設計進行了改進,使得模型更易學習。框架
什麼是(候選區域框)anchor box?dom
假設特徵能夠看作一個尺度 6448 像素的 256 通道圖像,對於該圖像的每個位置,考慮 9 個可能的候選窗口:三種面積三種比例。這些候選窗口稱爲 anchors。下圖示出 6448 圖像 anchor 中心,在每一個面積尺寸下,取三種不一樣的長寬比例(1:1,1:2,2:1),這樣一來,咱們獲得了一共 9 種面積尺寸各異的 anchor。示意圖以下:函數
以一個點 9 種尺寸來取 proposal,重複區域多。並且 feature map 相鄰兩個點對應原圖的 9 個 proposal 也是不少重複區域。只是整個 faster RCNN 中的第一步,只是對候選區域進行提取 (RPN, region proposal networks, 候選區域生成網絡)。這個過程只是但願可以獲得覆蓋目標的候選區域,因此有不一樣尺寸不一樣比例的 proposal(這樣纔有最大可能能夠在一個候選框中包括完整的目標)。而在這以後,確實會有不少重複區域,而這實際上是候選區域生成以後的下一個問題。針對這個問題,通常會採用非極大值抑制算法進行去重 (NMS, non maximum suppression)。工具
至於這個 anchor 究竟是怎麼用的,這個是理解整個問題的關鍵。學習
下面是整個 faster RCNN 結構的示意圖:
輸入圖像不管是什麼大小的樣本,都要轉化爲 224*224(可根據狀況本身設定)大小的圖片,送進網絡進行訓練。( 爲何要固定輸入網絡圖片尺寸呢?後面解釋。)
對於每一個 3x3 的窗口,做者就計算這個滑動窗口的中心點所對應的原始圖片的中心點。而後做者假定,這個 3x3 窗口,是從原始圖片上經過 SPP 池化 獲得的,而這個池化的區域的面積以及比例,就是一個個的 anchor。換句話說,對於每一個 3x3 窗口,做者假定它來自 9 種不一樣原始區域的池化,可是這些池化在原始圖片中的中心點,都徹底同樣。這個中心點,就是剛纔提到的,3x3 窗口中心點所對應的原始圖片中的中心點。如此一來,在每一個窗口位置,咱們均可以根據 9 個不一樣長寬比例、不一樣面積的 anchor,逆向推導出它所對應的原始圖片中的一個區域,這個區域的尺寸以及座標,都是已知的。而這個區域,就是咱們想要的 proposal。因此咱們經過滑動窗口和 anchor,成功獲得了 51x39x9 個原始圖片的 proposal。接下來,每一個 proposal 咱們只輸出 6 個參數:每一個 proposal 和 ground truth 進行比較獲得的前景機率和背景機率 (2 個參數)(對應圖上的 clsscore);因爲每一個 proposal 和 ground truth 位置及尺寸上的差別,從 proposal 經過平移放縮獲得 ground truth 須要的 4 個平移放縮參數(對應圖上的 bboxpred)。
爲何以前的 CNN 要固定輸入網絡圖片尺寸呢?
CNN 大致包含 3 部分:卷積、池化、全鏈接
- 卷積層。卷積操做對圖片輸入的大小會有要求嗎?好比一個 5 * 5 的卷積核,我輸入的圖片是 30 * 81 的大小,能夠獲得 (26,77) 大小的圖片,並不會影響卷積操做。我輸入 600 * 500,它仍是照樣能夠進行卷積,也就是卷積對圖片輸入大小沒有要求,只要你喜歡,任意大小的圖片進入,均可以進行卷積。
- 池化層。池化對圖片大小會有要求嗎?好比我池化大小爲(2,2)我輸入一張 30 * 40 的,那麼通過池化後能夠獲得 15 * 20 的圖片。輸入一張 53 * 22 大小的圖片,通過池化後,我能夠獲得 26 * 11 大小的圖片。所以池化這一步也沒對圖片大小有要求。只要你喜歡,輸入任意大小的圖片,均可以進行池化。
- 全鏈接層。既然池化和卷積都對輸入圖片大小沒有要求,那麼就只有全鏈接層對圖片結果又要求了。由於全鏈接層咱們的鏈接勸值矩陣的大小 W,通過訓練後,就是固定的大小了,好比咱們從卷積到全連層,輸入和輸出的大小,分別是 50、30 個神經元,那麼咱們的權值矩陣(50,30)大小的矩陣了。所以空間金字塔池化,要解決的就是從卷積層到全鏈接層之間的一個過分。
這裏插入卷積、池化層的輸入輸出計算方法:
例子計算詳情
怎麼改變這個現狀呢,也就是不管輸入圖片是什麼大小,不須要都轉化爲統一大小的圖片,再送入網絡的預處理過程。這就出現了大神何凱明的 CNN 應用之 SPP。空間金字塔池化的卷積神經網絡物體檢測,很詳細,能看懂其中緣由和機理,不贅述。
2.2 YOLOv2 多處改進
2.2.1 輸出層使用卷積層替代 YOLOv1 的全鏈接層
附 darknet-19 的結構表:
包含 19 conv + 5 maxpooling。用 1x1 卷積層替代 YOLOv1 的全鏈接層。
1x1 卷積層(此處 1x1 卷積層的存在是爲了跨通道信息整合)如上圖的紅色矩形框部分。
引入一點:YOLO,YOLOv二、YOLO9000,Darknet-19,Darknet-53,YOLOv3 分別是什麼關係?
- YOLOv2 是 YOLO 的升級版,但並非經過對原始加深或加寬網絡達到效果提高,反而是簡化了網絡。
- YOLO9000 是 CVPR2017 的最佳論文提名。首先講一下這篇文章一共介紹了 YOLOv2 和 YOLO9000 兩個模型,兩者略有不一樣。前者主要是 YOLO 的升級版,後者的主要檢測網絡也是 YOLOv2,同時對數據集作了融合,使得模型能夠檢測 9000 多類物體。而提出 YOLO9000 的緣由主要是目前檢測的數據集數據量較小,所以利用數量較大的分類數據集來幫助訓練檢測模型。
- YOLOv2 使用了一個新的分類網絡做爲特徵提取部分,參考了前人的先進經驗,好比相似於 VGG,做者使用了較多的 3 * 3 卷積核,在每一次池化操做後把通道數翻倍。借鑑了 network in network 的思想,網絡使用了全局平均池化(global average pooling),把 1 * 1 的卷積核置於 3 * 3 的卷積核之間,用來壓縮特徵。也用了 batch normalization(前面介紹過)穩定模型訓練。最終得出的基礎模型就是 Darknet-19,如上圖,其包含 19 個卷積層、5 個最大值池化層(maxpooling layers )
2.2.2 卷積層所有使用 Batch Normalization
v1 中也大量用了 Batch Normalization,同時在定位層後邊用了 dropout,v2 中取消了 dropout,在卷積層所有使用 Batch Normalization。
2.2.3 K-Means 算法
咱們知道在 Faster R-CNN 中 anchor box 的大小和比例是按經驗設定的,而後網絡會在訓練過程當中調整 anchor box 的尺寸。可是若是一開始就能選擇到合適尺寸的 anchor box,那確定能夠幫助網絡越好地預測 detection。因此做者採用 k-means 的方式對訓練集的 bounding boxes 作聚類,試圖找到合適的 anchor box。
另外做者發現若是採用標準的 k-means(即用歐式距離來衡量差別),在 box 的尺寸比較大的時候其偏差也更大,而咱們但願的是偏差和 box 的尺寸沒有太大關係。因此經過 IOU 定義了以下的距離函數,使得偏差和 box 的大小無關:
Faster R-CNN 採用的是手選先驗框方法,YOLOv2 對其作了改進,採用 k-means 在訓練集 bbox 上進行聚類產生合適的先驗框. 因爲使用歐氏距離會使較大的 bbox 比小的 bbox 產生更大的偏差,而 IOU 與 bbox 尺寸無關, 所以使用 IOU 參與距離計算, 使得經過這些 anchor boxes 得到好的 IOU 分值。距離公式:
以下圖 Figure2,左邊是聚類的簇個數核 IOU 的關係,兩條曲線分別表明兩個不一樣的數據集。在分析了聚類的結果並平衡了模型複雜度與 recall 值,做者選擇了 K=5,這也就是 Figure2 中右邊的示意圖是選出來的 5 個 box 的大小,這裏紫色和黑色也是分別表示兩個不一樣的數據集,能夠看出其基本形狀是相似的。並且發現聚類的結果和手動設置的 anchor box 大小差異顯著。聚類的結果中可能是高瘦的 box,而矮胖的 box 數量較少。
K-Means 算法概述:k-means 是非監督學習中的聚類算法; 基本 K-Means 算法的思想很簡單,事先肯定常數 K,常數 K 意味着最終的聚類類別數,首先隨機選定初始點爲質心,並經過計算每個樣本與質心之間的類似度 (這裏爲歐式距離),將樣本點歸到最類似的類中,接着,從新計算每一個類的質心 (即爲類中心),重複這樣的過程,知道質心再也不改變,最終就肯定了每一個樣本所屬的類別以及每一個類的質心。因爲每次都要計算全部的樣本與每個質心之間的類似度,故在大規模的數據集上,K-Means 算法的收斂速度比較慢。
使用聚類進行選擇的優點是達到相同的 IOU 結果時所需的 anchor box 數量更少, 使得模型的表示能力更強, 任務更容易學習。
2.2.4 Multi-Scale Training
和 YOLOv1 訓練時網絡輸入的圖像尺寸固定不變不一樣,YOLOv2(在 cfg 文件中 random=1 時)每隔幾回迭代後就會微調網絡的輸入尺寸。訓練時每迭代 10 次,就會隨機選擇新的輸入圖像尺寸。由於 YOLOv2 的網絡使用的 downsamples 倍率爲 32,因此使用 32 的倍數調整輸入圖像尺寸 {320,352,…,608}。訓練使用的最小的圖像尺寸爲 320 x 320,最大的圖像尺寸爲 608 x 608。 這使得網絡能夠適應多種不一樣尺度的輸入。更多詳細的資料可查看這裏目標檢測之 YOLOv3,YOLOv3 纔是全文的的重點。
這裏給出官方的 YOLOv2 與其它模型在 VOC 2007 數據集上的效果對比
本文的重點,先一張圖看看 V3 版本的強大
橫軸是每張圖像的預測推理時間,單位 ms。縱軸是在 COCO 數據集上預測的 mAP@0.5 的精度。不管是在耗費時間,仍是預測精度上面,v3 版本都完賽過去的一些模型。
darknet-53 模型
注:YOLO Detection 層: 座標及類別結果輸出層;Region 82,Region 94,Region 106。
YOLOv3 的改進之處:多尺度預算
座標預測:bbox 預測還是 yolov2 的使用維度聚類(dimension clusters )做爲 anchor boxes 來預測邊界框. 在訓練期間,咱們使用平方偏差損失的總和。
對象分數:YOLOv3 使用邏輯迴歸預測每一個邊界框(bounding box)的對象分數。 若是先前的邊界框比以前的任何其餘邊界框重疊 ground truth 對象,則該值應該爲 1。若是之前的邊界框不是最好的,可是確實將 ground truth 對象重疊了必定的閾值以上,咱們會忽略這個預測,按照 [15] 進行。咱們使用閾值 0.5。與 [15] 不一樣,咱們的系統只爲每一個 ground truth 對象分配一個邊界框。若是先前的邊界框未分配給 grounding box 對象,則不會對座標或類別預測形成損失。
類別預測:每一個框使用多標籤分類來預測邊界框可能包含的類。在訓練過程當中,使用二元交叉熵損失來進行類別預測。
補充:Darknet 框架 Darknet 由 C 語言和 CUDA 實現, 對 GPU 顯存利用效率較高 (CPU 速度差一些, 經過與 SSD 的 Caffe 程序對比發現存在 CPU 較慢,GPU 較快的狀況). Darknet 對第三方庫的依賴較少, 且僅使用了少許 GNU linux 平臺 C 接口, 所以很容易移植到其它平臺, 如 Windows 或嵌入式設備.
來開始本文的重中之重吧——
第一步:首先根據官網提示,一步步的走一遍,直到可以訓練 VOC 數據集,就能夠停下來歇歇了。官網點這裏穿越若是一塊兒正常,恭喜你,就能夠開始以後的步驟了。固然有興趣想了解 YOLOv3 中設計上的更多細節,能夠去看下詼諧幽默的論文,點這裏,看 YOLOv3: An Incremental Improvement後面也會就論文中和修改中的一些聯繫,作個解釋。
第二步:上面作完,只是說明你能夠檢測和訓練了官方的圖片數據集,下面開始本身的數據集。
注意點: 若是你的電腦設備是有 GPU 加速圖像運算的,那樣在第一步中,默認的仍是 CPU 下的訓練,想要使用 GPU 就要改 Makefile 文件這裏了
這是我這一個博客中看到的,將紅色框圈中的部分改成 1,修改了以後,在 darknet 文件目錄下 make clean 清除以前的 make 文件,從新 make,發現速度明顯提升,使用上了 GPU 訓練。(其實在以前第一次我從新 make 時候報 opencv 錯誤,後來儘管發錯 opencv 沒有安裝好,make 也經過了,對這個沒有影響,就沒有太關注這裏了,有經驗的求告知)。相同的命令,再來訓練一次 VOC 數據試試看,速度是否是提升槓槓的。
第三步:數據集的採集,製做標籤,這塊還參考手把手實踐 YOLO 深度殘差神經網絡拐點檢測,一句話也就是 labelImg 標記軟件工具了,具體不詳述了。其中有一點就是 ImageSets/Main/ 文件夾下的 train.txt,test.txt,val.txt,這裏的文件須要改成本身待訓練的圖片全部名字編號,在生成待訓練的 train.txt 大有用處。
第四步:對待訓練初始配置參數進行修改
**改動一 **
首先肯定你須要作幾個類別的物體檢測,也就是 classes=1,仍是 classes=5 或者 7,或者 20。我這裏待檢測的類別爲一類,因此 classes=1, 以下圖的 cfg 文件夾下的.data 文件:
將 VOC 格式的 xml 文件轉換成 YOLO 格式的 txt 文件。
沒改以前直接使用,會出現這個錯誤提示(訓練和檢測報錯都有):
改動就是在這裏修改:
make 命令百科
在軟件開發中,make 是一個工具程序(Utility software),經由讀取叫作「makefile」的文件,自動化建構軟件。它是一種轉化文件形式的工具,轉換的目標稱爲「target」;與此同時,它也檢查文件的依賴關係,若是須要的話,它會調用一些外部軟件來完成任務。它的依賴關係檢查系統很是簡單,主要根據依賴文件的修改時間進行判斷。大多數狀況下,它被用來編譯源代碼,生成結果代碼,而後把結果代碼鏈接起來生成可執行文件或者庫文件。它使用叫作「makefile」的文件來肯定一個 target 文件的依賴關係,而後把生成這個 target 的相關命令傳給 shell 去執行。
許多現代軟件的開發中 (如 Microsoft Visual Studio),集成開發環境已經取代 make,可是在 Unix 環境中,仍然有許多任務程師採用 make 來協助軟件開發。
**改動二 **
cfg 文件夾下的.cfg 文件,有不少,用到的只是 yolov3-voc.cfg(如今還不知作別的.cfg 文件該怎麼用,求指點,因而我把別的文件全刪除了,只留下 coco.data 和 yolov3-voc.cfg)一切正常,還沒發現出錯。刪了 -- 更名,就這樣了(改了名以後報錯?就須要改動一處的指示了,回看改動一)
最重要的改動,是在 my_yolov3.cfg(已圖片處的名字爲例)下的參數,欲知詳情,娓娓道來······
如圖:
YOLOv3 預測 3 個不一樣尺度的 box
咱們的系統使用相似的概念以金字塔網絡(SPP)從這些量表中提取特徵。最後一層網絡預測一個 3D 張量編碼的邊界框,對象和類的預測(classes)。COCO 試驗中,咱們預測每一個尺度上的 3 個盒子,因此這個張量是 NN3(4+1+80)的 4 個邊界框偏移量,1 個目標預測,和 80 個類的預測。若是 classes=1,也就是上面的 my_yolov3.data,文件裏面定義的,此時的最後一層 filters=3*(4+1+1)=18。
論文對最後一層網絡的解釋以下
第五步:Now we can train my target_yolo!
參考這個官方提示來作對應的修改,改成本身的命名形式,若是仍是不行,恐怕就是你的 make 步驟沒有作。make clean-- --make
具體的輸出詳解
Region Avg IOU: ----0.326577 is the average of the IOU of every image in the current subdivision. A 32,66% overlap in this case, this model still requires further training. Class: -----0.742537 still figuring this out Obj: -----0.033966 still figuring this out No Obj:----- 0.000793 still figuring this out The Avg Recall:------ 0.12500 is defined in code as recall/count, and thus a metric for how many positives YOLOv2 detected out of the total amount of positives in this subdivision. In this case only one of the eight positives was correctly detected. count: -----8 is the amount of positives (objects to be detected) present in the current subdivision of images (subdivision with size 8 in our case). Looking at the other lines in the log, you'll see there are also subdivision that only have 6 or 7 positives, indicating there are images in that subdivision that do not contain an object to be detected.
若是不幸,輸出的是這個樣子
那就是你在 2.1.1 節時候,把 Training or Testing 註釋錯了,更改下,再試試。
若是成功了,那就出去溜溜等着吧,記得回來看看 loss 參數,迭代輸出像這樣
9798----- indicates the current training iteration/batch. 0.370096 -----is the total loss. 0.451929 ------avg is the average loss error, which should be as low as possible. As a rule of thumb, once this reaches below 0.060730 avg, you can stop training. 0.001000----- rate represents the current learning rate, as defined in the .cfg file. 3.300000 -----seconds represents the total time spent to process this batch. The 627072 -----images at the end of the line is nothing more than 9778 * 64, the total amount of images used during training so far.
序列測試,這裏將 cfg/myyolov3.data 進行修改,加入 valid 的測試序列地址,從新 python voclabel.py
valid 測試
./darknet detector valid cfg/myyolov3.data cfg/myyolov3.cfg backup/yolo-voc_final.weights
/在終端只返回用時,在./results/comp4dettest_[類名].txt 裏保存測試結果/
打開查看內容
依次表示的是:文件名;每一個框中存在該分類物體的機率;框框座標 xmin;框框座標 ymin;框框座標 xmax;框框座標 ymax,代碼區以下截圖,位置 examples/detector.c
固然也有別的測試方式,並返回評價指標,如圖,可本身嘗試