自助收款機項目記錄與總結

研一主要做了兩件事情,一是收款機項目,二是6Dpose估計的比賽,這兩塊做的都不好。
我是跨專業進來的,考完研之後學了一點吳恩達的網課,來了之後就直接安排進入項目了,

收款機項目


過程總覽

先是做的tensorRT的優化,然後是邊緣設備的移植


tensorRT

先說結果,沒搞出來,用的剪枝模型代替

tensorRT需要將權重文件轉化爲ONNX格式,然後再將ONNX轉換成trt格式。

在接手tensorrt的處理後,想通過之前的同學提供的 model轉onnx 和 onnx轉trt 程序對剪枝後的yolo進行處理,第一步model轉onnx順利進行,但到了第二部轉trt發現無法將onnx序列化。

model轉onnx問題

起初,認爲是 onnx轉trt 程序有問題,之後查閱網上資料,但發現網上的PyTorch框架轉trt的程序都大同小異,幾乎都一樣,此時,懷疑是 model轉onnx 程序轉出來的 onnx 文件有問題。

爲了驗證懷疑是否正確,從網上下載了一個訓練mnist的onnx文件,發現可成功轉爲trt文件。

初步認爲是 model轉onnx 程序有問題,但爲了鞏固此結論,將官方的yolov3.onnx文件拿來試驗,但是運行報錯:
image.png
經搜索,是batch_size過大的問題,官方的batch_size是64,如圖
image.png
而我們平時用的batch_size是1,機器支持不起來這個大的batch_size,此時無法驗證官方onnx是否能轉rtr。

此時我換了一種方法,通過Nerotn可視化來比較官方onnx和我們自己轉出來的onnx的差別,差別如下:
我們自己的onnx(用的原版cfg和best.pt, 是未剪枝的,所以所用的資源是和官方相同的)的最後幾層:

image.png
官方的onnx的最後幾層如下:
image.png
初步斷定是 model轉onnx程序出了問題,開始查閱資料,但是此時又發現,PyTorch框架的寫法也基本都是一樣的,其他人都可順利轉換至最後。
嘗試用官方的tensorrt寫的解析器轉換model,但是報錯(python2.7版本,直接複製過來的,只修改了讀取cfg和weight的地址),錯誤尚未找到解決方法。

此時,問題開始焦灼,對於如何解決問題,現有一些幾個思路

  1. 通讀官方tensorrt寫的關於yolov3的解析器(python2.7版本,近800行),然後對其進行改進(改進後不知和框架直接寫的能有多少差別,時間成本高,可能收益也不好)
  2. 直接使用官方的trt來加速,如果對 未剪枝的yolo加速後的效果 比 剪枝後但未加速的yolo 好,那或許可能採用這種方法
  3. 用其他框架來轉換,如tensorflow,tensorflow框架是不需要轉onnx的,可直接用tensorrt加速推理,但是也可能遇到新的tensorflow難題(網上多是用tensorrt加速PyTorch框架寫的yolo,一方面說明PyTorch框架的優越性,一方面是否也說明其他框架在tensorrt加速方面表現沒有PyTorch好?)

爲了解決問題,我找了個新的開源項目,作者是在官方轉換sample(手寫解析器)上進行改動的,添加了1_batch_size和multi_size的代碼,因此上個周的64_batch_size無法處理得問題就解決了。

作者的cfg和weights解析器和官方相同,但這次我找到了讀取cfg文件報錯的原因,就是剪枝的cfg文件最後少了一個\n。

項目1地址:https://github.com/Cw-zero/TensorRT_yolo3_module

這個項目帶來的價值:解決了官方代碼只能處理64_batch_size, 無法處理1_batch_size的問題

利用該項目的代碼,可完整將原版和剪枝的cfg和weights -> onnx ->trt(利用的是官方手寫yolo解析器相關代碼,不是用的Pytorch框架)

對剪枝模型的加速 :

之後,試了一下這個項目的tensorrt推理,沒有計算速度,只是檢測能否順利運行,結果是運行蠻順利的。
下一步,將該項目的利用tensorrt推理的代碼移植到了剪枝的yolo上,發現竟然畫不出任何bounding_box
然後將原版yolo的trt也放到用於處理剪枝的代碼中,雖然精度不高但是能順利畫出bounding_box。
輸出剪枝的trt推導出的detection,發現全都是0,而原版的trt推導出來的不是。
回頭檢查問題,發現剪枝的onnx可視化後,有幾個數據是獨立於整個框架的,仔細觀察剪枝的cfg,發現其中有maxpool層,然而原版yolo中並沒有maxpool層,
所以官方給出的解析器也無法處理maxpool層,只是跳過了。

