ubuntu下跑通CornerNet的流程步驟
-
- 環境配置
-
- 寫這篇部落格原因?
- 更改conda_packagelist.txt
- conda下基于conda_packagelist.txt建立新環境
- 安裝pytorch 1.2 和torchvision
- 編譯Corner Pooling-(用pytorch=1.x的這裡是個大坑,請注意!)
-
- 按照原始代碼直接編譯,error
- 初次修改,測試階段OK,訓練階段不OK
- 最終修改,訓練和測試階段均OK
- 編譯nms(非極大值抑制)
- 安裝MS COCO API
- 下載下傳MS COCO資料集
- MSCOCO資料集存放位置(大坑)
-
- 問題描述:
- 問題解決
- CornerNet模型訓練
-
- GPU數量和顯存限制代碼修改
- 成功訓練結果,沒有訓練完成,時間太久了呀
- Cornernet模型測試
-
- 生成可視化檢測照片代碼修改
- 輸出結果
-
- 随便放幾張效果不錯的。
- 不好的結果
- 使用新的配置檔案說明
CornerNet 官方github連結
CornerNet 論文位址
環境配置
寫這篇部落格原因?
為什麼要寫這樣一篇部落格?
一是記錄自己的學習過程,二是因為CornerNet是基于pytorch 0.4.0寫的,其中的某些C++和Cuda API在1.0之後已經變化,是以在編譯corner pooling的時候會遇到問題,真讓人頭大,不過沒關系,這篇部落格将教你如何解決該問題。
下載下傳下來官方github代碼後,根目錄下有這樣一個檔案:
裡面含有跑通CornerNet所需要的的第三方庫,但是你仔細看其中的關于cuda和pytorch的第三方庫,你會發現,其安裝的是基于cuda8.0和pytorch 0.4.0的第三方庫,萬一你不幸裝的是cuda 9.0及以上,難道你為了跑通個CornerNet再去重裝cuda嗎?雖然這樣也可以,但是就有點太麻煩了。
更改conda_packagelist.txt
不過,如果不想重裝的話,接着往下看。

