<kbd id="afajh"><form id="afajh"></form></kbd>
<strong id="afajh"><dl id="afajh"></dl></strong>
    <del id="afajh"><form id="afajh"></form></del>
        1. <th id="afajh"><progress id="afajh"></progress></th>
          <b id="afajh"><abbr id="afajh"></abbr></b>
          <th id="afajh"><progress id="afajh"></progress></th>

          yolov5模型轉(zhuǎn)換NCNN模型部署

          共 3494字,需瀏覽 7分鐘

           ·

          2022-03-04 13:37

          寫作原因:最近看了下nihui大佬的ncnn,練習著將yolov5訓練的模型轉(zhuǎn)換成ncnn模型并部署,同時借鑒了網(wǎng)上優(yōu)秀的博文,記錄一下,如有不對的地方,請多多指教。

          說明:pytorch模型轉(zhuǎn)換成onnx模型,及onnx模型簡化和轉(zhuǎn)ncnn模型在引用的文章中都有詳細的說明,可移步至引用文章中查看。

          先來看下ncnn模型,兩個,一個是param一個是bin,需要修改的是param。

          圖1

          其實yolov5 v1-v5版本在訓練完后,使用onnx2ncnn.exe將簡化后的onnx模型轉(zhuǎn)換成ncnn模型時主要出現(xiàn)這個問題。V6版本在輸出上和前5個版本有一點不同,這里針對1-5版本。

          圖2

          圖3

          根據(jù)nihui大佬的方案看,主要做兩步工作,一是刪除這里報錯的網(wǎng)絡層,然后自定義一個新層作為替代,第二步是修改輸出參數(shù),做完這兩步就可以使用了。

          下面說下修改的是什么,這樣就可以知道自己的模型應該修改哪里了。

          一、param部分參數(shù)說明

          ??7767517???#?文件頭?魔數(shù)
          ??75?83?????#?層數(shù)量??輸入輸出blob數(shù)量
          ????????????#?下面有75行
          ??Input????????????data?????????????0?1?data?0=227?1=227?2=3
          ??Convolution??????conv1????????????1?1?data?conv1?0=64?1=3?2=1?3=2?4=0?5=1?6=1728
          ??ReLU?????????????relu_conv1???????1?1?conv1?conv1_relu_conv1?0=0.000000
          ??Pooling??????????pool1????????????1?1?conv1_relu_conv1?pool1?0=0?1=3?2=2?3=0?4=0
          ??Convolution??????fire2/squeeze1x1?1?1?pool1?fire2/squeeze1x1?0=16?1=1?2=1?3=1?4=0?5=1?6=1024
          ??...
          ??層類型????????????層名字???輸入blob數(shù)量?輸出blob數(shù)量??輸入blob名字?輸出blob名字???參數(shù)字典
          ??
          ??參數(shù)字典,每一層的意義不一樣:
          ??數(shù)據(jù)輸入層?Input????????????data?????????????0?1?data?0=227?1=227?2=3???圖像寬度×圖像高度×通道數(shù)量
          ??卷積層????Convolution??...???0=64?????1=3??????2=1????3=2?????4=0????5=1????6=1728???????????
          ???????????0輸出通道數(shù)?num_output()?;?1卷積核尺寸?kernel_size();??2空洞卷積參數(shù)?dilation();?3卷積步長?stride();?
          ?????????? 4卷積填充pad_size();?????? 5卷積偏置有無bias_term();?? 6卷積核參數(shù)數(shù)量 weight_blob.data_size();
          ??????????????????????????????????????????????????????????????C_OUT?*?C_in?*?W_h?*?W_w?=?64*3*3*3?=?1728
          ??池化層????Pooling??????0=0???????1=3???????2=2????????3=0???????4=0
          ??????????????????????0池化方式:最大值、均值、隨機?????1池化核大小?kernel_size();?????2池化核步長?stride();?
          ??????????????????????3池化核填充?pad();???4是否為全局池化?global_pooling();
          ??激活層????ReLU???????0=0.000000?????下限閾值?negative_slope();
          ???????????ReLU6??????0=0.000000?????1=6.000000?上下限
          ??
          ??綜合示例:
          ??0=1?1=2.5?-23303=2,2.0,3.0
          ??
          ??數(shù)組關鍵字?:?-23300?
          ??-(-23303)?-?23300?=?3?表示該參數(shù)在參數(shù)數(shù)組中的index
          ??后面的第一個參數(shù)表示數(shù)組元素數(shù)量,2表示包含兩個元素

          代碼 1

          二、對 ncnn.param 進行修正

          • 算子替換

          圖4 替換前

          圖5 替換后

          說明:為什么要這么做,nihui大佬對此的解釋如下:

          nihuinihuinihuinihuinihuinihuinihuinihuinihuinihuinihuinihuinihuinihuinihuinihuinihuinihuinihuinihuini

          轉(zhuǎn)換為 ncnn 模型,會輸出很多 Unsupported slice step,這是focus模塊轉(zhuǎn)換的報錯。

          Unsupported?slice?step?!
          Unsupported?slice?step?!
          Unsupported?slice?step?!
          Unsupported?slice?step?!
          Unsupported?slice?step?!
          Unsupported?slice?step?!
          Unsupported?slice?step?!
          Unsupported?slice?step?!

          代碼 2

          好多人遇到這種情況,便不知所措,這些警告表明focus模塊這里要手工修復下

          打開 yolov5/models/common.py 看看focus在做些什么

          class?Focus(nn.Module):
          ????#?Focus?wh?information?into?c-space
          ????def?__init__(self,?c1,?c2,?k=1,?s=1,?p=None,?g=1,?act=True):??#?ch_in,?ch_out,?kernel,?stride,?padding,?groups
          ????????super(Focus,?self).__init__()
          ????????self.conv?=?Conv(c1?*?4,?c2,?k,?s,?p,?g,?act)

          ????def?forward(self,?x):??#?x(b,c,w,h)?->?y(b,4c,w/2,h/2)
          ????????return?self.conv(torch.cat([x[...,?::2,?::2],?x[...,?1::2,?::2],?x[...,?::2,?1::2],?x[...,?1::2,?1::2]],?1))

          代碼 3

          這其實是一次 col-major space2depth 操作,pytorch 似乎并沒有對應上層api實現(xiàn)(反向的 depth2space 可以用 nn.PixelShuffle),yolov5 用 stride slice 再 concat 方式實現(xiàn),實乃不得已而為之的騷操作。

          替換后修改的參數(shù)含義

          由代碼1可知,param第二行的第一個數(shù)據(jù)是層數(shù)量,按niuhui大佬的意思需要替換的行數(shù)為4-13行,總共10行,因此第二行的第一個參數(shù)就是238-10=228,然后,新增加一層替換,因此最后第二行第一個參數(shù)就變成了228+1=229。

          然后就是就是新增加一行的輸入、輸出參數(shù)修改了,由代碼1中參數(shù)說明可知,input層的輸出是iamges,原來第14層的輸入為205,因此增加層的輸入輸出就確定了,分別為images、205。

          • 動態(tài)尺寸推理

          圖6

          說明:為什么要修改這里,nihui大佬的解釋是

          u版yolov5 是支持動態(tài)尺寸推理,但是ncnn天然支持動態(tài)尺寸輸入,無需reshape或重新初始化,給多少就算多少。u版yolov5 將最后 Reshape 層把輸出grid數(shù)寫死了,導致檢測小圖時會出現(xiàn)檢測框密密麻麻布滿整個畫面,或者根本檢測不到東西。

          解決方案就是將reshape層的輸出grid數(shù)量改為 -1 便可以自適應。

          瀏覽 169
          點贊
          評論
          收藏
          分享

          手機掃一掃分享

          分享
          舉報
          評論
          圖片
          表情
          推薦
          點贊
          評論
          收藏
          分享

          手機掃一掃分享

          分享
          舉報
          <kbd id="afajh"><form id="afajh"></form></kbd>
          <strong id="afajh"><dl id="afajh"></dl></strong>
            <del id="afajh"><form id="afajh"></form></del>
                1. <th id="afajh"><progress id="afajh"></progress></th>
                  <b id="afajh"><abbr id="afajh"></abbr></b>
                  <th id="afajh"><progress id="afajh"></progress></th>
                  天天摸日日摸狠狠添 | 久草中文网 | 免费日逼网站 | 豆花视频一区免费 | 久久久91av |