最近的一個任務用到了SSD作檢測,将這份代碼應用到了自己的資料上,為了防止自己忘了,其中的整個過程作一個記錄,同時這兩天決定将SSD的源碼好好讀一遍,加深一下了解。所用的代碼位址:
https://github.com/lufficc/SSDgithub.com
這份代碼是今年的,比起兩年前star數量最多的SSD Pytorch實作有更多的靈活度,更詳細的文檔,作者給出了不同的Backbone,在readme裡面給出了特别詳細的修改指導,對于想要自己更改網絡,寫自己的資料類的小夥伴,強烈安利!在此感謝原作者!
因為安裝使用SSD和源碼解讀是很大兩塊内容,分倆個部分來寫,第一部分主要是關于SSD的使用。
SSD安裝/訓練/推理
安裝:(ubuntu環境)對于如何安裝并跑這份代碼作者在readme裡面寫得簡直不能太詳盡,隻補充幾個注意點:
- 養成好習慣,盡量在conda 裡面創個虛拟環境
- CUDA9/10皆可,但是CUDA8是不行的
- 小Tip: conda install torchvision==0.3.0,一行指令基本幫忙把torch相關依賴都裝上了
:
建立一個datasets檔案夾。源碼支援coco/voc格式,當然你也可以自定義一個資料接口,這個作者也有指導!自己寫資料類請參考ssd/data/datasets/目錄下的coco.py和voc.py
對于voc:
--datasets
| --voc2007
| --Annotations
| --1.xml,2.xml,....,......
| --JPEGImages
| --1.jpg,2.jpg,....,......
| --ImageSets
| --Main
| --test.txt #用于測試的。形如1,2,3,4...也就是index 加上.xml或者.jpg就是标簽和圖像的名字
| --train.txt #用于訓練的
| --trainval.txt #訓練加驗證
| --val.txt #驗證
仿照VOCDataset(torch.utils.data.Dataset)寫一個針對自己特定資料格式的類就可!
對于想自己定義資料類以及更改網絡結構的,給出原作者的指導https://github.com/lufficc/SSD/blob/master/DEVELOP_GUIDE.mdgithub.com
含有三個目标的voc格式的.xml檔案标長這樣:
訓練:
- 組織好資料後,需要把它的路徑寫到 ssd/config/path_catlog.py中,同時在configs/vgg_ssd300voc0712.yaml檔案中指定所用資料。為了友善,上面我直接把自己的資料就命名為VOC2007,這樣其實不需要改 pathcatlog.py.
如果按照VOC命名則不需要更改,隻是給出它和下面圖中yaml的對應關系
- 還有一個特别需要注意的點就是類别的更改,在default.py和,.yaml中的NUM_CLASSES是自己的資料的類别,記得加上背景,同時,一定要在voc.py或者coco.py中(如果用的voc/coco格式)将類别标簽都改為自己的
- 運作train.py的訓練的時候,由于在ssd/config/default.py中,預設是vgg網絡作為backbone,但是如果你選擇了使用預訓練模型,那麼往往會遇到一個問題,預訓練模型需要到程式中指定的那個url去下載下傳,但往往會失敗。是以,這個時候不如到網上找一個vgg16的預訓練模型vgg16_reducedfc.pth,根據錯誤提示,把模型放到~/.torch/models/下面,要在指令行下面操作,.torch是隐藏檔案,圖形界面找不到的!
這兩個是都是這個工程的參數配置,yaml比前者的優先級高,yaml沒有的到defaults裡面找,使用何種backbone,輸入圖檔大小,特征圖,預設框的生成配置,訓練配置等等都在裡面。幾個關鍵的點:
更換backbone:這個對應了defaults.py中的# Backbone部分,在ssd/modeling/backbone目錄下面可以看到,作者提供了三個backbone。但是并非簡簡單單的把_C.MODEL.BACKBONE.NAME = 'vgg'換成mobilenet或者efficientnet就可。前面的連結裡面作者也給出了指導:
但是問題來了,這幾個參數該咋改呢,咋知道mobilenet對應的幾個特征圖的輸出通道和大小呢?當然隻能去看在ssd/modeling/backbone目錄下面的源碼了,以下對于更換為mobilenet的情況作一個說明。源碼支援300和512大小的圖像輸入,對于300x300的輸入,嘗試着自己列印一下作者定義的mobilenet為基礎的banckbone的網絡就很容易得到各個特征圖的資訊:
torch.Size([2, 96, 19, 19])
torch.Size([2, 1280, 10, 10])
torch.Size([2, 512, 5, 5])
torch.Size([2, 256, 3, 3])
torch.Size([2, 256, 2, 2])
torch.Size([2, 64, 1, 1])
#輸出通道分别是[96,1280,512,256,256,64]
#大小分别是[19,10,5,3,2,1]
#STRIDES代表了特征圖框放大到原始圖的縮放比例,輸入圖像是300x300,
#那麼300除以各個特征圖的大小就對應了比例:[15,30,60,100,150,300]
對于不能整除的情況,可以近似(這一點其實我也不是特别的了解,
我覺得完全可以在設計網絡階段就把其全都設計為整除的啊)
插播一句:
_C
是以更改後:
(注意一定要把mobilenet名字寫全,看源碼裡面叫啥:是叫mobilenet_v2啊!!!!!!)
順便給出imgesize=512對應的vgg和mobilenet_v2的特征圖size資訊
512輸入對應的vgg的六個FeatureMap
torch.Size([2, 512, 64, 64])
torch.Size([2, 1024, 32, 32])
torch.Size([2, 512, 16, 16])
torch.Size([2, 256, 8, 8])
torch.Size([2, 256, 6, 6])
torch.Size([2, 256, 4, 4])
512輸入對應的mobilenet_v2的六個FeatureMap
torch.Size([2, 96, 32, 32])
torch.Size([2, 1280, 16, 16])
torch.Size([2, 512, 8, 8])
torch.Size([2, 256, 4, 4])
torch.Size([2, 256, 2, 2])
torch.Size([2, 64, 1, 1])
至于lr,batch_size,模型輸出路徑等到.yaml中修改
推理參考:demo.py
補充說明,源碼中是用的vizer庫在繪圖,但是我感覺這給繪出來的圖太細了,而且不支援中文顯示,我沒搞懂怎麼調,于是用cv2和PIL重新寫了一遍
附上linux下中文字型的路徑:
/usr/share/fonts/truetype/arphic/uming.ttc
資料增強 可參考:
lim0:目标檢測資料集的增強(旋轉,鏡像,亮度等)含針對VOC标注格式資料的源碼zhuanlan.zhihu.com
下一步的計劃對于SSD源碼的解讀放在下篇