基于zynq FPGA平台的目标检测网络实现项目汇报与交接

背景:着手深度学习的FPGA实现的项目半年以来,实现了大量工作,现在需要移交项目,所以总结项目所有的情况,以及移交。

目录

一、项目概览

二、python端

2.1 MTCNN与训练过程

2.2 mAP的测试

2.3 网络结构的更改

2.4 输出python训练的权重到c代码端

python之中的顺序

c代码之中的顺序

三、c代码端

3.1 文件描述

程序文件

权重文件

更改结构顺序

3.2 卷积的更改

初始的依赖openBLAS的卷积函数

重新运用定义编写卷积代码

加入bias和ReLU

存储顺序

 四、硬件端

4.1 卷积IPcore

4.2 IPcore报告

时间资源

空间资源

4.3 ARM端工作

五、交接后续需要的工作


一、项目概览

项目分为python端,c代码端,硬件端。

python端用于确定相应的网络模型结构,训练模型。从而根据相应的权重进行保存。

c++端用于实现神经网络的推断,也就是只有前馈的预测运算。根据相应的python端的权重,和输入图片,预测得出相应的bounding box。一是因为c++代码执行效率高,并且省去了训练的过程,只有前馈运算过程。二是实现为c++代码可以方便于后面的HLS部署于FPGA上。

硬件端用于部署相应的网络结构。分为ARM端和FPGA端,ARM端就是arm架构,可以用c++代码直接交叉编译即可,FPGA端为FPGA架构,需要将相应的程序通过HLS实现为IPcore,烧写到FPGA上,然后用ARM控制进行运算。

二、python端

2.1 MTCNN与训练过程

https://github.com/wangbm/MTCNN-Tensorflow

MTCNN是三个级联的网络,Pnet用于生成备选框,Rnet用于对备选框初次筛选,Onet用于确定最终输出的备选框。

所以训练过程需要训练三个网络。

 训练流程见上面连接的内容。

2.2 mAP的测试

mAP为目标检测领域的基础指标。

首先标签相同交并比IoU>0.5表示网络检测正确。

然后画出相应的查全率与查准率的曲线,积分得到的蓝色区域即为mAP。

各类的平均AP即mAP

测试mAP需要将程序做一定的修改,将所有图像的预测标签与groundTruth放入文件夹之中。然后测试。

这一系列过程被封装好,封装到test_all.py之中。

2.3 网络结构的更改

在原始结构的基础上,

  • 重新制作公交人头数据集,重新训练以在公交人头数据集上运行
  • 为了增加硬件平台的功能(最好确定为定长度的),将卷积固定为3x3,
  • 去掉pooling的过程,运用stride为2的卷积来替代以增加并行性。
  • 然后将PReLU改为ReLU,这样不用存储斜率。
  • 增加一定量的通道数量,以增加mAP
  • 在文件mtcnn.py之中
  • 更改后的网络结构表 https://blog.csdn.net/weixin_36474809/article/details/85990687

2.4 输出python训练的权重到c代码端

python权重与c权重顺序很不一样。python之中权重为四维张量,c代码之中为线性存储的。

python之中的顺序

c代码之中的顺序

 因为是线性存储,所以需要一系列偏移地址找到权重位置:

三、c代码端

3.1 文件描述

程序文件

  • mtcnn.cpp .hpp : Network structure definition of MTCNN 网络结构的定义
  • network.cpp hpp : Basic functions such as conv , relu , padding  基本的函数实现,比如卷积,reLU,padding
  • pbox.cpp .hpp : definition of basic data format.  基本的数据结构定义。例如pBox结构体,里面存了宽,高,通道数和数据指针指向数据。

权重文件

  • Pnet.bin , Rnet.bin , Onet.bin total 3.0 MB 三个权重文件3MB,为了减少FPGA数据流量
  • Generated by python 通过前面的python端训练产生。
  • Read by readData function. 通过c文件之中的readData函数读取。之前c代码之中权重文件为.txt格式,我们改为 .bin格式,数据更紧密。
  • readData function difinied in network.cpp, function called in mtcnn.cpp

