<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>

          實(shí)操教程|NCNN+Int8+YOLOv4量化模型和實(shí)時(shí)推理

          共 8193字,需瀏覽 17分鐘

           ·

          2021-05-20 11:01

          ↑ 點(diǎn)擊藍(lán)字 關(guān)注極市平臺

          作者丨pengtougu@知乎(已授權(quán))
          來源丨h(huán)ttps://zhuanlan.zhihu.com/p/372278785
          編輯丨極市平臺

          極市導(dǎo)讀

           

          本文作者使用NCNN量化YOLOV4模型以及進(jìn)行推理的全過程,附有相關(guān)代碼。 >>加入極市CV技術(shù)交流群,走在計(jì)算機(jī)視覺的最前沿

          一、前言

          2021年5月7日,騰訊優(yōu)圖實(shí)驗(yàn)室正式推出了ncnn新版本,這一版本的貢獻(xiàn)毫無疑問,又是對arm系列的端側(cè)推理一大推動,先剖出nihui大佬博客上關(guān)于新版ncnn的優(yōu)化點(diǎn):繼續(xù)保持優(yōu)秀的接口穩(wěn)定性和兼容性

          • API接口完全不變
          • 量化校準(zhǔn)table完全不變
          • int8模型量化流程完全不變(重點(diǎn)是這個(gè)?。。≈皩ensorflow框架一直不感冒,很大一部分源于tensorflow每更新一次版本,就殺死一片上一版本的接口,可能上了2.0以后這種情況好了很多,不過依舊訓(xùn)練是torch用的更多)

          ncnn int8量化工具(ncnn2table)新特性

          • 支持 kl aciq easyquant 三種量化策略
          • 支持多輸入的模型量化
          • 支持RGB/RGBA/BGR/BGRA/GRAY輸入的模型量化
          • 大幅改善多線程效率
          • 離線進(jìn)行(反量化-激活-量化)->(requantize)融合,實(shí)現(xiàn)端到端量化推理

          更多詳情大家可以去看下nihui大佬的博客:https://zhuanlan.zhihu.com/p/370689914

          二、新版ncnn的int8量化初探

          趁著這股熱風(fēng),趕緊試下新版ncnn量化版int8(更重要的原因是月底要中期答辯了,畢設(shè)還沒搞完,趕緊跑跑大佬的庫,順帶嫖一波)

          2.1 安裝編譯ncnn

          話不多說,在跑庫前先安裝編譯好需要的環(huán)境,安裝和編譯過程可以看我的另一條博客:https://zhuanlan.zhihu.com/p/368653551

          2.2 yolov4-tiny量化int8

          • 在量化前,先不要著急,我們先看看ncnn的wiki,看下量化前需要做什么工作:

          https//github.com/Tencent/ncnn/wiki/quantized-int8-inference

          wiki中:為了支持int8模型在移動設(shè)備上的部署,我們提供了通用的訓(xùn)練后量化工具,可以將float32模型轉(zhuǎn)換為int8模型。

          也就是說,在進(jìn)行量化前,我們需要yolov4-tiny.bin和yolov4-tiny.param這兩個(gè)權(quán)重文件,因?yàn)橄肟焖贉y試int8版本的性能,這里就不把yolov4-tiny.weights轉(zhuǎn)yolov4-tiny.bin和yolov4-tiny.param的步驟寫出來了,大家上model.zoo去嫖下這兩個(gè)opt文件

          地址:https://github.com/nihui/ncnn-assets/tree/master/models

          • 接著,按照步驟使用編譯好的ncnn對兩個(gè)模型進(jìn)行優(yōu)化:
          ./ncnnoptimize yolov4-tiny.param yolov4-tiny.bin yolov4-tiny-opt.param yolov4-tiny.bin 0

          如果是直接上model.zoo下的兩個(gè)opt文件,可以跳過這一步。

          • 下載校準(zhǔn)表圖像

          先下載官方給出的1000張ImageNet圖像,很多同學(xué)沒有梯子,下載慢,可以用下這個(gè)鏈接:

          https://download.csdn.net/download/weixin_45829462/18704213

          這里給大家設(shè)置的是免費(fèi)下載,如果后續(xù)被官方修改了下載積分,那就么得辦法啦(好人的微笑.jpg)

          ImageNet圖像下載
          • 制作校準(zhǔn)表文件

          linux下,切換到和images同個(gè)文件夾的根目錄下,直接

          find images/ -type f > imagelist.txt

          windows下,打開Git Bash(沒有的同學(xué)自行百度安裝,這個(gè)工具是真的好用),切換到切換到和images同個(gè)文件夾的根目錄下,也是直接上面的命令行:

          生成圖片名列表文件命令

          生成所需的list.txt列表,格式如下:

          圖片名列表文件預(yù)覽

          接著繼續(xù)輸入命令:

          ./ncnn2table yolov4-tiny-opt.param yolov4-tiny-opt.bin imagelist.txt yolov4-tiny.table mean=[104,117,123] norm=[0.017,0.017,0.017] shape=[224,224,3] pixel=BGR thread=8 method=kl

          其中,上述所包含變量含義如下:

          mean平均值和norm范數(shù)是你傳遞給Mat::substract_mean_normalize()的值,shape形狀是模型的斑點(diǎn)形狀

          pixel是模型的像素格式,圖像像素將在Extractor::input()之前轉(zhuǎn)換為這種類型 thread線程是可用于并行推理的CPU線程數(shù)(這個(gè)要根據(jù)自己電腦或者板子的性能自己定義) 量化方法是訓(xùn)練后量化算法,目前支持kl和aciq

          • 量化模型
          ./ncnn2int8 yolov4-tiny-opt.param yolov4-tiny-opt.bin yolov4-tiny-int8.param yolov4-tiny-int8.bin yolov4-tiny.table

          直接一步走,所有量化的工具在ncnn\build-vs2019\tools\quantize文件夾下

          量化工具所在目錄

          找不到的讀者請看下自己編譯過程是不是有誤,正常編譯下是會有這些量化文件的運(yùn)行成功后會生成兩個(gè)int8的文件,分別是:

          生成的量化模型

          對比一下原來的兩個(gè)opt模型,小了整整一倍!

          三、新版ncnn的int8量化再探

          量化出了int8模型僅僅是成功了一半,有模型但是內(nèi)部參數(shù)全都錯(cuò)亂的情況也不是沒見過。。。

          • 調(diào)用int8模型進(jìn)行推理

          打開vs2019,建立新的工程,配置的步驟我在上一篇博客已經(jīng)詳細(xì)說過了,再狗頭翻出來祭給大家:

          https://zhuanlan.zhihu.com/p/368653551

          大家直接去ncnn\example文件夾下copy一下yolov4.cpp的代碼(一個(gè)字!嫖?。?/span>

          但是我在這里卻遇到了點(diǎn)問題,因?yàn)橐恢备悴欢罄兄骱瘮?shù)寫的傳參是什么,在昨晚復(fù)習(xí)完教資后搞到了好晚。。

          int main(int argc, char** argv){    cv::Mat frame;    std::vector<Object> objects;    cv::VideoCapture cap;    ncnn::Net yolov4;    const char* devicepath;    int target_size = 0;    int is_streaming = 0;
          if (argc < 2) { fprintf(stderr, "Usage: %s [v4l input device or image]\n", argv[0]); return -1; }
          devicepath = argv[1];
          #ifdef NCNN_PROFILING double t_load_start = ncnn::get_current_time();#endif int ret = init_yolov4(&yolov4, &target_size); //We load model and param first! if (ret != 0) { fprintf(stderr, "Failed to load model or param, error %d", ret); return -1; }
          #ifdef NCNN_PROFILING double t_load_end = ncnn::get_current_time(); fprintf(stdout, "NCNN Init time %.02lfms\n", t_load_end - t_load_start);
          #endif if (strstr(devicepath, "/dev/video") == NULL) { frame = cv::imread(argv[1], 1); if (frame.empty()) { fprintf(stderr, "Failed to read image %s.\n", argv[1]); return -1; } } else { cap.open(devicepath);
          if (!cap.isOpened()) { fprintf(stderr, "Failed to open %s", devicepath); return -1; } cap >> frame; if (frame.empty()) { fprintf(stderr, "Failed to read from device %s.\n", devicepath); return -1; } is_streaming = 1; } while (1) { if (is_streaming) {#ifdef NCNN_PROFILING double t_capture_start = ncnn::get_current_time();#endif cap >> frame;
          #ifdef NCNN_PROFILING double t_capture_end = ncnn::get_current_time(); fprintf(stdout, "NCNN OpenCV capture time %.02lfms\n", t_capture_end - t_capture_start);#endif if (frame.empty()) { fprintf(stderr, "OpenCV Failed to Capture from device %s\n", devicepath); return -1; } }
          #ifdef NCNN_PROFILING double t_detect_start = ncnn::get_current_time();#endif detect_yolov4(frame, objects, target_size, &yolov4); //Create an extractor and run detection
          #ifdef NCNN_PROFILING double t_detect_end = ncnn::get_current_time(); fprintf(stdout, "NCNN detection time %.02lfms\n", t_detect_end - t_detect_start);#endif#ifdef NCNN_PROFILING double t_draw_start = ncnn::get_current_time();#endif draw_objects(frame, objects, is_streaming); //Draw detection results on opencv image
          #ifdef NCNN_PROFILING double t_draw_end = ncnn::get_current_time(); fprintf(stdout, "NCNN OpenCV draw result time %.02lfms\n", t_draw_end - t_draw_start);#endif if (!is_streaming) { //If it is a still image, exit! return 0; } } return 0;}


          果然大佬就是大佬,寫的代碼高深莫測,我只是一個(gè)小白,好難

          靠,第二天直接不看了,重新寫了一個(gè)main函數(shù),調(diào)用大佬寫的那幾個(gè)function:

          int main(int argc, char** argv){    cv::Mat frame;    std::vector<Object> objects;    cv::VideoCapture cap;    ncnn::Net yolov4;    const char* devicepath;    int target_size = 160;    int is_streaming = 0;    /*    const char* imagepath = "E:/ncnn/yolov5/person.jpg";
          cv::Mat m = cv::imread(imagepath, 1); if (m.empty()) { fprintf(stderr, "cv::imread %s failed\n", imagepath); return -1; }
          double start = GetTickCount(); std::vector<Object> objects; detect_yolov5(m, objects); double end = GetTickCount(); fprintf(stderr, "cost time: %.5f\n ms", (end - start)/1000);
          draw_objects(m, objects);
          */ int ret = init_yolov4(&yolov4, &target_size); //We load model and param first! if (ret != 0) { fprintf(stderr, "Failed to load model or param, error %d", ret); return -1; }
          cv::VideoCapture capture; capture.open(0); //修改這個(gè)參數(shù)可以選擇打開想要用的攝像頭
          //cv::Mat frame; while (true) { capture >> frame; cv::Mat m = frame; double start = GetTickCount(); std::vector<Object> objects; detect_yolov4(frame, objects, 160, &yolov4); double end = GetTickCount(); fprintf(stderr, "cost time: %.5f ms \n", (end - start)); // imshow("外接攝像頭", m); //remember, imshow() needs a window name for its first parameter draw_objects(m, objects, 8);
          if (cv::waitKey(30) >= 0) break; }
          return 0;}

          還有幾點(diǎn)注意,大家在進(jìn)行推理的時(shí)候



          把fp16禁掉,不用了 

          換成int8推理 

          把線程改成你之前制作int8模型的那個(gè)線程 

          模型也替換掉

          具體如下:

          代碼需要修改的幾點(diǎn)

          走到這里,就可以愉快的推理了

          推理效果展示

          四、總結(jié)

          說一下我的電腦配置,神舟筆記本K650D-i5,處理器InterCorei5-4210M,都是相對過時(shí)的老機(jī)器了,畢竟買了6年,性能也在下降。

          跑庫過程全程用cpu,為什么不用gpu?(問的好,2g顯存老古董跑起來怕電腦炸了)

          對比之前的fp16模型,明顯在input_size相同的情況下快了40%-70%,且精度幾乎沒有什么損耗

          總結(jié)來說,新版ncnn的int8量化推理確實(shí)是硬貨,后續(xù)會嘗試更多模型的int8推理,做對比實(shí)驗(yàn)給各位網(wǎng)友看

          所有的文件和修改后的代碼放在這個(gè)倉庫里,歡迎大家白嫖:https://github.com/pengtougu/ncnn-yolov4-int8

          感興趣的朋友可以git clone下載跑跑,即下即用(前提要安裝好ncnn)

          如果覺得有用,就請分享到朋友圈吧!

          △點(diǎn)擊卡片關(guān)注極市平臺,獲取最新CV干貨

          公眾號后臺回復(fù)“82”獲取CVPR 2021-LightTrack直播鏈接


          極市干貨
          YOLO教程:一文讀懂YOLO V5 與 YOLO V4大盤點(diǎn)|YOLO 系目標(biāo)檢測算法總覽全面解析YOLO V4網(wǎng)絡(luò)結(jié)構(gòu)
          實(shí)操教程:PyTorch vs LibTorch:網(wǎng)絡(luò)推理速度誰更快?只用兩行代碼,我讓Transformer推理加速了50倍PyTorch AutoGrad C++層實(shí)現(xiàn)
          算法技巧(trick):深度學(xué)習(xí)訓(xùn)練tricks總結(jié)(有實(shí)驗(yàn)支撐)深度強(qiáng)化學(xué)習(xí)調(diào)參Tricks合集長尾識別中的Tricks匯總(AAAI2021
          最新CV競賽:2021 高通人工智能應(yīng)用創(chuàng)新大賽CVPR 2021 | Short-video Face Parsing Challenge3D人體目標(biāo)檢測與行為分析競賽開賽,獎(jiǎng)池7萬+,數(shù)據(jù)集達(dá)16671張!


          CV技術(shù)社群邀請函 #

          △長按添加極市小助手
          添加極市小助手微信(ID : cvmart2)

          備注:姓名-學(xué)校/公司-研究方向-城市(如:小極-北大-目標(biāo)檢測-深圳)


          即可申請加入極市目標(biāo)檢測/圖像分割/工業(yè)檢測/人臉/醫(yī)學(xué)影像/3D/SLAM/自動駕駛/超分辨率/姿態(tài)估計(jì)/ReID/GAN/圖像增強(qiáng)/OCR/視頻理解等技術(shù)交流群


          每月大咖直播分享、真實(shí)項(xiàng)目需求對接、求職內(nèi)推、算法競賽、干貨資訊匯總、與 10000+來自港科大、北大、清華、中科院、CMU、騰訊、百度等名校名企視覺開發(fā)者互動交流~



          覺得有用麻煩給個(gè)在看啦~  
          瀏覽 125
          點(diǎn)贊
          評論
          收藏
          分享

          手機(jī)掃一掃分享

          分享
          舉報(bào)
          評論
          圖片
          表情
          推薦
          點(diǎn)贊
          評論
          收藏
          分享

          手機(jī)掃一掃分享

          分享
          舉報(bào)
          <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>
                  狠狠撸视频 | 国产成人自拍在线 | 大香蕉黄网| 色婷婷视频 | AV软件在线免费观看 |