NNIE-lite

《NNIE-lite 为算法工程师而生》

  趟过NNIE的小伙伴可能都知道,NNIE是有很多坑的,而且是纯C的环境,除非你有几年C的开发经验,否则阅读起来不是那么容易的,而作为算法工程师,我相信更多人和我一样擅长Python和C++,所以在把NNIE用起来还是有些费力的。而作为算法工程师,你的工作更应该 focus on 模型上,现在有了NNIE-lite这个项目,极大的帮助大家脱离苦海,算法工程师可以把目光聚焦在模型效果和效率上,而不用再为其他的琐事担心了,使用NNIE像用ncnn一样简单。

Key Words:NNIE、 C++、 OpenCV


Beijing, 2020

作者:RaySue

Code:https://github.com/RaySue/NNIE-lite

Agile Pioneer  

写在前面

  • 如果你有摄像头端(海思NNIE)移植算法的需求

  • 如果你更擅长于C++编程

  • 如果你擅长使用cmake构建工程

  • 恰好你喜欢用OpenCV来进行io处理,这个比起bgr来调试十分方便

  • Come on and star the repo https://github.com/RaySue/NNIE-lite

  那么 NNIE-lite 就是非常适合你的,我当时如果有NNIE-lite这样的项目,可能至少节省我一周的时间去梳理使用NNIE的逻辑。

模型部署通用步骤(ncnn、TensorRT、MNN、OpenVION…)

  1. 模型转换 :以TensorRT为例:把你的caffe或onnx模型转为.engine文件,然后就可以利用TensorRT框架使用GPU进行加速了;

  2. 数据预处理 :准备推理输入数据,如图片颜色通道排列和分离,像素数据转换成浮点数,数据归一化处理等;

  3. 模型推理 :对输入数据进行推理计算,并输出推理数据,在手写体识别例子中,输出的是预测为0~9这10个数字对应的概率值;

  4. 后处理 :对推理输出的数据进行解析,得到最终推理结果,在分割的例子中,从Tensor中解析出最终你要的各个类别的idx组成的矩阵就是分割的结果。

NNIE 介绍

  NNIE 是 Neural Network Inference Engine 的简称,是海思媒体 SoC 中专门针对神经网络特别是深度学习卷积神经网络进行加速处理的硬件单元,支持现有大部分的公开网络,如 Alexnet、VGG16、Googlenet、Resnet18、Resnet50 等分类网络,Faster R- CNN、YOLO、SSD、RFCN 等检测网络,以及 SegNet、FCN 等场景分割网络。

sample_nnie_main.c例程函数调用关系:

NNIE-lite_第1张图片

NNIE-lite

  NNIE-lite 是面向算法工程师打造的,可以很容易的在Hisi芯片上移植算法,验证算法的效果和效率,而不必过多关心NNIE的细节,而且也不用对C语言有太多的经验。

模型转换

  参见博客https://blog.csdn.net/racesu/article/details/107045858里面详细介绍了如何搭建模型转换的环境。

构建自己的项目 pipeline

NNIE-lite_第2张图片

   在工程目录的examples中有使用NNIE-lite做通用分类和通用分割的例子,每个例子都可以单独运行,main函数中就是调用的整个流程。

最后

  希望越来越多的小伙伴能够加入到 NNIE-lite,贡献你们已经跑通的demo,我会把你们的名字写在 NNIE-lite 的页面上。

附录

  • 模型推理时间比较
模型 输入数据维度 cv500 av100
MNIST 1x28x28x1 0.1 ms 0.1 ms
Yolov1 1x448x448x3 102 ms 36 ms
Yolov2 1x416x416x3 201 ms 75 ms
Yolov3 1x416x416x3 182 ms 60 ms
SSD 1x300x300x3 149 ms 53 ms
PvaNet 1x224x224x3 43 ms 16 ms
RFCN 1x800x600x3 501 ms 180 ms
SegNet 1x224x224x3 183 ms 65 ms
ENet 1x352x640x3 250 ms 92 ms
(AlexNet)FasterRCNN 1x1240x375x3 51 ms 18 ms
LSTM 16x128x20 94 ms 34 ms
  • 实验环境: Ubuntu18.04

  海思只给提供了一个模型转换工具nnie_mapper,是把caffe模型转为nnie硬件支持的.wk的压缩模型文件。模型的原始值是float32表示的,而用8bit量化得到的是用int8来量化存储的,所以一般来说.wk模型的大小只有原始模型的四分之一,但是我转的模型却没有变小,而是变大了一点。

  因为海思并没有提供nnie_mapper的源码,所以我需要查看该执行文件依赖哪些动态库:readelf -d nnie_mapper_12 来查看依赖哪些库,并对应 Hisvp 开发指南找到相应的版本。


安装多版本gcc (gcc 4.8.5)

GNU编译器集合(GCC)是C,C ++,Objective-C,Fortran,Ada,Go和D编程语言的编译器和库的集合。许多开源项目包括GNU工具和Linux内核都是用GCC编译的。

  • Ubuntu 多版本 gcc 的安装和切换 参考:
  • 首先更新包列表:sudo apt update
  • 键入以下命令安装build-essential软件包:sudo apt install build-essential
  • 多版本安装:
    • 使用命令将ubuntu-toolchain-r/test PPA添加到您的系统:sudo apt install software-properties-common
    • sudo add-apt-repository ppa:ubuntu-toolchain-r/test
    • 安装多个版本的GCC&G++: sudo apt install gcc-4.8 g+±4.8 gcc-7 g+±7 gcc-8 g+±8 gcc-9 g+±9
    • 默认版本是具有最高优先级的版本,在我们的例子中是gcc-4.8
