• 快科技
  • 中文科技资讯专业发布平台
Paddlepaddle从零开始 试用Edgeboard模型
2019-07-16 16:16:51  作者:安妮 编辑:安妮   点击可以复制本篇文章的标题和链接

作者  Litchll

摘要:前言 在上一周的测试中,我们按照官方给的流程,使用EasyDl快速实现了一个具有性别检测功能的人脸识别系统,那么 今天,我们将要试一下通过Paddlepaddle从零开始,训练一个自己的多分类模型,并进行嵌入式部署。 整个训练 过程和模型在:https://aistudio.baidu.com/aistudio/projectDetail/61103 下面详细介绍模型训练...

前言

在上一周的测试中,我们按照官方给的流程,使用EasyDl快速实现了一个具有性别检测功能的人脸识别系统,那么

今天,我们将要试一下通过Paddlepaddle从零开始,训练一个自己的多分类模型,并进行嵌入式部署。 整个训练

过程和模型在:https://aistudio.baidu.com/aistudio/projectDetail/61103 下面详细介绍模型训练的过程.

数据集准备

我们使用CIFAR10数据集。CIFAR10数据集包含60,000张32x32的彩色图片,10个类别,每个类包含6,000张。其中

50,000张图片作为训练集,10000张作为验证集。

1.!mkdir ‐p /home/aistudio/.cache/paddle/dataset/cifar 

2.# wget将下载的文件存放到指定的文件夹下,同时重命名下载的文件,利用‐O 

3.!wget "http://ai‐atest.bj.bcebos.com/cifar‐10‐python.tar.gz" ‐O cifar‐10‐python.tar.gz 

4.!mv cifar‐10‐python.tar.gz /home/aistudio/.cache/paddle/dataset/cifar/ 

模型结构

我们选择了以三个卷积层串联一个全连接层的输出,作为猫狗分类的预测,采用固定维度输入,输出为分类数

1.def convolutional_neural_network(img): 

2.# 第一个卷积‐池化层 

3.conv_pool_1 = fluid.nets.simple_img_conv_pool( 

4.input=img, # 输入图像 

5.filter_size=5, # 滤波器的大小 

6.num_filters=20, # filter 的数量。它与输出的通道相同 

7.pool_size=2, # 池化层大小2*2 

8.pool_stride=2, # 池化层步长 

9.act="relu") # 激活类型 

10.# 第二个卷积‐池化层 

11.conv_pool_2 = fluid.nets.simple_img_conv_pool( 

12.input=conv_pool_1, 

13.filter_size=5, 

14.num_filters=50, 

15.pool_size=2, 

16.pool_stride=2, 

17.act="relu") 

18.# 第三个卷积‐池化层 

19.conv_pool_3 = fluid.nets.simple_img_conv_pool( 

20.input=conv_pool_2, 

21.filter_size=5, 

22.num_filters=50, 

23.pool_size=2, 

24.pool_stride=2, 

25.act="relu") 

26.# 以softmax为激活函数的全连接输出层,10类数据输出10个数字 

27.prediction = fluid.layers.fc(input=conv_pool_3, size=10, act='softmax') 

28.return prediction 

训练&验证

接下来在Paddlepaddle fluid上,进行训练。整个训练代码见附件train.py 模型验证,采用附件predict.py的代码进

行验证与运行时间的测量,选取一张狗的图:dog.jpg (可以fork首页链接aistudio平台上的demo) 连续预测10000

次,输出如下:

1.CPU 运行结果为:预处理时间为0.0006270000000085929,预测时间为:16.246494 

2.Out: 

3.im_shape的维度: (1, 3, 32, 32) 

4.The run time of image process is 

5.0.0006270000000085929 

6.The run time of predict is 

7.16.246494 

8.results [array([[5.0159363e‐04, 3.5942634e‐05, 2.5955746e‐02, 4.7745958e‐02, 

9.      9.9251214e‐03, 9.0146154e‐01, 1.9564393e‐03, 1.2230080e‐02, 

10.    4.7619540e‐08, 1.8753216e‐04]], dtype=float32)] 

