mmdetection最小復(fù)刻版(四):獨家yolo轉(zhuǎn)化內(nèi)幕
AI編輯:深度眸
0 摘要
github地址:
https://github.com/hhaAndroid/mmdetection-mini
? ? 本文深入講解將darnket模型權(quán)重轉(zhuǎn)化為mmdetection中模型和權(quán)重以及yolov5轉(zhuǎn)化為mmdetection的心路歷程,其中有淚、有汗還有無盡的心酸,不過好在最好都解決了。通過本文你可以了解其中的每個細節(jié)。在這其中,踩了很多坑,我會一一說明。只要掌握了這套轉(zhuǎn)化流程,那么任何darknet中的模型或者yolov5代碼中的模型,你都可以自己轉(zhuǎn)化到mmdetection-mini中。那么為何要轉(zhuǎn)化呢?好處是啥?我個人覺得應(yīng)該可以歸納如下:
(1) 徹底掌握算法模型
? ? darknet采用文件cfg模式來構(gòu)建模型,好處是不用會寫代碼也可以寫模型,壞處也比較明顯:
????1. 切分過細,從頭構(gòu)建大模型會累死,且容易出錯
????2. 采用索引形式來進行跳層連接,不太好把握結(jié)構(gòu)
????3. 配置過長,無法把握網(wǎng)絡(luò)設(shè)計的思想精華
????4. 不好調(diào)試,各層的連接關(guān)系在forward時候才能知道,比較麻煩
????5. 純c寫的,我c和c++語言只會皮毛
? ? 熟悉darknet的人應(yīng)該都有體會。而yolov5的github代碼不可謂不亂(大家知道的),雖然他是pytorch寫的,但是在構(gòu)建模型時候也是參考了darknet的cfg思想,開發(fā)比較快,但是對于用戶學(xué)習(xí)來說,不太友好。而一旦轉(zhuǎn)化為mmdetection框架來構(gòu)建pytorch模型,那么結(jié)構(gòu)就一目了然了,調(diào)試要多方便有多方便,哪里不會bug哪里,輕松愉快。
(2) 能夠掌握所有細節(jié)
? ? 很多時候,自己不寫一遍,其實不能算是掌握了,浮于表面。如果我能夠?qū)arknet模型或者yolov5模型轉(zhuǎn)化到mmdetection中,并且評估指標(biāo)mAP完全一致,那么我就必須理解每一個cfg內(nèi)容,理解每一個細節(jié)包括模型結(jié)構(gòu)、bbox編解碼、數(shù)據(jù)處理邏輯等等。這可以督促我分析更加底層的東西,對于學(xué)習(xí)來說是一個不錯的思路。
(3) 所有代碼統(tǒng)一到mmdetection-mini中
? ? 目前主流的darknet系列和yolov5系列,以及可能以后新出了的模型,都可以全部在mmdetection-mini中進行訓(xùn)練和測試,特別是基于darknet或者yolov5權(quán)重進行微調(diào)訓(xùn)練。不過目前我只完成了模型和測試步驟,從頭訓(xùn)練部分還沒有完成,這將是一個長期任務(wù)。
? ? 本來想這篇文章把yolov5心酸歷程也寫進去的,但是后來發(fā)現(xiàn)文字太多了,就放到下一篇吧!
1 darknet系列轉(zhuǎn)化過程
? ? 由于yolov2比較老了,性能和速度都無法和yolov3、tiny-yolov3相比,故這里不包括yolov2,具體是yolov3/yolov4以及tiny-yolo3/tiny-yolov4,一共4個模型。
? ? 剛開始我對darknet不熟悉,只是看cfg而已,darknet源碼是完全沒看過。如果你想找pytorch版本的yolo系列,github當(dāng)然也是不計其數(shù)。搜索yolov3,帶有pytorch的star最多的是eriklindernoren/PyTorch-YOLOv3庫,但是一旦打開model.py,如下所示:

? ? 很明顯,他也是直接解析yolov3.cfg來構(gòu)建模型的,而前面說過我比較不喜歡這個做法,所以這種方式我直接就放棄了。然后我找到了騰訊優(yōu)圖的目標(biāo)檢測庫
https://github.com/Tencent/ObjectDetection-OneStageDet,在當(dāng)時他就已經(jīng)實現(xiàn)了yolov2和yolov3系列了,他的模型構(gòu)建就是標(biāo)準(zhǔn)的pytorch寫法,通俗易懂,所以我一直沿用了這種做法。有了參考寫法,再配合darknet里面的cfg可以采用https://lutzroeder.github.io/netron/軟件直接可視化網(wǎng)絡(luò)結(jié)構(gòu),那么就可以動手了。通過netron可視化網(wǎng)絡(luò)結(jié)構(gòu),可以非常容易看出網(wǎng)絡(luò)結(jié)構(gòu)以及檢查自己寫的代碼是否正確,起到了極大的幫助。
? ? 我首先把ObjectDetection-OneStageDet代碼看了一遍并且跑了下,基本上了解了細節(jié)??紤]到y(tǒng)olov3模型太大了,不好搞,所以先拿tiny-yolov3開刀,一旦整個流程通了,那么新增yolov3那還不是手到擒來。
1.1 第一步:構(gòu)建模型
? ? 構(gòu)建tiny-yolov3模型,那實在是太簡單了,因為結(jié)構(gòu)非常簡單,為了快速實現(xiàn),我們可以模仿騰訊優(yōu)圖做法,如下所示,地址為https://github.com/Tencent/ObjectDetection-OneStageDet/blob/master/vedanet/network/backbone/_tiny_yolov3.py:

? ? 我開始也是按照這個寫法寫的,對應(yīng)框架代碼里面的
mmdet/models/backbones/rr_tiny_yolov3_backbone.py。tiny-yolov3是兩個輸出尺度,而不是三個,下采樣率為32和16。為了檢查代碼是否正確,我還使用了darknet的cfg文件進行可視化。下面就是構(gòu)建head了。head部分也非常簡單,就是對stride=32的分支采用上采樣層然后和stride=16的特征層進行concat操作即可:

整個模型就構(gòu)建好了。
1.2 第二步:權(quán)重轉(zhuǎn)化
? ? 構(gòu)建模型是非常容易的,可以直接抄騰訊優(yōu)圖的代碼,但是權(quán)重轉(zhuǎn)化就沒那么容易了,需要自己搞定。要將tiny-yolov3權(quán)重轉(zhuǎn)化到mmdetection-mini中,需要做以下幾件事情:
? (1) 熟悉darknet權(quán)重保存格式.weights
? (2) 權(quán)重轉(zhuǎn)化為pytorch結(jié)構(gòu)
(1) 熟悉weights權(quán)重保存格式及其讀取規(guī)則
? ??對于darknet保存的weights的格式解析,在網(wǎng)上有很多,我梳理了下大概就理解了,對應(yīng)代碼在mmdet/models/utils/brick.py里面的WeightLoader類中。整個權(quán)重文件其實是一個numpy矩陣,前幾個字節(jié)是一些版本以及head信息,后面開始才是權(quán)重,其格式為:
? ? (1) 如果僅僅是卷積層,那么存儲格式是先bias,然后采用卷積權(quán)重參數(shù)
? ? (2) 如果是conv+bn+激活,那么存儲格式是先bn的bias,weights,running_mean和running_var,然后才是卷積的bias,weights
? ? 明白這兩個就可以了,解析時候必須要按照這個格式來讀取,否則后果非常嚴(yán)重,后面會細說。并且必須以conv+bn+激活的組合格式來解析,因為darkent的最小配置單位就是這個,如果你在pytorch構(gòu)建模型時候,把conv和bn分開寫,那么解析難度會增加非常多,注意看我的yolo系列的最小模型單位是Conv2dBatchLeaky或者Conv2,目的就是為了解析方便。
(2) 構(gòu)建轉(zhuǎn)換腳本
? ? 理解了上面的流程,就大概知道咋弄了,但是為了轉(zhuǎn)換方便以及轉(zhuǎn)換本身就是僅僅運行一次即可,不需要每次跑訓(xùn)練都轉(zhuǎn)換一次,故我把tiny-yolov3在tools/darknet/tiny_yolov3.py里面copy了一遍,模型是一樣的,主要目的是:任何人先用這個腳本轉(zhuǎn)換一下模型,保存為mmdetection-mini能夠直接讀取的格式,然后在訓(xùn)練和測試時候就直接用轉(zhuǎn)換后的模型即可,而不再需要讀取darknet原始weights權(quán)重。
? ? tools/darknet/tiny_yolov3.py里面采用了WeightLoader類來加載darknet權(quán)重:

注意必須實現(xiàn)__modules_recurse方法,該方法的作用是遍歷復(fù)雜模型的每個子模塊,一定要遍歷到最小單位即conv+bn+激活或者conv,因為WeightLoader類的輸入必須是這兩個,否則無法解析。
? ? 下載darknet的tiny-yolov3權(quán)重,替換tiny_yolov3.py的權(quán)重路徑,運行即可。

(3) 打印結(jié)果檢查
? ? 打印信息如下,跑到這里,你需要檢查兩個部分:
? ? (1) 最后一行[8858734/8858734 weights],如果兩者不相等,說明你代碼寫錯了,因為權(quán)重沒有全部導(dǎo)入
? ? (2) 檢查Layer skipped的層是否是沒有參數(shù)的層,如果跳過了帶參數(shù)層,那么你一定寫錯了
到目前為止,一切都搞定了,tiny-yolov3的所有權(quán)重全部導(dǎo)入了,美好的一比,如果你這樣認(rèn)為,那你就大錯特錯了。
(4) 替換key
? ? 還有一個收尾的工作要做,這里保存的pth模型和mmdetection-mini里面的算法雖然一樣,但是模型的key是不一樣的,為了能夠在mmdetection-mini中直接跑,你還需要替換key,對于tiny-yolov3來說,稍微比較簡單,如下:

如果你想說我咋知道哪些key要替換?我的做法是:先去mmdetection-mini中把模型的所有key保存下來,然后和這里的key比對下就行了。工作雖然繁瑣一些,但是還是能接受的。
? ? 到這里為止,保存的pth就可以真的在mmdetection-mini中跑起來了。美好的一比,如果你這樣認(rèn)為,那你又大錯特錯了。
1.3 第三步: 結(jié)果檢查
? ? 前面都是準(zhǔn)備工作,模型也得到了,最核心的是驗證你轉(zhuǎn)化的模型進行推理時候效果對不對,可以從單張圖預(yù)測可視化和驗證集計算mAP兩個方面驗證。
? ? 先對單張圖進行推理,看下預(yù)測效果對不對吧。此時你可以發(fā)現(xiàn),基本上啥都預(yù)測不出來。這一步才是最要命的,搞了半天,各種確認(rèn),最后發(fā)現(xiàn)沒有效果?這個地方坑很多,我開始被坑了一天,出現(xiàn)這個原因的主要問題是還是對darknet框架不熟悉,下面我說下錯誤原因,有好幾個。
(1) 模型構(gòu)建順序不能錯
? ? 因為darknet里面的權(quán)重是沒有開始和結(jié)尾的numpy數(shù)組,你只能自己去切割數(shù)組,這就會帶來一個問題:假設(shè)原始模式是ConvBN_1+ConvBN_2,但是你在pytorch里面寫成了ConvBN_2+ConvBN_1,那么上面寫的整個過程都是不會報錯而且是正常的,但是實際上你寫錯了。例如你可以在tools/darknet/tiny-yolov3.py里面把:
self.layer0 = nn.ModuleList([nn.Sequential(layer_dict) for layer_dict in layer0])self.head0?=?nn.ModuleList([nn.Sequential(layer_dict)?for?layer_dict?in?head0])
順序調(diào)換,寫成:
self.head0 = nn.ModuleList([nn.Sequential(layer_dict) for layer_dict in head0])self.layer0 = nn.ModuleList([nn.Sequential(layer_dict) for layer_dict in layer0])
就是這么簡單,你再跑腳本,打印也是完全正確的,但是實際你錯的非常嚴(yán)重,因為權(quán)重切割錯了。
? ? 總的來說就是darkent里面的權(quán)重,保存順序完全按照cfg從上到下的順序,而不是網(wǎng)絡(luò)實際運行順序。如果你的解析順序不正確,那么即使網(wǎng)絡(luò)結(jié)構(gòu)寫對了,導(dǎo)入的權(quán)重也可能是錯誤的,因為不會報錯。
(2) head模型順序不能錯
? ? 要說明這個問題,tiny-yolov3說明不了問題,需要上大模型yolov3。yolov3是典型的darknet53+fpn+head的結(jié)構(gòu),一般我們在構(gòu)建模型時候,都是按照mmdetection-mini的做法來寫,例如head部分我們的寫法是:

這種寫法本身沒有問題,但是對于導(dǎo)入darknet權(quán)重來說就不行了,因為yolov3里面的配置是:

? ? yolo層其實就是輸出層,他的三個輸出層其實不是放在最后,而是插在中間的,也就是說他的權(quán)重保存模式是backbone+卷積+輸出1+fpn融合+輸出2+fpn融合+輸出3,而是通常的backbone+fpn+輸出1+輸出2+輸出3。這種結(jié)構(gòu)導(dǎo)致我們的pytorch模型構(gòu)建瞬間復(fù)雜很多,大家仔細看tools/darknet/yolov3.py里面的代碼拆分非常細,原因就是如此:
self.layers1 = nn.ModuleList([nn.Sequential(layer_dict) for layer_dict in layer_list1])self.head1 = nn.ModuleList([nn.Sequential(layer_dict) for layer_dict in head_1])self.layers2?=?nn.ModuleList([nn.Sequential(layer_dict)?for?layer_dict?in?layer_list2])????self.head2?=?nn.ModuleList([nn.Sequential(layer_dict)?for?layer_dict?in?head_2])self.layers3?=?nn.ModuleList([nn.Sequential(layer_dict)?for?layer_dict?in?layer_list3])????self.head3?=?nn.ModuleList([nn.Sequential(layer_dict)?for?layer_dict?in?head_3])
順序是layers1+head1+layers2+head2+layers3+head3,任何一個順序都不能亂,否則都是錯誤的。
(3) concat一定要注意順序
? ? 即使前面的你都弄好了,你依然可能出錯,因為concat不管你是a+b,還是b+a,代碼都不會報錯,但是實際你錯了,這個要非常小心,一定要執(zhí)行檢查,不要concat順序反了。我開始沒有想到這個問題,在測試tiny-yolov3時候,總是發(fā)現(xiàn)有一層的預(yù)測是正確的,但是另一個層是錯誤的,當(dāng)時想了很久都搞不懂,最后才想到可能是concat的問題,最后調(diào)換下順序就好了。這個問題出現(xiàn)的原因依然是沒有仔細研究cfg,參數(shù)如下:
[]layers = -1, 8
這個就表示是將最后一層輸出和第8個輸出層結(jié)果進行concat,順序是[-1,8]。?
(4) tiny-yolov3里面MaxPool2d寫錯了
? ? 這個問題也被坑了很久,注意是因為騰訊優(yōu)圖里面寫錯了(他現(xiàn)在也是錯誤的),我當(dāng)時沒有想到會錯,所以一直沒有懷疑這個,查了大概1天才發(fā)現(xiàn),被坑的很慘。tiny-yolov3的cfg中maxpool有一個地方非常奇怪:

注意看這兩個maxpool參數(shù),第一個maxpool是標(biāo)準(zhǔn)寫法,但是第二個maxpool的stride=1,而不是2,騰訊優(yōu)圖里面寫的是:
('11_max', nn.MaxPool2d(3, 1, 1)),? ? 這個明顯不是cfg里面的寫法。對于騰訊優(yōu)圖復(fù)現(xiàn)的來說,可能影響很小,因為他根本就沒有導(dǎo)入tiny-yolov3權(quán)重,所以改了下沒有問題,但是我就不能這么搞了。正確的寫法應(yīng)該是:
('10_zero_pad', nn.ZeroPad2d((0, 1, 0, 1))),('11_max', nn.MaxPool2d(2, 1)),
? ? 先pad,然后在maxpool。當(dāng)時寫錯情況下預(yù)測現(xiàn)象是預(yù)測的bbox會存在偏移即預(yù)測正確,但是bbox偏掉了。我開始一直懷疑是我bbox還原代碼寫錯了,因為解碼錯誤也很出現(xiàn)bbox偏移,最后才發(fā)現(xiàn)是這個參數(shù)。這個坑,被坑了很久。
(5) bn和激活參數(shù)設(shè)置不一致
? ? 這個也要非常小心,一定要仔細看下bn和激活函數(shù)參數(shù)設(shè)置,否則影響很大,例如LeakyReLU的激活參數(shù)是0.1,而不是默認(rèn)的0.01,你最好先檢查這個參數(shù)。
(6) 圖片輸入處理流程不一致
? ? ?假設(shè)輸入是416x416,其測試流程是先進行pad為正方形,然后resize,但是需要注意其resize圖片是采用最近鄰,而mmdetection框架中是線性插值。實際測試表明差距還是比較大,會導(dǎo)致一些框丟失。而且我原來寫的代碼一直都是bgr輸入,測試時候發(fā)現(xiàn)效果總是不太對,后來才發(fā)現(xiàn)darknet網(wǎng)絡(luò)輸入是rgb,且直接除以255進行歸一化。
? ? 注意:我在mmdetection-mini中測試依然用的是線性插值模式,沒有修改,而且數(shù)據(jù)前處理邏輯也沒有完全按照darknet來做,而且沿用mmdetection的處理邏輯,如果你是用權(quán)重來微調(diào),我認(rèn)為影響很小的。在后面的yolov5中會關(guān)于圖片預(yù)處理問題會詳述。
? ? 以上就是全部坑了,我踩過的坑全部記錄下了,希望對大家有點幫助,下面針對各個模型說明下一些細節(jié)。
2 yolov3特殊說明
? ? 按照前面的流程可以轉(zhuǎn)換darknet中的所有模型。對于yolov3而言,有些細節(jié)說明下:
(1) __modules_recurse函數(shù)
? ? 前面說過darknet權(quán)重的最小單位是ConvBnAct,故需要通過自己遞歸模塊,直到符合條件為止。故對于自定義模塊例如HeadBody,你需要在Yolov3類開頭定義custom_layers,然后在__modules_recurse遞歸。如果子模塊里面還包括非最小模塊,則內(nèi)部模塊也要加入,否則依然無法導(dǎo)入:
custom_layers = (vn_layer.Stage, vn_layer.Stage.custom_layers, vn_layer.HeadBody, vn_layer.Transition,vn_layer.Head)
例如上面的Stage模塊,內(nèi)部還有定制模塊StageBlock,那么也要加入。

如果你不加入,那么運行時候會看到很多conv層都被跳過了。并且由于yolov3的head寫法,導(dǎo)致在模型的key替換時候會稍微麻煩一些,這種問題只需要細心點就可以解決,不難。