打開conda_packagelist.txt,删除如下四個第三方庫連結,然後你可以自己去裝最重要的pytroch和torchvision。
https://conda.anaconda.org/caffe2/linux-64/caffe2-cuda8.0-cudnn7-0.8.dev-py36_2018.05.14.tar.bz2
https://repo.continuum.io/pkgs/free/linux-64/cudatoolkit-8.0-3.tar.bz2
https://conda.anaconda.org/pytorch/linux-64/pytorch-0.4.0-py36_cuda8.0.61_cudnn7.1.2_1.tar.bz2
https://conda.anaconda.org/pytorch/linux-64/torchvision-0.2.1-py36_1.tar.bz2
conda下基于conda_packagelist.txt建立新環境
cd進入下載下傳後的cornernet檔案夾下:
打開terminal,執行:
conda create --name CornerNet --file conda_packagelist.txt
至此,cornernet所需要的大部分的第三庫已經安裝成功。
安裝pytorch 1.2 和torchvision
這方面我們要參考pytorch官網:
不知道為什麼,在我建立的虛拟環境cornernet中使用pip安裝時,雖然是python3環境,但是需要将pip3改為pip,暫時不知道什麼原因。
執行如下指令即可:
pip install torch==1.2.0+cu92 torchvision==0.4.0+cu92 -f https://download.pytorch.org/whl/torch_stable.html
這個裝的話,比較快,畢竟是從pytorch官網直接擷取安裝包。
編譯Corner Pooling-(用pytorch=1.x的這裡是個大坑,請注意!)
這一步确實遇到了問題,畢竟官方代碼是基于pytorch 0.4.0寫的,我裝的是pytorch 1.2.0,有問題也在意料之中。
按照原始代碼直接編譯,error
執行:
cd <CornerNet dir>/models/py_utils/_cpools/
python setup.py install --user
問題如下:
src/top_pool.cpp: In function ‘std::vectorat::Tensor top_pool_backward(at::Tensor, at::Tensor)’:
src/top_pool.cpp:44:41: error: could not convert ‘at::CUDA((c10::ScalarType)6)’ from ‘at::DeprecatedTypeProperties’ to ‘c10::IntArrayRef {aka c10::ArrayRef}’
auto max_val = at::zeros(torch::CUDA(at::kFloat), {batch, channel, width});
^
src/top_pool.cpp:45:41: error: could not convert ‘at::CUDA((c10::ScalarType)4)’ from ‘at::DeprecatedTypeProperties’ to ‘c10::IntArrayRef {aka c10::ArrayRef}’
auto max_ind = at::zeros(torch::CUDA(at::kLong), {batch, channel, width});
^
src/top_pool.cpp:57:44: error: could not convert ‘at::CUDA((c10::ScalarType)0)’ from ‘at::DeprecatedTypeProperties’ to ‘c10::IntArrayRef {aka c10::ArrayRef}’
auto gt_mask = at::zeros(torch::CUDA(at::kByte), {batch, channel, width
^
src/top_pool.cpp:58:44: error: could not convert ‘at::CUDA((c10::ScalarType)6)’ from ‘at::DeprecatedTypeProperties’ to ‘c10::IntArrayRef {aka c10::ArrayRef}’
auto max_temp = at::zeros(torch::CUDA(at::kFloat), {batch, channel, width
初次修改,測試階段OK,訓練階段不OK
好像是cuda接口的問題,應該是由于pytorch版本的改變,導緻了cuda接口的變化,但是怎麼改呢?接着看。。
終于讓我在github上官方代碼的issues上找到了,
隻需要在 **/models/py_utils/_cpools/src/**目錄下,将src下bottom_pool.cpp、left_pool.cpp、top_pool.cpp以及right_pool.cpp四個檔案中四行代碼改變一下即可,四個檔案的更改都是一樣的。
即将
改為:
即可。
- 需要改動的有以下四處:
44、45行代碼處:
auto max_val = at::zeros(torch::CUDA(at::kFloat), {batch, channel, height});
auto max_ind = at::zeros(torch::CUDA(at::kLong), {batch, channel, height});
57、58行代碼處:
auto gt_mask = at::zeros(torch::CUDA(at::kByte), {batch, channel, height});
auto max_temp = at::zeros(torch::CUDA(at::kFloat), {batch, channel, height});
如此可以編譯成功,但是前期因為顯示卡和資料集問題,我隻是對官方訓練了500000次的模型進行了測試,在此情況修改下的xxx_pool.cpp确實可以使用,但是進行從0開始訓練MS COCO資料集的時候就出現了問題。
output = right_pool.backward(input, grad_output)[0]
RuntimeError: Expected object of type Variable but found type CUDAByteType for argument #0 ‘out’ (checked_cast_variable at /pytorch/torch/csrc/autograd/VariableTypeManual.cpp:48)
最終修改,訓練和測試階段均OK
是以還是編譯corner pooling時由于pytorch版本不同導緻出現了問題,我在查找了資料之後,發現了最終的解決方案。
其可以正常進行訓練。
方案如下:
下載下傳CornerNet-Lite CornerNet-Lite Github 連結 源代碼,将其代碼包中的CornerNet-Lite/core/models/py_utils/_cpools檔案夾複制替換CornerNet源代碼下的CornerNet/models/py_utils/_cpools/,然後運作指令進行重新編譯:
python setup.py install --user
按照此方法編譯後,至少在corner pooling這裡的環境配置是沒有問題的。
我在查找資料時,還遇到另外一種修改corner pooling下cpp檔案代碼的方法,不過經過我試用,這種修改至少對我的系統無效,依然會蹦出上述問題。
修改方法貼在了下面,讀者看到的話也可以試試,看看行不行。
編譯nms(非極大值抑制)
這個沒什麼可說的,隻要裝了cmake即可,我裝的是3.4版本的好像,版本不要太低應該都沒事。
cd <CornerNet dir>/external
make
安裝MS COCO API
應該需要建立一個data檔案夾:
cd <CornerNet dir>/data
git clone [email protected]:cocodataset/cocoapi.git coco
cd <CornerNet dir>/data/coco/PythonAPI
make
如果,第一次是第一次git,那麼需要安裝git:
以及設定github上的ssh,否則無法git,具體過程請參考我另一篇博文:
git安裝和使用
下載下傳MS COCO資料集
我之前下載下傳過train2017、val2017、test2017,但是好像cornernet自己split了一個2014trainval的标簽,因為還沒看源代碼,我先下載下傳資料。
這個連結是google的,不翻牆有可能進不去,有需要的可以評論郵箱,我看到會發的。
annotations檔案下載下傳連結
MS COCO 資料集下載下傳位址
下載下傳紅框标記的即可。
MSCOCO資料集存放位置(大坑)
我在看github英文說明的時候,其實官方對于資料集的使用說的模棱兩可,我于是就按照字面的意思将下載下傳的train2014直接重命名為trainval2014,val2014重命名為minival2014,test2017重命名為testdev2017,并放置在dir>/data/coco/images/下(如果沒有,建立即可)。
問題描述:
結果出現了以下問題:
print("image.shape", image.shape[:]) AttributeError: 'NoneType' object has no attribute 'shape'
但從圖中也可以看出,圖檔路徑名是可以列印出來的,那麼為什麼還會出現NoneType這種錯誤呢?最可能的答案就是路徑下的圖檔缺少了,即annotation裡定義的标簽圖檔在路徑下有的找不到,是以才會出現這種問題。那麼缺少了哪些問題呢?
問題解決
最終我發現,其實官方是将train2014和val2014合在一起作為trainval2014的,minival2014時從其中split的,具體怎麼split我不知道,因為空間足夠,是以我直接複制了一份,并重命名為了minival2014。
經過後續的訓練測試,證明我這樣做可以的,不會再出現這種NoneType的問題了。
但是實際訓練的時候,還是會出現因為GPU數量太少和GPU顯存太小的問題。不過我都一一解決了,解決方案在訓練和測試章節。
CornerNet模型訓練
To train and evaluate a network, you will need to create a configuration file, which defines the hyperparameters, and a model file, which defines the network architecture. The configuration file should be in JSON format and placed in config/. Each configuration file should have a corresponding model file in models/. i.e. If there is a .json in config/, there should be a .py in models/. There is only one exception which we will mention later.
- 訓練CornerNet模型:
為了訓練和評價一個網絡,你需要建立一個定義了超參數和模型檔案的配置檔案,這将定義網絡的基本架構。配置檔案應該是json格式,并且被放在config/檔案夾下。每個配置檔案都應該有一個相對應的在models/檔案夾下的模型檔案。就是說,如果config/下有一個json檔案,那麼models/需要有一個.py檔案
官方提供了配置檔案CornerNet.json和模型檔案CornerNet.py。
GPU數量和顯存限制代碼修改
如果你不考慮自己的GPU數量和GPU顯存直接執行該指令的話,估計還是可能會抛出類似于corner pooling沒有編譯正确時的錯誤,即這種。
output = right_pool.backward(input, grad_output)[0]
RuntimeError: Expected object of type Variable but found type CUDAByteType for argument #0 ‘out’ (checked_cast_variable at /pytorch/torch/csrc/autograd/VariableTypeManual.cpp:48)
筆者本人的電腦是一個1060ti顯示卡 6G顯存,是以很慚愧,算力太緊張。是以官方是用的10塊GPU訓練的,對于我來說顯然不成立,直接執行指令确然會報錯。
- 是以GPU數量和顯存緊張的情況下請這樣修改:
如果你隻有一塊GPU,請将batch_size改為1,如果你的顯存大于12G請将chunk_sizes改為[4 ],如果跟我一樣隻是6G的,請改為[1],改為[2]我試過了,還是會out of memory。chunk_sizes代表向GPU配置設定多少張圖檔。
同時,train.py代碼中的指令行參數thread,請由預設參數4改為1。這個我不知道具體是做什麼用的目前,但是應該和GPU的數量有關。
改到這一步,還是不能直接運作指令,否則會如下錯誤:
dist = tag_mean.unsqueeze(1) - tag_mean.unsqueeze(2) IndexError: Dimension out of range (expected to be in range of [-2, 1], but got 2)
如果出現這種錯誤,按照圖示進行修改:
在kp_utils.py中加入紅框中的代碼即可。
成功訓練結果,沒有訓練完成,時間太久了呀
最後執行這個指令:
python train.py CornerNet
結果:
可以正常進行疊代,疊代輸出的上下還是因為pytorch版本不同出現的一些警告,不過應該問題不大。
我大概疊代了10000次,5000次儲存一次模型,結果因為空間不夠,導緻程序中斷,不過整個流程沒有什麼問題。
儲存的5000次和10000次疊代模型。
Cornernet模型測試
官方同樣提供了一個訓練了500k疊代次數的CornerNet模型,不過其用了10個Titan X GPUs,是以代碼裡有個地方預設的是10個GPU,如果你沒有10個GPU,你需要把那個地方更改一下,不然有可能會報錯,還有配置檔案裡的batchsize也需要更改以适應你的gpu顯存。怎麼修改在下面。
我們可以從如下連結(500k疊代次數模型下載下傳連結,同樣需要google。
)下載下傳,并将其放在**/cache/nnet/CornerNet**檔案夾下,
- 執行如下代碼進行測試:
split==testing表示測試testdev2017下的圖檔,在代碼中有定義,有時間我會在github上更新一個annotation版本的CornerNet代碼。
生成可視化檢測照片代碼修改
執行指令,CornerNet會自動生成results.json檔案,其中存儲了圖像id和detection坐标點,但是如果想生成可視化後的object detection圖檔需要進行如下修改。
在CornerNet/test/coco.py代碼中的kp_detection函數内第152行的
if debug
改為:
再在191行下加入一行代碼:
然後在terminal下執行:
輸出結果
随便放幾張效果不錯的。
不好的結果
仔細觀察CornerNet輸出的可視化結果,我們可以發現CornerNet檢測的兩個主要問題:
- 對于密集型的object經常會出現對兩個同樣object之間的區域也列為object,可能不太好描述,看圖就明白了。
直接将兩個car之間的區域也檢測為car;
直接将兩個person之間的區域也檢測為person。
又或者将tennis racket中的區域也檢測為object;
- 對于一些密集型object檢測不準确
比如下面的sheep,很多沒檢測都,而且直接将很大一塊草地也檢測為sheep了。
- 其他的檢測不到和檢測定位差距較大問題
下圖兩個孩子的檢測框明顯和實際差距過大。
bird沒有檢測到。
fire hvdrant 沒有檢測到。
總之雖然,效果不錯,但是還是有很大問題。
正因為,其是通過角點來判斷,是以對于密集型object出現這種将object之間的區域也檢測為object也不足為奇。
使用新的配置檔案說明
如果想使用新的配置檔案,按照如下方案,我還沒試過。
- 使用新的配置檔案:
如果想測試不同的超參數,但是又不想重寫原始的配置檔案,可以建立一個帶字尾的配置檔案(model-suffix.json),但是不需要在models/下建立一個帶字尾的model-suffix.py檔案。
- 使用官方重寫的多尺度配置檔案:
python test.py CornerNet --testiter <iter> --split <split> --suffix multi_scale
有空會補上訓練和測試結果。已補上訓練成功截圖和測試結果,因為算力原因,就先不從頭開始訓CornerNet了。
2019.10.9,2019.10.12更新。
希望能幫到大家。随手點贊是對我最大的認可。