11.infer results: dog 

 

1.GPU V100 运行结果为:预处理时间为0.0006390000000067175,预测时间为:15.903074000000018 

2.Out: 

3.im_shape的维度: (1, 3, 32, 32) 

4.The run time of image process is 

5.0.0006390000000067175 

6.The run time of predict is 

7.15.903074000000018 

8.results [array([[5.0159392e‐04, 3.5942641e‐05, 2.5955772e‐02, 4.7746032e‐02, 

9.     9.9251205e‐03, 9.0146142e‐01, 1.9564414e‐03, 1.2230078e‐02, 

10.   4.7619821e‐08, 1.8753250e‐04]], dtype=float32)] 

11.infer results: dog 

可以看到,模型可以正确的识别出图片中的动物为狗,接下来,我们就要尝试将这个模型部署到Edgeboard上面。

模型导出

我们需要将模型保存为模型文件model以及权重文件params,可以采用如下Paddle的API进行保存如图所示,在AiStudio的左侧打开模型文件所在的文件夹,下载mlp-model、mlp-params两个文件。

Paddlepaddle从零开始 试用Edgeboard模型

在Edgeboard上部署模型,完成预测

1、新建工程文件夹,目录结构如下(可以仿照sample里的resnet、inception例程):

1.‐sample_image_catdog 

2.      ‐build 

3.      ‐image 

4.      ‐include 

5.             ‐paddlepaddle‐mobile 

6.             ‐... 

7.      ‐lib 

8.            ‐libpaddle‐mobile.so 

9.      ‐model 

10.          ‐mlp 

11.             ‐model 

12.             ‐params 

13.      ‐src 

14.             ‐fpga_cv.cpp 

15.             ‐main.cpp 

2、将AiStudio上导出来的模型放置在model里的mlp文件夹,修改名字为model、params

Paddlepaddle从零开始 试用Edgeboard模型

3、新建 CMakeLists.txt

1.cmake_minimum_required(VERSION 3.5.1) 

2.project(paddle_edgeboard) 

3.set(CMAKE_CXX_STANDARD 14) 

4.set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} ‐pthread") 

5.add_definitions(‐DPADDLE_MOBILE_FPGA_V1) 

6.add_definitions(‐DPADDLE_MOBILE_FPGA) 

7.set(PADDLE_LIB_DIR "${PROJECT_SOURCE_DIR}/lib" ) 

8.set(EASYDL_INCLUDE_DIR "${PROJECT_SOURCE_DIR}/include" ) 

9.set(PADDLE_INCLUDE_DIR "${PROJECT_SOURCE_DIR}/include/paddle‐mobile" ) 

10.set(APP_NAME "paddle_edgeboard" ) 

11.aux_source_directory(${CMAKE_CURRENT_SOURCE_DIR}/src SRC) 

12.find_package(OpenCV QUIET COMPONENTS core videoio highgui imgproc imgcodecs ml video) 

13.include_directories(SYSTEM ${OpenCV_INCLUDE_DIRS}) 

14.#list(APPEND Caffe_LINKER_LIBS ${OpenCV_LIBS}) 

15.message(STATUS "OpenCV found (${OpenCV_CONFIG_PATH}),${OpenCV_LIBS}") 

16.#add_definitions(‐DUSE_OPENCV) 

17.include_directories(${EASYDL_INCLUDE_DIR}) 

18.include_directories(${PADDLE_INCLUDE_DIR}) 

19.LINK_DIRECTORIES(${PADDLE_LIB_DIR}) 

20.add_executable(${APP_NAME} ${SRC}) 

21.target_link_libraries(${APP_NAME} paddle‐mobile) 

22.target_link_libraries(${APP_NAME} ${OpenCV_LIBS} ) 

4、main.cpp

1.#include 

<

 

iostream

>

 

2.#include "io/paddle_inference_api.h"

3.#include "math.h"

4.#include 

<

 

stdlib.h

 

5.#include 

<

 

unistd.h

 

6.#include 

<

 

fstream

>

 