sudo update-alternatives --install /usr/bin/gcc gcc /usr/bin/gcc-4.8 48 --slave /usr/bin/g++ g++ /usr/bin/g++-4.8 
    
sudo update-alternatives --install /usr/bin/gcc gcc /usr/bin/gcc-8 80 --slave /usr/bin/g++ g++ /usr/bin/g++-8

sudo update-alternatives --install /usr/bin/gcc gcc /usr/bin/gcc-9 90 --slave /usr/bin/g++ g++ /usr/bin/g++-9
    
# 切换 gcc 版本, 选择4.8.5再进行后续编译操作
sudo update-alternatives --config gcc 


编译protobuf 3.5.1

下载地址:https://github.com/google/protobuf/releases 找3.5.1

编译安装

  • 1.tar -xvf protobuf; cd protobuf
  • 2.autogen.sh
  • 3.configure -prefix=/you/want/to/install/
  • 4.make
  • 5.make check
  • 6.make install
  • 7.把lib路径加入到LD_LIBRARY_PATH中,把bin加到PATH中(通过编辑~/.bashrc即可)

编译 opencv 3.4.0

下载地址
OpenCV - https://opencv.org/
opencv_contrib - github

安装依赖

  • sudo apt-get install build-essential
  • sudo apt-get install cmake git libgtk2.0-dev pkg-config libavcodec-dev libavformat-dev libswscale-dev
  • sudo apt-get install python-dev python-numpy libtbb2 libtbb-dev libjpeg-dev libtiff-dev libjasper-dev libdc1394-22-dev

编译安装

  • tar -xvzf opencv-3.4.0.tar.gz

  • cd opencv-3.4.0

  • 安装opencv_contrib【如果编译过程出现问题就不编译opencv_contrib即可】

    • mv …/opencv_contrib-3.4.0 ./
  • mkdir build; mkdir install

  • cmake -D CMAKE_BUILD_TYPE=RELEASE -D CMAKE_INSTALL_PREFIX=/x/x –D WITH_VTK=ON -D OPENCV_EXTRA_MODULES_PATH=/x/x/opencv_contrib-3.4.0/modules/ -D CUDA_NVCC_FLAGS="-std=c++11 --expt-relaxed-constexpr" -D WITH_NVCUVID=OFF -D BUILD_opencv_cudacodec=OFF -D ENABLE_CXX11=YES . . .. ..

    • OPENCV_EXTRA_MODULES_PATH=你的opencv_contrib/modules的位置
    • CMAKE_INSTALL_PREFIX=你想安装的位置
    • cuda10以上没有dynlink_nvcuvid.h和nvcuvid.h,所以要将BUILD_opencv_cudacodec=OFF
    • 如果编译opencv-contrib需要下载boost之类的可以不编译这个,即去掉OPENCV_EXTRA_MODULES_PATH
  • make

  • make check

  • make install

  • CMAKE_INSTALL_PREFIX 中就是你需要的include lib bin

加入nnie_env.sh中,并source

# protobuf
export PATH=$PATH:/home/surui/Documents/software/protobuf-3.5.1/release/bin
export LD_LIBRARY_PATH=$LD_LIBRARY_PATH:/home/surui/Documents/software/protobuf-3.5.1/release/lib
# OpenCV
export LD_LIBRARY_PATH=$LD_LIBRARY_PATH:/home/surui/Documents/software/opencv-3.4.0/release/lib

模型转换

注意

你的gcc的版本最好是4.8,我的是4.8.5,而且你的protobuf需要是在这个版本下编译的,否则会报错
undefined symbol:_ZN6google8protobuf8internal26fixed_address_empty_stringE

用命令:nm -s libprotobuf.so|grep _ZN6google8protobuf8internal26fixed_address_empty_stringE 会发现有这个符号,但是多了B5cxx11,这个是和编译程序的 gcc 程序有关系,由于 protobuf 的源码中含有c++程序,所以需要使用 gcc4.8.5 和 g++4.8.5 来编译 protobuf 才行。

模型转换命令:

nnie_mapper_12 model.cfg

model.cfg 文件介绍:

[prototxt_file]  model.prototxt          # caffe 的prototxt  
[caffemodel_file] model.caffemodel       # caffe 的model文件
[batch_num] 1                            # [单张模式/多张模式]
[net_type] 0                             
[sparse_rate] 0                          # 0 - 不稀疏处理 0.5 - 0.5稀疏
[compile_mode] 1                         # 0 - 高速模式损失精度 1 - 高精度模式
[is_simulation] 0                        # 0 - 芯片模式 1 - 仿真模式用于pc端 
[log_level] 2
[instruction_name] save_model   # 存储的NNIE模型文件名 
[image_list] ./file_list.txt    # 用于存储数据的决定路径,30张左右的样例数据用于量化模型
[image_type] 1           # 1 - 表示网络数据输入为 SVP_BLOB_TYPE_U8(普通的灰度图和RGB图)类型; 此时要求 image_list 配置是 RGB 图或者灰度图片的 list 文件;
[mean_file] ./mean.txt   # 均值文件,用于数据的标准化,每行代表一个通道要减去的值
[norm_type] 5            # 0 - 不做预处理 5 - 减通道均值后再乘以 data_scale
[RGB_order] BGR 
[data_scale] 1           # 0.00390625 = 1/ 256;1 就是不缩放
[internal_stride] 16  # 数据的维度必须是16的倍数,否则按16的倍数补全,默认为16,修改无效




参考

https://zhuanlan.zhihu.com/p/67327779
https://blog.csdn.net/ywcpig/article/details/85260752

你可能感兴趣的:(深度学习移动端部署)