Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up
Appearance settings

midasklr/yolov5ncnn

Repository files navigation

YOLOv5转NCNN

update20210608

新增yolov5模型剪枝和NCNN INT8量化。

项目持续更新,主要包括yolov5s模型的剪枝,int8量化,ncnn模型转换和Android移植测试。

基于YOLOv5最新v5.0 release,和NCNN官方给出example的差别主要有:

编译运行

动态库用的是官方编译好的ncnn-20210507-ubuntu-1604-shared

mkdir build 
cd build
cmake ..
make -j8
./yolov5 ../bus.jpg

可以看到:

安卓

参考https://github.com/nihui/ncnn-android-yolov5 ,使用这里转的v5.0分支的ncnn模型。

Yolov5s剪枝

https://github.com/midasklr/yolov5prune 稀疏训练+Bn层剪枝,可以获得更加紧凑的模型,这里一次稀疏训练+60%Bn层剪枝,模型从28M降低到7M。

流程

以下为yolov5s.pt转NCNN流程,自己训练的模型一样:

pytorch测试和导出onnx

先测试下yolov5s效果:

python detect.py --weights yolov5s.pt --source data/images

效果不错:

导出 onnx,并用 onnx-simplifer 简化模型,这里稍微不同,如果按照详细记录u版YOLOv5目标检测ncnn实现,那么直接导出来的模型可以看到输出:

python models/export.py --weights yolov5s.pt --img 640 --batch 1

可以看到后处理怎么都出来了???

看看models/yolo.py代码发现:

inference里面不就对应上面onnx模型那部分输出处理后然后torch.cat起来么,这部分处理我们放在代码里面做,所以可以注释这部分:

这样导出来的模型就是三个输出了:

ok,输出和详细记录u版YOLOv5目标检测ncnn实现对应上了,同时可以看到激活函数silu:

经过onnx-sim简化一下:

python -m onnxsim yolov5s.onnx yolov5s-sim.onnx

转换和实现focus模块等

后续和详细记录u版YOLOv5目标检测ncnn实现一样,ncnn转化后激活函数转为swish,可swish的实现:

Swish::Swish()
{
 one_blob_only = true;
 support_inplace = true;
}
int Swish::forward_inplace(Mat& bottom_top_blob, const Option& opt) const
{
 int w = bottom_top_blob.w;
 int h = bottom_top_blob.h;
 int channels = bottom_top_blob.c;
 int size = w * h;
 #pragma omp parallel for num_threads(opt.num_threads)
 for (int q = 0; q < channels; q++)
 {
 float* ptr = bottom_top_blob.channel(q);
 for (int i = 0; i < size; i++)
 {
 float x = ptr[i];
 ptr[i] = static_cast<float>(x / (1.f + expf(-x)));
 }
 }
 return 0;
}
} // namespace ncnn

和silu一样,那么就可以正常进行推理了,可能需要注意的就是三个输出节点不要弄错就ok。

INT8量化

1. NCNN源码编译

  1. 最新ncnn新增支持int8量化
git clone https://github.com/Tencent/ncnn.git
cd ncnn
git submodule update --init
  1. 增加Focus层

    将layer/yolov5focus.cpp/.h 两个文件放在ncnn/src/layer下,然后ncnn/src/CMakeList.txt增加:

    ncnn_add_layer(YoloV5Focus)
    
  2. 编译

不同系统的编译见https://github.com/Tencent/ncnn/wiki/how-to-build

编译完成后会有:

ncnn/build/tools/onnx/onnx2ncnn :用于onnx转ncnn的工具

/ncnn/build/tools/ncnnoptimize 优化工具

ncnn/build/tools/quantize/ncnn2int8 转int8

ncnn/build/tools/quantize/ncnn2table 生成校准表

2. 模型量化

参考https://github.com/Tencent/ncnn/wiki/quantized-int8-inference 操作,在ncnn2table工具下,准备我们的检验图片放在images文件夹下,最好是我们训练模型的验证或者测试集,这里使用coco val数据集5k张图片。

然后

find images/ -type f > imagelist.txt
./ncnn2table yolov5s-opt.param yolov5s-opt.bin imagelist.txt yolov5s.table mean=[0,0,0] norm=[0.0039215,0.0039215,0.0039215] shape=[416,416,3] pixel=BGR thread=8 method=kl

校准表见INT8/yolov5s.table。

然后转化模型:

./ncnn2int8 yolov5s-opt.param yolov5s-opt.bn yolov5s-int8.param yolov5s-int8.bin yolov5s.table

转化后的int8模型见yolov5s-int8.param和yolov5s-int8.bin。

3. INT8 推理

使用最新的动态库:https://github.com/Tencent/ncnn/releases/tag/20210525

根据你的系统选择。

相关设置:

 yolov5.opt.num_threads = 8;
 yolov5.opt.use_int8_inference = true;

FP16模型和INT8模型对比:

kl和aciq两种量化方式,前者损失会更大。

input inference time model size
yolov5s 416 22 ms 14.6 M(fp16)
yolov5s-prune 416 18 ms 1.7 M(fp16)
yolov5s-int8 416 52ms 887.5k(int8)

目前int8量化后效果还不错,但是推理时间慢了很多,可能原因是int8不针对x86,参考Tencent/ncnn#2974 后续测试arm上加速效果

About

ncnn of yolov5 v5.0 branch

Resources

Stars

Watchers

Forks

Releases

No releases published

Packages

Contributors

AltStyle によって変換されたページ (->オリジナル) /