7.#include 

<

 

ostream

>

 

8.#include 

<

 

fstream

 

9.#include 

<

 

iomanip

 

10.#include 

<

 

typeinfo

>

 

11.#include 

<

 

typeindex

 

12.#include 

<

 

vector

 

13.#include

<

 

ctime

 

14.#include "fpga/KD/float16.hpp" 

15.#include "fpga/KD/llapi/zynqmp_api.h" 

16.using namespace paddle_mobile; 

17.#include 

<

 

opencv2/highgui.hpp

 

18.#include 

<

 

opencv2/imgproc.hpp

 

19.using namespace cv; 

20.cv::Mat sample_float; 

21.static std::vector

<

 

std::string

 

label_list(10); 

22.void readImage(std::string filename, float* buffer) { 

23.Mat img = imread(filename); 

24.if (img.empty()) { 

25.std::cerr 

<

 

 

"Can't read image from the file: " 

<

 

 

filename 

<

 

 

std::endl; 

26.exit(1); 

27.} 

28.Mat img2;

29.resize(img, img2, Size(32,32)); 

30.img2.convertTo(sample_float, CV_32FC3); 

31.int index = 0; 

32.for (int row = 0; row 

 

sample_float.rows; ++row) { 

33.float* ptr = (float*)sample_float.ptr(row); 

34.for (int col = 0; col 

 

sample_float.cols; col++) { 

35.float* uc_pixel = ptr; 

36.// uc_pixel[0] ‐= 102; 

37.// uc_pixel[1] ‐= 117; 

38.// uc_pixel[1] ‐= 124; 

39.float r = uc_pixel[0]; 

40.float g = uc_pixel[1]; 

41.float b = uc_pixel[2]; 

42.buffer[index] = b / 255.0; 

43.buffer[index + 1] = g / 255.0; 

44.buffer[index + 2] = r / 255.0; 

45.// sum += a + b + c; 

46.ptr += 3; 

47.// DLOG 

<

 

 

"r:" 

<

 

 

<

 

<

 

 " g:" 

<

 

 

<

 

 

" b:" 

<

 

 

b; 

48.index += 3; 

49.} 

50.} 

51.// return sample_float; 

52.} 

53.PaddleMobileConfig GetConfig() { 

54.PaddleMobileConfig config; 

55.config.precision = PaddleMobileConfig::FP32; 

56.config.device = PaddleMobileConfig::kFPGA; 

57.// config.model_dir = "../models/mobilenet/"; 

58.config.prog_file = "../model/mlp/model"; 

59.config.param_file = "../model/mlp/params"; 

60.config.thread_num = 4; 

61.return config; 

62.} 