出現這種情況的問題在於我不瞭解該剪枝算法,我原本以爲只是減掉了幾個層,又合併了幾個層,沒有加額外的其它層,這時開始尋找新的方法。

兩個思路:
一、用Pytorch框架轉換onnx,然後又項目1的代碼轉trt(之所以不用pytorch一口氣轉,是因爲tensorrt5.0不支持upsample層,而無論是剪枝還是原版yolo,都要用到upsample層,官方的沒用框架的代碼可以很好的解析upsample層,如果要用pytorch那麼就得自己定義upsample層解析),之前失敗的原因,經過這幾天的查閱,發現確實是Pytorch版本的問題,tensorrt5.0出的時候是對應的Pytorch0.4.1的,從0.4.1到1.0,Pytroch中帶的ONNX已經升級了,tensorrt未必能解讀新版本的ONNX。
但相對應的問題有是:需要裝雙版本cuda,現安裝版本是10.0,而Pytorch0.4.1要求的是cuda9.0。

二、找新的剪枝模型,和原版結構相同的那種
項目2地址:https://github.com/Lam1360/YOLOv3-model-pruning
找到如上模型,原版的剪枝,層數更少,沒有maxpool層,而且還是檢測手的,已經訓練好可以直接使用。
相對應的問題:需要在python3.6環境運行,Pytorch1.0及以上版本

一開始先以第一個爲執行方案,先在自己電腦的虛擬機中安裝pytorch0.4.1和cuda,但是cuda安裝失敗了,經查閱,發現虛擬機中無法安裝cuda, 硬安裝的方法也有,但很麻煩,而裝雙版本cuda也很麻煩,所以先執行第二個思路試試

將項目2的cgf和pth文件放到項目1的轉換代碼中,順利的轉出onnx和trt文件,可視化onnx文件,發現這次沒有奇怪的層和脫離框架的數據,很欣慰。
然後建立python3.6的虛擬環境,安裝pytorch時出現Bug,發現服務器cuda10.0的軟連接沒有了,可能是之前換pytorch版本時搞壞了

這個周在進行項目2的tensorrt加速,換了多種方法,改動shape也無法正確用tensorrt推理,折騰多天無果。後來看了下這個剪枝模型參考的論文,發現與原版相比,減掉了很多CNN的channel,可能這就是我使用的tensorrt加速代碼無法正常運行的原因,這個代碼是針對原版yolo寫的,或許對層進行了改動會無法識別?
在陷入困難之際,決定試試項目2在tx2上的速度,發現最高能達到9 fps,所以之後就沒有繼續搞tensorrt了


邊緣設備

在這個項目的時間裏,大部分時間都是在搞移植,一共接觸了四塊板子:Nano,TX1,TX2,rk3399pro。其中前三塊板子還好,支持pytorch模型(我們的代碼就是pytorch寫的),但是第四塊就有點拉跨了,而且公司那邊還就想用第四塊(便宜,有NPU,計算速度稍快)。

公司那邊提出用rk3399pro,經調研,發現當其GPU和NPU同時運行時,速度能達到Nano的二倍左右,然後用新的模型在Nano上試了一下,能達到4幀,如果3399的效果真的能達到Nano二倍,或許可以試試,測試了下,rk3399 pro是可以運行tensorflow框架的yolo的,能跑到7幀左右,然後就開始着手模型轉換的工作。

問題就在於第四塊支持的框架有限(僅部分tensorflow,caffe,darknet,不支持pytorch)。

一開始的想法是,想直接用網上的代碼將pytorch框架轉換成tensorflow框架,經查閱後,發現有兩種方式:

一、pytorch -> onnx -> keras -> tensorflow
由於之前研究tensorRT的時候用到了很多的onnx文件,而且現在還保存的,就先嚐試了這種方法。
這是該方法用到的代碼來源:https://github.com/nerox8664/onnx2keras
但是轉換時發現了問題,就是隻能轉換layer,到了轉換weight的時候就會卡住,keras model轉換不出來
報錯代碼:TypeError: unhashable type:‘google.protobuf.pyext._message.RepeatedScalarContainer’
之後嘗試更換多個protobuf版本,發現還是不可以,目前認爲可能是onnx文件有些問題,但是還沒找到解決的方法。就先嚐試了另一種方法

二、pytorch -> keras -> tensorflow
這個方法用到的代碼來源:https://github.com/nerox8664/pytorch2keras
查看更多的資料,發現這個代碼並不支持yolo層的轉換,所以這個方法也不能用。
解決問題的思路

  1. 用tensorflow復現剪枝和微調的代碼(我們現在正在嘗試,但是我覺得以我們現在的水平,不太可能)
  2. 在網上找一些tensorflow的yolo剪枝代碼(這是我最開始嘗試的方法,但是沒找到,下個周再仔細看看)

