摘要:前言 在上一周的测试中,我们按照官方给的流程,使用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张作为验证集。
!mkdir ‐p /home/aistudio/.cache/paddle/dataset/cifar # wget将下载的文件存放到指定的文件夹下,同时重命名下载的文件,利用‐o !wget http://ai‐atest.bj.bcebos.com/cifar‐10‐python.tar.gz ‐o cifar‐10‐python.tar.gz !mv cifar‐10‐python.tar.gz /home/aistudio/.cache/paddle/dataset/cifar/模型结构
我们选择了以三个卷积层串联一个全连接层的输出,作为猫狗分类的预测,采用固定维度输入,输出为分类数
def convolutional_neural_network(img): # 第一个卷积‐池化层 conv_pool_1 = fluid.nets.simple_img_conv_pool( input=img, # 输入图像 filter_size=5, # 滤波器的大小 num_filters=20, # filter 的数量。它与输出的通道相同 pool_size=2, # 池化层大小2*2 pool_stride=2, # 池化层步长 act=relu) # 激活类型 # 第二个卷积‐池化层 conv_pool_2 = fluid.nets.simple_img_conv_pool( input=conv_pool_1, filter_size=5, num_filters=50, pool_size=2, pool_stride=2, act=relu) # 第三个卷积‐池化层 conv_pool_3 = fluid.nets.simple_img_conv_pool( input=conv_pool_2, filter_size=5, num_filters=50, pool_size=2, pool_stride=2, act=relu) # 以softmax为激活函数的全连接输出层,10类数据输出10个数字 prediction = fluid.layers.fc(input=conv_pool_3, size=10, act='softmax') return prediction训练&验证
接下来在paddlepaddle fluid上,进行训练。整个训练代码见附件train.py 模型验证,采用附件predict.py的代码进
行验证与运行时间的测量,选取一张狗的图:dog.jpg (可以fork首页链接aistudio平台上的demo) 连续预测10000
次,输出如下:
cpu 运行结果为:预处理时间为0.0006270000000085929,预测时间为:16.246494 out: im_shape的维度: (1, 3, 32, 32) the run time of image process is 0.0006270000000085929 the run time of predict is 16.246494 results [array([[5.0159363e‐04, 3.5942634e‐05, 2.5955746e‐02, 4.7745958e‐02, 9.9251214e‐03, 9.0146154e‐01, 1.9564393e‐03, 1.2230080e‐02, 4.7619540e‐08, 1.8753216e‐04]], dtype=float32)] infer results: doggpu v100 运行结果为:预处理时间为0.0006390000000067175,预测时间为:15.903074000000018 out: im_shape的维度: (1, 3, 32, 32) the run time of image process is 0.0006390000000067175 the run time of predict is 15.903074000000018 results [array([[5.0159392e‐04, 3.5942641e‐05, 2.5955772e‐02, 4.7746032e‐02, 9.9251205e‐03, 9.0146142e‐01, 1.9564414e‐03, 1.2230078e‐02, 4.7619821e‐08, 1.8753250e‐04]], dtype=float32)] infer results: dog可以看到,模型可以正确的识别出图片中的动物为狗,接下来,我们就要尝试将这个模型部署到edgeboard上面。
模型导出
我们需要将模型保存为模型文件model以及权重文件params,可以采用如下paddle的api进行保存如图所示,在aistudio的左侧打开模型文件所在的文件夹,下载mlp-model、mlp-params两个文件。
在edgeboard上部署模型,完成预测
1、新建工程文件夹,目录结构如下(可以仿照sample里的resnet、inception例程):
‐sample_image_catdog ‐build ‐image ‐include ‐paddlepaddle‐mobile ‐... ‐lib ‐libpaddle‐mobile.so ‐model ‐mlp ‐model ‐params ‐src ‐fpga_cv.cpp ‐main.cpp2、将aistudio上导出来的模型放置在model里的mlp文件夹,修改名字为model、params
3、新建 cmakelists.txt
cmake_minimum_required(version 3.5.1) project(paddle_edgeboard) set(cmake_cxx_standard 14) set(cmake_exe_linker_flags ${cmake_exe_linker_flags} ‐pthread) add_definitions(‐dpaddle_mobile_fpga_v1) add_definitions(‐dpaddle_mobile_fpga) set(paddle_lib_dir ${project_source_dir}/lib ) set(easydl_include_dir ${project_source_dir}/include ) set(paddle_include_dir ${project_source_dir}/include/paddle‐mobile ) set(app_name paddle_edgeboard ) aux_source_directory(${cmake_current_source_dir}/src src) find_package(opencv quiet components core videoio highgui imgproc imgcodecs ml video) include_directories(system ${opencv_include_dirs}) #list(append caffe_linker_libs ${opencv_libs}) message(status opencv found (${opencv_config_path}),${opencv_libs}) #add_definitions(‐duse_opencv) include_directories(${easydl_include_dir}) include_directories(${paddle_include_dir}) link_directories(${paddle_lib_dir}) add_executable(${app_name} ${src}) target_link_libraries(${app_name} paddle‐mobile) target_link_libraries(${app_name} ${opencv_libs} )4、main.cpp
#include #include io/paddle_inference_api.h #include math.h #include #include #include #include #include #include #include #include #include #include #include fpga/kd/float16.hpp #include fpga/kd/llapi/zynqmp_api.h using namespace paddle_mobile; #include #include using namespace cv; cv::mat sample_float; static std::vector label_list(10); void readimage(std::string filename, float* buffer) { mat img = imread(filename); if (img.empty()) { std::cerr << can't read image from the file: << filename << std::endl; exit(‐1); } mat img2; resize(img, img2, size(32,32)); img2.convertto(sample_float, cv_32fc3); int index = 0; for (int row = 0; row < sample_float.rows; ++row) { float* ptr = (float*)sample_float.ptr(row); for (int col = 0; col < sample_float.cols; col++) { float* uc_pixel = ptr; // uc_pixel[0] ‐= 102; // uc_pixel[1] ‐= 117; // uc_pixel[1] ‐= 124; float r = uc_pixel[0]; float g = uc_pixel[1]; float b = uc_pixel[2]; buffer[index] = b / 255.0; buffer[index + 1] = g / 255.0; buffer[index + 2] = r / 255.0; // sum += a + b + c; ptr += 3; // dlog << r: << r << g: << g << b: << b; index += 3; } } // return sample_float; } paddlemobileconfig getconfig() { paddlemobileconfig config; config.precision = paddlemobileconfig::fp32; config.device = paddlemobileconfig::kfpga; // config.model_dir = ../models/mobilenet/; config.prog_file = ../model/mlp/model; config.param_file = ../model/mlp/params; config.thread_num = 4; return config; } int main() { clock_t starttime,endtime; zynqmp::open_device(); std::cout << open_device success << std::endl; paddlemobileconfig config = getconfig(); std::cout << getconfig success << std::endl; auto predictor = createpaddlepredictor(config); std::cout << predictor success << std::endl; starttime = clock();//计时开始 float data[1 * 3 * 32 * 32] = {1.0f}; readimage(../image/cat.jpg, data); endtime = clock();//计时结束 std::cout << the run time of image process is: <<(double)(endtime ‐ starttime) / clocks_per_sec << s << std::endl; paddletensor tensor; tensor.shape = std::vector({1, 3, 32, 32}); tensor.data = paddlebuf(data, sizeof(data)); tensor.dtype = paddledtype::float32; std::vector paddle_tensor_feeds(1, tensor); paddletensor tensor_out; tensor_out.shape = std::vector({}); tensor_out.data = paddlebuf(); tensor_out.dtype = paddledtype::float32; std::vector outputs(1, tensor_out); std::cout << before predict
insmod /home/root/workspace/driver/fpgadrv.ko cd /home/root/workspace/sample/sample_image_catdog mkdir build cd build rm ‐rf * cmake .. make ./paddle_edgeboard修改main文件要预测的图像:
6、修改main文件后重复执行预测,可得结果如下:图像处理时间大概为:0.006秒,预测时间大概为:0.008秒
7、连续预测10000次所用时间为:23.7168
性能对比(连续预测10000次 单位:秒)
平台 前处理耗时 模型预测耗时
edgeboard 0.006 23.7168
cpu(aistudio平台双核8g) 0.000627 16.2464
gpu(aistudio平台双核8g+gpu v100 16gb) 0.000639 15.9030
总结
优点:
1. edgeboard内置的paddle-mobile,可以与paddle训练出来的模型进行较好的对接。
2. 预测速度上: edge在预测小模型的时候,能与双核cpu和gpu在一个数量级,估计是模型较小,batch size也
为1,gpu,cpu的性能优势抵不过通信的开销,后续将进行大模型、高batch size的测试。
3. 提供的demo也足够简单,修改起来难度很低。
不足:
1. paddle-mobile相关文档具有一定门槛,且较为分散。初次使用的时候会走一些弯路出现问题的时候往往是个
黑盒,不易于定位。在这次进行模型训练的尝试中,出现过一次op不支持的情况,我们在官网上甚至没有找
到支持的op列表,这个在开发哥们的支持下升级版本后解决。如果后续能在稳定的固件版本下使用,并有比
较易用的sdk,开发门槛可能会进一步降低。
观展有奖 | 安森美将在机器视觉展(深圳)展示出类拔萃的图像感知方案
OTA更新的车载网络要求
谷歌正在将新的表情符号与 Android 系统更新分离
舍弗勒将收购价格提高到38亿欧元,纬湃科技认为依然不够
苹果再遇危机,Phone销量明显下滑,将会是严重的打击
Edgeboard试用—基于CIFAR10分类模型的移植
赛思x上海联通:解决IDC机房高精度对时需求问题,用赛思5G通信设备
基于STC89C52单片机的温湿度远程监控系统设计
助听器百科知识
国产CPU不能跟随其他人的步伐,自主才是硬道理!
华为(烟台)人工智能创新中心启动
温州将深入实施数字经济“一号工程”,全力培育发展战略性新兴产业
IR推出高效可靠的超高速1200V IGBT
使用DMZ1520E直接给MCU供电的方案
复杂音乐版权的问题可以利用区块链解决吗
嵌入式汽车发动机检测装置设计
冰屏将会成为LED透明显示屏厂家抢占市场的利器
NI宣布推出ActiveUptime一款服务型维护解决方案
找方案 | 基于DIODES AP33772的USB PD Sink Controller之无线电动工具方案
CRT显示器高压包引脚功能定义及参数介绍