63.int main() { 

64.clock_t startTime,endTime; 

65.zynqmp::open_device(); 

66.std::cout 

<

 

<

 

 " open_device success " 

<

 

 

std::endl; 

67.PaddleMobileConfig config = GetConfig(); 

68.std::cout 

<

 

 

" GetConfig success " 

<

 

 

std::endl; 

69.auto predictor = 

70.CreatePaddlePredictor

<

 

PaddleMobileConfig, 

71.PaddleEngineKind::kPaddleMobile

>

 

(config); 

72.std::cout 

<

 

 

" predictor success " 

<

 

 

std::endl; 

73.startTime = clock();//计时开始 

74.float data[1 * 3 * 32 * 32] = {1.0f}; 

75.readImage("../image/cat.jpg", data); 

76.endTime = clock();//计时结束 

77.std::cout 

<

 

 

"The run time of image process is: " 

<

 

<

 

(double)(endTime ‐ startTime) / 

78.CLOCKS_PER_SEC 

<

 

 

"s" 

<

 

<

 

 std::endl; 

79.PaddleTensor tensor; 

80.tensor.shape = std::vector

<

 

int

>

 

({1, 3, 32, 32}); 

81.tensor.data = PaddleBuf(data, sizeof(data)); 

82.tensor.dtype = PaddleDType::FLOAT32; 

83.std::vector

<

 

PaddleTensor

 

paddle_tensor_feeds(1, tensor); 

84.PaddleTensor tensor_out; 

85.tensor_out.shape = std::vector

<

 

int

>

 

({}); 

86.tensor_out.data = PaddleBuf(); 

87.tensor_out.dtype = PaddleDType::FLOAT32; 

88.std::vector

<

 

PaddleTensor

 

outputs(1, tensor_out); 

89.std::cout 

<

 

 

" before predict " 

<

 

 

std::endl; 

90.predictor‐

>

 

Run(paddle_tensor_feeds, &outputs); 

91.std::cout 

<

 

<

 

 " after predict " 

<

 

<

 

 std::endl; 

92.// assert(); 

93.endTime = clock();//计时结束 

94.std::cout << "The run time of predict is: " <<(double)(endTime ‐ startTime) / CLOCKS_PER_SEC 

95.<

 

"s" 

<

 

<

 

 std::endl; 

96.float* data_o = static_cast

<

 

float*

>

 

(outputs[0].data.data()); 

97.for (size_t j = 0; j 

 

outputs[0].data.length() / sizeof(float); ++j) { 

98.std::cout 

<

 

<

 

 "output[" 

<

 

<

 

 j 

<

 

<

 

 "]: " 

<

 

 

data_o[j] 

<

 

<

 

 std::endl; 

99.} 

100.int index = 0; 

101.float max = 0.0; 

102.for (int i = 0;i 

<

 

 10; i++) { 

103.float val = data_o[i]; 

104.if (val 

>

 

 max) { 

105.max = val 

>

 

 max ? val : max; 

106.iindex = i; 

107.} 

108.} 

109.label_list = {"airplane", "automobile", "bird", "cat", "deer", "dog", "frog", "horse", 

110."ship", "truck" }; 

111.std::cout 

<

 

 

"Result" 

<

 

<

 

 " is " 

<

 

 

label_list[index] 

<

 

 

std::endl; 

112.return 0; 

113.} 

5、编译运行

1.insmod /home/root/workspace/driver/fpgadrv.ko 

2.cd /home/root/workspace/sample/sample_image_catdog 

3.mkdir build 

4.cd build 

5.rm ‐rf * 

6.cmake .. 

7.make 

8../paddle_edgeboard 

修改main文件要预测的图像:

Paddlepaddle从零开始 试用Edgeboard模型

Paddlepaddle从零开始 试用Edgeboard模型

6、修改main文件后重复执行预测,可得结果如下:图像处理时间大概为:0.006秒,预测时间大概为:0.008秒

Paddlepaddle从零开始 试用Edgeboard模型

Paddlepaddle从零开始 试用Edgeboard模型

7、连续预测10000次所用时间为:23.7168

Paddlepaddle从零开始 试用Edgeboard模型

性能对比(连续预测10000次 单位:秒)

Paddlepaddle从零开始 试用Edgeboard模型

总结

优点:

1. EdgeBoard内置的Paddle-Mobile,可以与Paddle训练出来的模型进行较好的对接。

2. 预测速度上: Edge在预测小模型的时候,能与双核CPU和GPU在一个数量级,估计是模型较小,batch size也

为1,gpu,cpu的性能优势抵不过通信的开销,后续将进行大模型、高batch size的测试。

3. 提供的demo也足够简单,修改起来难度很低。

不足:

1. Paddle-Mobile相关文档具有一定门槛,且较为分散。初次使用的时候会走一些弯路出现问题的时候往往是个

黑盒,不易于定位。在这次进行模型训练的尝试中,出现过一次op不支持的情况,我们在官网上甚至没有找

到支持的op列表,这个在开发哥们的支持下升级版本后解决。如果后续能在稳定的固件版本下使用,并有比

较易用的sdk,开发门槛可能会进一步降低。

微信公众号搜索" 驱动之家 "加关注,每日最新的手机、电脑、汽车、智能硬件信息可以让你一手全掌握。推荐关注!【微信扫描下图可直接关注

文章价值打分
当前文章打分0 分,共有0人打分
文章观点支持

+0
+0