嘗試了使用ONNX模型和Darknet模型來讓之前的剪枝yolo能在rk3399 pro上運行,遇到的問題:
ONNX模型:
將之前搞tensorrt的時候用的onnx放到rk3399提供的 onnx轉rknn 代碼中轉換,轉出來不能用。剪枝和原版的都試過了,判斷不是剪枝的問題,原版的也不能用,網上說這個rk3399只對tensorflow有完整支持,而對其他模型支持不全,這可能是個原因。
Darknet框架:
我之前使用的權重文件是.pth文件,Darknet需要.weights文件,我是用之前代碼自帶的轉換函數來轉換:
model = Darknet(‘prune_yolov3-hand.cfg’)
weights = ‘prune_yolov3_ckpt.pth’
model.load_state_dict(torch.load(weights, map_location=‘cpu’))
model.save_darknet_weights(path=‘converted.weights’)
但是也報錯
IndexError: index 1 is out of range
還沒找到那裏出了問題,這些轉換看起來不是怎麼靠譜

嘗試了對yolo剪掉用不掉的小尺度來提高速度,後來發現無論只保留那個尺度,都能檢測出近距離和遠距離的手
在這裏插入圖片描述
在這裏插入圖片描述
這兩張手分別是隻保留大尺度和只保留小尺度檢測出來的,按理來講不應該這樣,但是運行起來三種尺度除了最大框的大小以外幾乎沒什麼區別。

開始着手Darknet框架的處理,主要使用到了兩個網站的內容:
ToyBrick社區:http://t.rock-chips.com/forum.php?mod=viewthread&tid=184
yolov3官網:https://pjreddie.com/darknet/train-cifar/

過程:

  1. 一開始直接對cfg進行改動,然後使用原版的weights,在pytorch框架下的yolov3是可以運行這樣的文件並進行預測的。但是在Darknet框架中,這樣沒有用。
  2. 後來使用原版的weights,對cfg進行修改,然後提取相應的卷積層參數進行訓練,這裏只用了3張圖片epoch了8次,訓練的classes只有3種,只爲嘗試該思路的可行性。
  3. 成功訓練之後,將其放到rk3399的darknet網絡中,rknn的inference能順利執行,並輸出最後卷積層輸出的參數。
  4. 之後對inference之後的數據維度處理進行了調整,使用圖片進行測試,可以執行完檢測程序(但是是沒有檢測效果的),證明darknet的修改基本沒有什麼問題了。
  5. 對視頻進行測試,能夠達到10 FPS

先是訓練了單尺度的yolov3,但是效果奇差,根本檢測不出東西來;現在在訓完整的單分類yolov3,如果效果好,就提取前82層(單尺度)的網絡再試試。

完整的尺度的yolov3訓練出來了,但是仍然發現什麼都檢測不到,一開始以爲是訓練的不好,後來將權重放到服務器上,發現可以正常預測,精度還可以。
因此,回頭看了下官方提供的yolo_demo的代碼,感覺他寫的不太對,訓練的單尺度權重放上去什麼都跑不出來,object_threshold計算用了一種沒見過的公式,跟之前看過的一些yolov3源碼不太一樣:
obj_thresh = -np.log(1/OBJ_THRESH - 1)
之後嘗試用tensorflow的代碼,但是因爲對tensorflow不夠了解,改起來很吃力,就嘗試在服務器的代碼中,將Pytorch實現的部分用Numpy來寫,但是我對這兩個也不是很熟,改起來比較慢,比較花費時間。

將Pytorch模型改爲Numpy的工作已經完成了,但是預測的效果還是很差

在這裏插入圖片描述

在這裏插入圖片描述

那麼大的模型想要在小的板子上運行,必然是要量化的,將文件大小從200+MB壓縮到50+MB,必然會損失一些精度。而我遇到的問題是,檢測不出任何的手,精度損失巨大,如何去處理這個量化損失精度問題就不懂了,這個交給專業移植人士了。

總結
剛來的時候什麼也不懂,也沒能對這個項目面臨的問題提出一些有效的方法,所以感覺在這一塊收穫不是很大,但是作爲一個入門我感覺還是蠻好的,如果是已經學了半年,而且一開始就是我們處理的話,我感覺是能做出些好的效果的。
在這個項目中獲得的提升:

  1. 對yolov3的代碼的理解加深
  2. 對於神經網絡的檢測效果有一定了解,在這個項目裏跟手相似的顏色都很用被誤檢,且背景顏色對檢測效果也有較大影響,色差越大越好
  3. 熟悉各個板子的刷機和環境配置 ( 汗 - -!)
  4. 熟悉了numpy、darknet的部分使用方法
發佈了53 篇原創文章 · 獲贊 2 · 訪問量 7150
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章