添加链接
link管理
链接快照平台
  • 输入网页链接,自动生成快照
  • 标签化管理网页链接
相关文章推荐
温暖的芒果  ·  Laravel 8 - Left ...·  2 年前    · 
本仓库主要包含以下部分的内容: Part1: 调整yolov4.cfg 网络. Part2: 在主机端(ubuntu18.04)上使用 Xilinx 的vitis -ai 1.3.2 工具完成对网络的量化和编译。 Part3: 在边缘端(ultra_96_v2), 使用pynq-dpu1.2 分别测试剪枝前后yolov4网络的推理速度,使用pynq-dpu1.3 分别测试剪枝前后yolov4网络消耗的能量。 Part4: demo.video https://www.bilibili.com/video/BV1AU4y1n7w6/. 实验结果如图1所示。 Part5: Evaluate test-dev2017 about 21k images on the Ultra_96_v2 . 致谢: 感谢 XILINX & NICU 共同举办的暑期学校,这是个值得纪念的Summer School, 我们度过了南京疫情和上海“烟花”台风,最终抵达 XILINX_2021 SUMMER SCHOOL的彼岸.
  • Part1: 调整 yolov4.cfg 网络文件.
  • Part2: 使用vitis -ai 工具对网络进行量化和编译.
  • Part3: 将网络部署到边缘端(ultra_96_v2)上,编写notebook.ipynb 文件,调用pynq-dpu 推理运行网络.
  • Note:在部署YOLOV4 网络之前,需要对YOLOV4网络进行剪枝的同学,可以参考( https://github.com/chumingqian/Model_Compression_For_YOLOV4 ). 这里提供在VOC 和COCO上,训练好的权重文件: https://pan.baidu.com/s/1lL1tPSOKJc4V4eF_SqVoHw 提取码: rvrg.

    网络文件位于07-yolov4-tutorial/dk_model/ . 注意到,需要先对yolov4.cfg 修改成dpu支持的网络,再对修改后的网络进行剪枝。

    Part1: 调整yolov4.cfg 网络.

    1.0 由于当前pynq-dpu1.2 暂未支持MISH激活函数,且dpu 支持的最大池化的kernel size为8, 故修改yolov4网络的结构, 使修改后的yolov4.cfg 网络能够使用配合使用Xilinx的 vitis-ai 工具进行量化和编译,并在pynq-dpu 上运行.本仓库中对原始网络的 yolov4.cfg 文件做了如下修改.

               m1  将MISH激活函数替换成leaky.     
               m2  将SPP Moudle maxpool 由5 ,9,13 替换成 5,5,7; 之后对修改后的网络进行重新微调训练。
    

    Part2: 在主机端(ubuntu18.04)上使用 Xilinx 的vitis -ai 1.3.2 工具完成对网络的量化和编译。

    2.0 在Ubuntu18.04 上安装docker, https://docs.docker.com/engine/install/ubuntu/ ,并确认本机的linux user 加入到docker组中, https://docs.docker.com/engine/install/linux-postinstall/ or reference the https://www.xilinx.com/html_docs/vitis_ai/1_3/installation.html install the vitis ai。

    2.1 从GitHub上拉取vitis ai的仓库文件:

              git clone --recurse-submodules https://github.com/Xilinx/Vitis-AI  
                  cd Vitis-AI
    

    2.2 从 docker上拉取预编译好的vitis ai 的安装环境,(若在本地安装请准备好32G 以上的内存用于安装时的编译)。

                启动docker 环境中的vitis ai :	    
           ./docker_run.sh xilinx/vitis-ai-cpu:latest
         注意到默认启动最新版本的vitis ai, 如需启动对应的版本,在后面指定对应的序列。
    	  	         Vitis AI v1.4	./docker_run.sh xilinx/vitis-ai-cpu:1.4.916
    			 Vitis AI v1.3	./docker_run.sh xilinx/vitis-ai-cpu:1.3.411
    			 Vitis AI v1.3.1
    			 Vitis AI v1.3.2
    			 Vitis AI v1.2	./docker_run.sh xilinx/vitis-ai-cpu:1.2.82
    

    2.3 在启动vitis ai后, 可以看到vitis ai 当前支持的深度学习框架有Pytorch、Tensorflow、Tensorflow 2 和 Caffe.

    由于笔者实现的是Darknet 版本的yolov4, 网络文件为.cfg格式, 故先要对网络文件以及权重文件的格式进行转换,此处介绍两种转换方式由darknet 分别转换成Tensorflow 和 caffe. 之后对caffe 和 Tensorflow 模型进行量化和编译。
    对网络模型的量化和编译,具体可参考 vitis ai 中的技术文(https://china.xilinx.com/products/design-tools/vitis/vitis-ai.html),其中有中文版c_ug1414-vitis-ai.pdf.     
    

    2.4 Darknet Convert to Tensorflow(conda activate Tensorflow) (for pynq-dpu1.2 ,generate the dpu_model.elf )

    	STEP1: 网络模型,权重格式转换:		
    	python ../keras-YOLOv3-model-set/tools/model_converter/convert.py --yolo4_reorder ../dk_model/yolov4-voc-leaky.cfg ../dk_model/leakcy-v4.weights ../keras_model/v4_voc_leaky.h5
    	python ../keras-YOLOv3-model-set/tools/model_converter/keras_to_tensorflow.py --input_model ../keras_model/v4_voc_leaky.h5 --output_model=../tf_model/v4_tf_model.pb
            输入节点和输出节点名称因模型而异,可使用 vai_q_tensorflow 量化器来检查和估算这些节点。请参阅以下代码片段示例:
    	$ vai_q_tensorflow inspect --input_frozen_graph=../tf_model/v4_tf_model.pb
               或者通过图可视化获取图的输入和输出名称。 TensorBoard 和 Netron 均可执行此操作。请参阅以下示例, 其中使用的是 Netron:
    	$ pip install netron
    	$  netron ../tf_model/v4_tf_model.pb
    	STEP2:量化步骤:
    	vai_q_tensorflow quantize --input_frozen_graph ../tf_model/v4_tf_model.pb --input_fn yolov4_graph_input_keras_fn.calib_input   --output_dir ../chu_v4_quantized --input_nodes image_input --output_nodes conv2d_93/BiasAdd,conv2d_101/BiasAdd,conv2d_109/BiasAdd --input_shapes ?,416,416,3 --calib_iter 30
    	STEP3:COMPLIE 编译步骤		
    	pynq-dpu1.2 使用以下这个,编译生成的.elf 文件用于 Pynq-dpu1.2 版本:	
    	dnnc-dpuv2 --save_kernel --parser tensorflow --frozen_pb ../chu_v4_quantized/deploy_model.pb --dcf dpuPynq_ultra96v2.dcf  --cpu_arch arm64 --output_dir ../chu_v4_compiled --net_name tf_model_v4_416
    

    2.5 darnet convert to caffe ( conda activate caffe ) (for pynq-dpu1.3, generate the dpu_model.xmodel )

    	STEP1: MODEL CONVERT  TO CAFFE
    	python /opt/vitis_ai/conda/envs/vitis-ai-caffe/bin/convert.py ../dk_model/yolov4-voc-leaky.cfg ../dk_model/leakcy-v4.weights  ../dpu1.3.2_caffe_model/v4_leacky.prototxt ../dpu1.3.2_caffe_model/v4_leacky.caffemodel
    	STEP2:  MDOEL  QUANTI
    	*1.在量化之前,对原始的.prototxt网络拷贝一个副本,在副本中加入校准图片的路径并作如下修改,使用该副本网络进行量化;
    	  name: "Darkent2Caffe"
    	  #input: "data"
    	  #input_dim: 1
    	  #input_dim: 3
    	  #input_dim: 416
    	  #input_dim: 416
    	  ####Change input data layer to VOC validation images #####
    	  layer {
    	    name: "data"
    	    type: "ImageData"
    	    top: "data"
    	    top: "label"
    	    include {
    	      phase: TRAIN
    	    transform_param {
    	      mirror: false
    	      yolo_height:416  #change height according to Darknet model
    	      yolo_width:416   #change width according to Darknet model
    	    image_data_param {
    	      source: "voc/calib.txt"  #list of calibration imaages     
    	      root_folder: "images/" #path to calibartion images
    	      batch_size: 1
    	      shuffle: false
    	  #####No changes to the below layers##### 
    	*2.并且注意到校准图片的.txt 文档中,实现量化时需要含两列的列表文件,这与tensorflow 的校准文件的txt文档不一样。(对于量化校准,不含标签的校准数据即可足够。但实现需要含2列的图像列表文件。只需将第2列设为随机值或 0 即可)
    	*3.注意到校准图片的路径应该是docker 环境下的路径,即路径应该是 workspace 是vitis-ai 为工作空间的, 此时的vitis-ai 可以理解成主机上的home;		
    	vai_q_caffe quantize -model ../dpu1.3.2_caffe_model/v4_leacky_quanti.prototxt  -keep_fixed_neuron -calib_iter 3 -weights ../dpu1.3.2_caffe_model/v4_leacky.caffemodel -sigmoided_layers layer133-conv,layer144-conv,layer155-conv -output_dir ../dpu1.3.2_caffe_model/ -method 1 
    	STEP3:  MODEL  COMPILE 
    	vai_c_caffe --prototxt ../dpu1.3.2_caffe_model/original_model_quanti/deploy.prototxt --caffemodel ../dpu1.3.2_caffe_model/original_model_quanti/deploy.caffemodel --arch ./u96pynq_v2.json --output_dir ../dpu1.3.2_caffe_model/ --net_name dpu1-3-2_v4_voc --options "{'mode':'normal','save_kernel':''}";
    	 注意到在ultra_96_v2上,pynq-dpu1.3 中,使用编译生成好的.xmodel 文件运行网络推理时, 如果出现 footprint  not match 的现象,可将u96pynq_v2.json 文件替换成 u96pynq.json,具体可参考:https://forums.xilinx.com/t5/AI-and-Vitis-AI/vitis-ai-1-3-with-ultra96/td-p/1189251 。
    

    Part3: 在边缘端(ultra_96_v2), 使用pynq-dpu1.2 分别测试剪枝前后yolov4网络的推理速度,使用pynq-dpu1.3 分别测试剪枝前后yolov4网络消耗的能量。

       3.1  在SD(32G)卡上烧写PYNQ2.6的镜像, 镜像文件(https://github.com/Xilinx/PYNQ/releases or http://www.pynq.io/board.html) 
       3.2  在ultra_96_v2 上,载入SD卡, 启动板卡。 可以使用MobaXterm连接串口通信, 从本地浏览器中输入192.168.3.1; 在板卡上安装DPU-PYNQ https://github.com/Xilinx/DPU-PYNQ,  如果网速较慢,可以先下载到PC端上, 再从PC机中拖入到板子中对应的路径下。
       3.3  编写用于运行网络推理的notebook.ipynb, 以下为调用DPU 运行网络推理的主体步骤,(其中测试功耗的evaluation.ipynb 在test_energy文件中)。
    		* 加载模型(vitis-ai生成的.xmodel or dup_model.elf):
    		  	overlay.load_model(“dpu_model.xmodel”  )
    		* 定义dpu对象
    		   	dpu = overlay.runner
    		* 创建输入和输出Buffer
    			output_data = [np.empty(shapeOut, dtype=np.float32, order="C")]
    			input_data = [np.empty(shapeIn, dtype=np.float32, order="C")]
    		* 进行预测
    			job_id = dpu.execute_async(input_data, output_data)
    			dpu.wait(job_id)
    		* 预测的结果存储在output_data中
    

    Part4: demo.video https://www.bilibili.com/video/BV1AU4y1n7w6/.

    展示了当 image input size: 416 *416,从:1.网络的体积,2.网络的推理速度 3.网络消耗的能量,这三个方面来对比剪枝前后的网络的性能:

      1  对比剪枝前后网络模型的体积大小.     
      2  在ultra96_v2, pynq-dpu1.2,的环境下载入生成的.elf 文件,运行对应的.ipynb文件.
         2.1 测试剪枝网络模型的推理速度 250 ms.
         2.2 测试未剪枝网络模型的推理速度 330 ms. 
      3  在ultra96_v2, pynq-dpu1.3,的环境下载入生成的.xmodel 文件,运行对应的.ipynb文件.
         3.1 测试剪枝网络模型推理10 张images 所消耗的功耗,约为39J.  随后测试推理500 images,所消耗的功耗,约为1872J .
         3.2 测试未剪枝网络模型推理500 images,所消耗的功耗,约为2347J .
    
    实验结果如图1所示。

    Part5: Evaluate test-dev2017 about 21k images on the Ultra_96_v2 .

    5.1 We may use about 2.5 days( = 223978 s /60s / 60 min / 24 Hour ) to get the following information:

               top - 10:47:35 up 3 days,
    	process batch: 286
    	process batch: 287
    	save current epoch result, and this is the  epoch : 51
    	The whole number of  images: 20288
    	Total time: 223978.88142991066 seconds
    	Total energy: 867699.8735406108 J
    	root@pynq:/home/xilinx/jupyter_notebooks/lpcv_2021#
    

    Every epoch inculde 400 images, so 50 * 400 + 288 = 20288 is correct.

    5.2 The reason we divide the 20288 images into 51 epochs to test is that the ultra96_v2 board's memory is 2 G. It is often occurs running out of memory and cause the connection refused.

    Here is the solution we use, extanding the swap space temporary.

  • check all process "top"
  • Check the current usage "free -h " and show the usage of the swap "swapon --show".
  • sudo su to get the super privillage.
  • -make a folder to storage the swapfile. mkdir "root/swap/swapfile" cd to this path, if don't have this path make it.

    "sudo dd if=/dev/zero of=swap2G bs=1G count=2 " ; make a swap file

    "mkswap swap2G"; Turn the swap file into a swap space .

    "swapon swap2G "; Activate this swap space.

    5.3 We make it swap space as temporary, because we know , the swap space use regard as a "fake memory of the RAM", when use this hardware space with a high process speed, it may reduce the hardware's life.

    If you want make this swap space as a permanent,

    sudo vim /etc/fstab; add "root/swap/swapfile/swap2G swap swap defaults 0 0 " to this file.

    "swapon --show " check the swap space.

    致谢: 感谢 XILINX & NICU 共同举办的暑期学校,这是个值得纪念的Summer School, 我们度过了南京疫情和上海“烟花”台风,最终抵达 XILINX_2021 SUMMER SCHOOL的彼岸.