對于我來說,只要搞定了tiny-yolov3和yolov3,那么其余模型都可以很快就轉(zhuǎn)換成功。
3 tiny-yolov4特殊說明
? ? 在tiny-yolov4中引入了一種新的配置:
[route]layers=-1groups=2????group_id=1
groups=2表示將該特征圖平均分成兩組,group_id=1表示取第1組特征。實際上就是:
x0 = x[:, channel // 2:, ...]其他地方就沒啥要注意的了,按照cfg可視化寫就行。
4 yolov4特殊說明
? ? 在tiny-yolov4和yolov4中引入了一個新的參數(shù):scale_x_y = 1.05,對xy坐標(biāo)進行固定scale,其具體實現(xiàn)是:

雖然這個值非常接近1,但是對最終mAP還是有一點影響的。
4 轉(zhuǎn)化性能說明
? ? 對應(yīng)的文檔在docs/model_zoo.md中,這里寫下詳情。在給出指標(biāo)前,有一個地方一定要理清楚,否則各種指標(biāo)你會看起來很懵。
? coco數(shù)據(jù)集劃分方法有兩種:coco2014和coco2017,在
https://cocodataset.org/#download里面有說明,大概就是
MSCOCO2014數(shù)據(jù)集:訓(xùn)練集:82783張,13.5GB, 驗證集:40504張,6.6GB,共計123287張MSCOCO2017數(shù)據(jù)集:訓(xùn)練集:118287張,19.3GB,驗證集:5000張,1814.7M,共計123287張
? ? 數(shù)據(jù)集應(yīng)該還是那些,但是劃分原則改變了。在coco2014中驗證集數(shù)據(jù)太多了,很多大佬做實驗時候其實不是這樣搞的,參考retinanet論文里面的說法:訓(xùn)練集通常都是train2014+val2014-minival2014,也就是從val2014中隨機挑選5000張圖片構(gòu)成minival數(shù)據(jù)集,其余數(shù)據(jù)集全部當(dāng)做訓(xùn)練集。論文中貼的指標(biāo)都是test_dev2014數(shù)據(jù),是本地生成json,然后發(fā)送給coco官方服務(wù)器得到mAP值,本地是沒有l(wèi)abel的。
? ? 基于大家通常的做法,coco官方在2017年開始也采用了這種切分方式,也就是原來是大家各種隨機切分val得到minival,但是現(xiàn)在官方統(tǒng)一了minival,讓大家數(shù)據(jù)完全一樣,對比更加公平。故在2017年開始,劃分就變成train2014+val2014-minival2014=train2017,minival2014=val2017,測試集應(yīng)該沒咋變。
? 也就是是說yolov3論文中的指標(biāo)都是test_dev2014的結(jié)果,訓(xùn)練是train2014+val2014-minival2014。一定要注意minival2014是各自隨機切分的,也就是minival2014雖然圖片數(shù)和val2017一樣,但是有可能val2017的數(shù)據(jù)有部分?jǐn)?shù)據(jù)其實在train2014+val2014-minival2014中。
4.1 測試前置說明
? ? (1) mmdetection中貼的指標(biāo)都是在val2017上面測試的,而darknet中提供的指標(biāo)都是test_dev2014上面的,不具有非常強的對比性,因為val2017可能出現(xiàn)在darknet的訓(xùn)練集中,而且val數(shù)據(jù)集一般會比test_dev簡單一些
? ? (2) mmdetection中數(shù)據(jù)處理流程還是沿用mmdetection的,而不是darknet一樣的處理流程,會有點點差距,而且閾值也不太一樣,但是對于最終結(jié)果不會差距很大或者說沒有關(guān)系。在后面的yolov5中我進行了深入分析,可以保證處理流程完全一致,這里就暫時不寫了。
4.2 yolov3指標(biāo)
? ??1 權(quán)重下載鏈接:
? ? ?https://github.com/AlexeyAB/darknet
???2 對應(yīng)配置:? ?
????https://raw.githubusercontent.com/AlexeyAB/darknet/master/cfg/yolov3.cfg??
? 3 darknet(test_dev2014): 416x416 55.3% [email protected] (31.0 [email protected]:0.95)?- 66(R) FPS - 65.9 BFlops - 236 MB??
???4 darknet(val2017): 416x416 65.9 [email protected]??
? ?5 mmdetection(val2017): 416x416 66.8 [email protected] (37.4 [email protected]:0.95)? -248 MB
? ? darknet(test_dev2014)是官方論文指標(biāo),而darknet(val2017)是我直接用darknet框架測試val2017數(shù)據(jù)得到的指標(biāo),而mmdetection(val2017)是mini框架轉(zhuǎn)換后進行測試的指標(biāo)??梢园l(fā)現(xiàn)指標(biāo)會更高一些,原因應(yīng)該是后處理閾值不一樣。這里就可以完全確定代碼肯定沒有問題了。
4.3 yolov4指標(biāo)
? ??1 權(quán)重下載鏈接:
? ? ?https://github.com/AlexeyAB/darknet ??
???2 對應(yīng)配置:?
????https://raw.githubusercontent.com/AlexeyAB/darknet/master/cfg/yolov4.cfg
? ?3 darknet(test_dev2014):? 416x416 62.8% [email protected] (41.2% [email protected]:0.95)?- 55(R) FPS / 96(V) FPS - 60.1 BFlops? 245 MB
???4 darknet(test_dev2014):? 608x608 65.7% [email protected] (43.5% [email protected]:0.95) - 55(R) FPS / 96(V) FPS - 60.1 BFlops? 245 MB
? 5 mmdetection(val2017): 416x416 65.8% [email protected] (42.0% [email protected]:0.95)- 257. MB? ?
??6 mmdetection(val2017): 608x608 73.0% [email protected] (48.4% [email protected]:0.95) -257.7 MB? ?
注意:yolov4的anchor尺寸變了,我開始沒有發(fā)現(xiàn)導(dǎo)致測試mAP比較低,不同于yolov3,下載的權(quán)重是608x608訓(xùn)練過的,測試用了兩種尺度而已。
4.4 tiny-yolov3指標(biāo)
????1 權(quán)重下載鏈接:
? ? ?https://github.com/AlexeyAB/darknet ?
????2 對應(yīng)配置:?
????https://raw.githubusercontent.com/AlexeyAB/darknet/master/cfg/yolov3-tiny.cfg
??3 darknet(test_dev2014):? 416x416 33.1% [email protected]?- 345(R) FPS -? 5.6 BFlops - 33.7 MB
? ? 4 mmdetection(val2017): 416x416 36.5% [email protected] -35.4 MB??
注意:yolov3-tiny.cfg中最后一個[yolo]節(jié)點,mask應(yīng)該是 1,2,3,而不是github里面的0,1,2
4.5 tiny-yolov4指標(biāo)
????1 權(quán)重下載鏈接:
? ? ?https://github.com/AlexeyAB/darknet? ??
????2 對應(yīng)配置:?
????https://raw.githubusercontent.com/AlexeyAB/darknet/master/cfg/yolov4-tiny.cfg
??3 darknet(test_dev2014): 416x416 40.2% [email protected]?- 371(1080Ti) FPS / 330(RTX2070) FPS - 6.9 BFlops - 23.1 MB??
? 4 mmdetection(val2017): 416x416 38.0% [email protected] (19.3 [email protected]:0.95) -24.3 MB
由于我的測試集是val2017,而不是test_dev2014,所以我提供的mAP會高一些,這是非常正常的。
5 總結(jié)
? ?我提供的代碼應(yīng)該沒有大問題,但是有些細節(jié)可能有點問題,我后面會慢慢完善。希望大家看完這篇文章能夠?qū)W會:
? ?
????(1) darknet的cfg可視化方式;權(quán)重存儲方式
????(2) 對于以后任何darknet模型,都可以僅僅用1個小時就轉(zhuǎn)換到mmdetection中進行微調(diào)訓(xùn)練
????(3) darknet訓(xùn)練、測試方式和mmdetection中的區(qū)別
我后面會去研究darknet的具體實現(xiàn)過程,爭取理解的更加透徹。還有一些不完善的地方,歡迎提出改進意見。下一篇對yolov5轉(zhuǎn)換過程進行深度講解。
6 附加
? ?其實后續(xù)我還想完成一件事情即模仿大部分pytorch復(fù)現(xiàn)yolo系列寫法,提供一個通用的pytorch模型,可以直接加載darknet權(quán)重,輸入也是cfg模式,內(nèi)部自動解析cfg來構(gòu)建模型。這樣就可以實現(xiàn)兩種目的:
? ?
????(1) 如果想了解所有模型細節(jié),可以按照原來的流程,先轉(zhuǎn)化再導(dǎo)入pth權(quán)重
? ?(2) 如果想快速將darknet模型應(yīng)用到mmdetection中,而不寫一行代碼,那么就可以用這個通用的pytorch模型了
但是其需要做如下工作:
????(1) 這個pytorch模型要能夠適應(yīng)所有cfg,也就是必須實時了解darknet里面有沒有新增一些騷操作,這邊也要實時兼容
????(2) 對于微調(diào)訓(xùn)練,也要支持不同輸出層的權(quán)重不導(dǎo)入
github地址:
https://github.com/hhaAndroid/mmdetection-mini
歡迎star和提出改進意見
推薦閱讀
mmdetection最小復(fù)刻版(三):數(shù)據(jù)分析神兵利器
mmdetection最小復(fù)刻版(二):RetinaNet和YoloV3分析
機器學(xué)習(xí)算法工程師
? ??? ? ? ? ? ? ? ? ? ? ? ??????????????????一個用心的公眾號
?

