Paddlepaddle從零開始 試用Edgeboard模型
作者 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"‐Ocifar‐10‐python.tar.gz
4.!mvcifar‐10‐python.tar.gz/home/aistudio/.cache/paddle/dataset/cifar/
模型結構
我們選擇了以三個卷積層串聯一個全連接層的輸出,作為貓狗分類的預測,采用固定維度輸入,輸出為分類數
1.defconvolutional_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.returnprediction
訓練&驗證
接下來在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.Theruntimeofimageprocessis
5.0.0006270000000085929
6.Theruntimeofpredictis
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.inferresults:dog
1.GPUV100運行結果為:預處理時間為0.0006390000000067175,預測時間為:15.903074000000018
2.Out:
3.im_shape的維度:(1,3,32,32)
4.Theruntimeofimageprocessis
5.0.0006390000000067175
6.Theruntimeofpredictis
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.inferresults:dog
可以看到,模型可以正確的識別出圖片中的動物為狗,接下來,我們就要嘗試將這個模型部署到Edgeboard上面。
模型導出
我們需要將模型保存為模型文件model以及權重文件params,可以采用如下Paddle的API進行保存如圖所示,在AiStudio的左側打開模型文件所在的文件夾,下載mlp-model、mlp-params兩個文件。
在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
3、新建 CMakeLists.txt
1.cmake_minimum_required(VERSION3.5.1)
2.project(paddle_edgeboard)
3.set(CMAKE_CXX_STANDARD14)
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}/srcSRC)
12.find_package(OpenCVQUIETCOMPONENTScorevideoiohighguiimgprocimgcodecsmlvideo)
13.include_directories(SYSTEM${OpenCV_INCLUDE_DIRS})
14.#list(APPENDCaffe_LINKER_LIBS${OpenCV_LIBS})
15.message(STATUS"OpenCVfound(${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.usingnamespacepaddle_mobile;
17.#include
<
opencv2/highgui.hpp
>
18.#include
<
opencv2/imgproc.hpp
>
19.usingnamespacecv;
20.cv::Matsample_float;
21.staticstd::vector
<
std::string
>
label_list(10);
22.voidreadImage(std::stringfilename,float*buffer){
23.Matimg=imread(filename);
24.if(img.empty()){
25.std::cerr
<
<
"Can'treadimagefromthefile:"
<
<
filename
<
<
std::endl;
26.exit(1);
27.}
28.Matimg2;
29.resize(img,img2,Size(32,32));
30.img2.convertTo(sample_float,CV_32FC3);
31.intindex=0;
32.for(introw=0;row
<
sample_float.rows;++row){
33.float*ptr=(float*)sample_float.ptr(row);
34.for(intcol=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.floatr=uc_pixel[0];
40.floatg=uc_pixel[1];
41.floatb=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:"
<
<
r
<
<
"g:"
<
<
g
<
<
"b:"
<
<
b;
48.index+=3;
49.}
50.}
51.//returnsample_float;
52.}
53.PaddleMobileConfigGetConfig(){
54.PaddleMobileConfigconfig;
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.returnconfig;
62.}
63.intmain(){
64.clock_tstartTime,endTime;
65.zynqmp::open_device();
66.std::cout
<
<
"open_devicesuccess"
<
<
std::endl;
67.PaddleMobileConfigconfig=GetConfig();
68.std::cout
<
<
"GetConfigsuccess"
<
<
std::endl;
69.autopredictor=
70.CreatePaddlePredictor
<
PaddleMobileConfig,
71.PaddleEngineKind::kPaddleMobile
>
(config);
72.std::cout
<
<
"predictorsuccess"
<
<
std::endl;
73.startTime=clock();//計時開始
74.floatdata[1*3*32*32]={1.0f};
75.readImage("../image/cat.jpg",data);
76.endTime=clock();//計時結束
77.std::cout
<
<
"Theruntimeofimageprocessis:"
<
<
(double)(endTime‐startTime)/
78.CLOCKS_PER_SEC
<
<
"s"
<
<
std::endl;
79.PaddleTensortensor;
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.PaddleTensortensor_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
<
<
"beforepredict"
<
<
std::endl;
90.predictor‐
>
Run(paddle_tensor_feeds,&outputs);
91.std::cout
<
<
"afterpredict"
<
<
std::endl;
92.//assert();
93.endTime=clock();//計時結束
94.std::cout<<"Theruntimeofpredictis:"<<(double)(endTime‐startTime)/CLOCKS_PER_SEC
95.<
<
"s"
<
<
std::endl;
96.float*data_o=static_cast
<
float*
>
(outputs[0].data.data());
97.for(size_tj=0;j
<
outputs[0].data.length()/sizeof(float);++j){
98.std::cout
<
<
"output["
<
<
j
<
<
"]:"
<
<
data_o[j]
<
<
std::endl;
99.}
100.intindex=0;
101.floatmax=0.0;
102.for(inti=0;i
<
10;i++){
103.floatval=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.return0;
113.}
5、編譯運行
1.insmod/home/root/workspace/driver/fpgadrv.ko
2.cd/home/root/workspace/sample/sample_image_catdog
3.mkdirbuild
4.cdbuild
5.rm‐rf*
6.cmake..
7.make
8../paddle_edgeboard
修改main文件要預測的圖像:
6、修改main文件后重復執行預測,可得結果如下:圖像處理時間大概為:0.006秒,預測時間大概為:0.008秒
7、連續預測10000次所用時間為:23.7168
性能對比(連續預測10000次 單位:秒)
優點:
1. EdgeBoard內置的Paddle-Mobile,可以與Paddle訓練出來的模型進行較好的對接。
2. 預測速度上: Edge在預測小模型的時候,能與雙核CPU和GPU在一個數量級,估計是模型較小,batch size也
為1,gpu,cpu的性能優勢抵不過通信的開銷,后續將進行大模型、高batch size的測試。
3. 提供的demo也足夠簡單,修改起來難度很低。
不足:
1. Paddle-Mobile相關文檔具有一定門檻,且較為分散。初次使用的時候會走一些彎路出現問題的時候往往是個
黑盒,不易于定位。在這次進行模型訓練的嘗試中,出現過一次op不支持的情況,我們在官網上甚至沒有找
到支持的op列表,這個在開發哥們的支持下升級版本后解決。如果后續能在穩定的固件版本下使用,并有比
較易用的sdk,開發門檻可能會進一步降低。