更改结构顺序

c代码的网络结构需要与python代码的结构一致。每次更改网络结构之后,需要做以下的修改。

  • Changing python code network structure。更改python代码的结构
  • Rerun python training code 重新训练python端的代码
  • Generate weight file. 输出权重文件
  • In mtcnn.hpp , change the structure of class Pnet(Rnet,Onet) private definition. 在mtcnn.hpp程序之中更改类Pnet(Rnet,Onet)的private定义
  • In mtcnn.cpp , change class Pnet(Rnet,Onet) construct function and destruct function. 在mtcnn.cpp更改相应的类的构造函数和析构函数
  • Change parameters in dataNumber, pointTeam, readData for weight file read.更改与权重读取相关的三个函数及参量:dataNumber, pointTeam, readData。
  • Change Init function for each layer buffer malloc.更改实现相应的层的init函数,init函数用于开辟内存空间。
  • Change run function to run each layer. 更改每层的运行函数。

3.2 卷积的更改

初始的依赖openBLAS的卷积函数

openBLAS为线性代数实现的函数。

卷积的运用滑窗函数实现为一个二维矩阵,然后与权重排列成的二维矩阵实现矩阵乘。这也是大多数卷积的实现方式。但是这种方法无法实现于FPGA之上。并且每次进行取框函数会加大运算量。

Convolution in 2D matrix multiplication format:
// input Weight matrix  *  input feature matrix(Trans) = output feature matrix
// height (outChannels)    height (3D_KernelSize)        height (outChannels)
// width  (3D_KernelSize)  width  (outFeatureSize)       width  (outFeatureSize)

重新运用定义编写卷积代码

我们需要从卷积的定义出发,编写卷积函数。

Without feature_2_matrix process: 
//  outpBox [out_ChannelNum][out_height][out_width] 
//  +=weightIn[out_ChannelNum][in_ChannelNum][kernelWidth][kernelHeight] 
//  *pboxIn[in_ChannelNum][width][height] 

伪代码如上,这样,既不用滑窗函数,而且生成的output也可以被下层当作feature直接运用。

定义出发的卷积方便zynqNet改为FPGA内并行的结构。实现加速。

加入bias和ReLU

卷积后的过程并入卷积函数利用并行化,尽可能多的将任务给FPGA实现。

存储顺序

 四、硬件端

4.1 卷积IPcore

卷积IPcore的实现参考zynqNet的结构,在DDR上搬运数据,传入BRAM上,然后通过并行实现加速。

关于IPcore的实现有很多内容,可以参考之前的博客

Validated in MTCNN code 嵌入入MTCNN代码之中验证

Validated in HLS test bench (C-simulation) 嵌入HLS的test Bench之中验证。也就是实现c仿真。

Validated in synthesis and generate report 通过synthesisi和生成相应的报告

Export RTL 输出RTL代码

C-RTL co-simulation C与RTL协同仿真。

4.2 IPcore报告

https://blog.csdn.net/weixin_36474809/article/details/85271940

时间资源

zynqNet的时钟周期如下,基本与卷积IPcore为同一个数量级。

从MACC的次数考虑

zynqNet的MACC次数固定为 : 152,731,648,整个网络运行时间为2s

MTCNN:

从43,543,288 到85,176,568

按照此时间预测,MTCNN的时间为:

From 0.57sec – 1.12sec

空间资源

 即使占用的资源比zynqNet少很多,但是MIZ7020平台上资源超出预期。

在7035平台上资源够用。

4.3 ARM端工作

 刚开始的MTCNN代码分开的开辟每层的卷积,对于调用IPcore来讲非常耗时。

所以需要更改为在DDR一次性的开辟所有的内存反复调用。

五、交接后续需要的工作

模型压缩,使资源可以在7020平台上运行

你可能感兴趣的:(FPGA,机器学习,MTCNN,目标检测)