Edgeboard试用 — 基于CIFAR10分类模型的移植
前言
在上一次的测试中,我们按照官方给的流程,使用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: dog
GPU 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进行保存
fluid.io.save_inference_model(model_save_dir,['images'],[predict], exe,params_filename="mlp" + '-params',model_filename="mlp" + '-model',)
如图所示,在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.cpp
2、将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 " << std::endl; predictor->Run(paddle_tensor_feeds, &outputs); std::cout << " after predict " << std::endl;
// assert(); endTime = clock();//计时结束
std::cout << "The run time of predict is: " <<(double)(endTime - startTime) / CLOCKS_PER_SEC << "s" << std::endl; float* data_o = static_cast(outputs[0].data.data());
for (size_t j = 0; j < outputs[0].data.length() / sizeof(float); ++j) {
std::cout << "output[" << j << "]: " << data_o[j] << std::endl;
} int index = 0;
float max = 0.0;
for (int i = 0;i < 10; i++) {
float val = data_o[i];
if (val > max) {
max = val > max ? val : max;
index = i;
}
} label_list = {"airplane", "automobile", "bird", "cat", "deer", "dog", "frog", "horse",
"ship", "truck" };
std::cout << "Result" << " is " << label_list[index] << std::endl; return 0;
}
5、编译运行
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秒
总结
优点:
1、EdgeBoard内置的Paddle-Mobile,可以与Paddle训练出来的模型进行较好的对接。
2、预测速度上: Edge在预测小模型的时候,能与双核CPU和GPU在一个数量级,估计是模型较小,batch size也为1,gpu,cpu的性能优势抵不过通信的开销,后续将进行大模型、高batch size的测试。
3、提供的demo也足够简单,修改起来难度很低。
不足:
Paddle-Mobile相关文档具有一定门槛,且较为分散。初次使用的时候会走一些弯路出现问题的时候往往是个黑盒,不易于定位。在这次进行模型训练的尝试中,出现过一次op不支持的情况,我们在官网上甚至没有找到支持的op列表,这个在开发哥们的支持下升级版本后解决。如果后续能在稳定的固件版本下使用,并有比较易用的sdk,开发门槛可能会进一步降低。
作者:Litchll
Edgeboard试用 — 基于CIFAR10分类模型的移植的更多相关文章
- 基于Distiller的模型压缩工具简介
Reference: https://github.com/NervanaSystems/distiller https://nervanasystems.github.io/distiller/in ...
- 笔记︱风控分类模型种类(决策、排序)比较与模型评估体系(ROC/gini/KS/lift)
每每以为攀得众山小,可.每每又切实来到起点,大牛们,缓缓脚步来俺笔记葩分享一下吧,please~ --------------------------- 本笔记源于CDA-DSC课程,由常国珍老师主讲 ...
- 【AUC】二分类模型的评价指标ROC Curve
AUC是指:从一堆样本中随机抽一个,抽到正样本的概率比抽到负样本的概率大的可能性! AUC是一个模型评价指标,只能用于二分类模型的评价,对于二分类模型,还有很多其他评价指标,比如logloss,acc ...
- NLP学习(2)----文本分类模型
实战:https://github.com/jiangxinyang227/NLP-Project 一.简介: 1.传统的文本分类方法:[人工特征工程+浅层分类模型] (1)文本预处理: ①(中文) ...
- 风控分类模型种类(决策、排序)比较与模型评估体系(ROC/gini/KS/lift)
python信用评分卡建模(附代码,博主录制) https://study.163.com/course/introduction.htm?courseId=1005214003&utm_ca ...
- 使用Keras基于RCNN类模型的卫星/遥感地图图像语义分割
遥感数据集 1. UC Merced Land-Use Data Set 图像像素大小为256*256,总包含21类场景图像,每一类有100张,共2100张. http://weegee.vision ...
- 【tornado】系列项目(二)基于领域驱动模型的区域后台管理+前端easyui实现
本项目是一个系列项目,最终的目的是开发出一个类似京东商城的网站.本文主要介绍后台管理中的区域管理,以及前端基于easyui插件的使用.本次增删改查因数据量少,因此采用模态对话框方式进行,关于数据量大采 ...
- 【tornado】系列项目(一)之基于领域驱动模型架构设计的京东用户管理后台
本博文将一步步揭秘京东等大型网站的领域驱动模型,致力于让读者完全掌握这种网络架构中的“高富帅”. 一.预备知识: 1.接口: python中并没有类似java等其它语言中的接口类型,但是python中 ...
- DL4NLP——词表示模型(二)基于神经网络的模型:NPLM;word2vec(CBOW/Skip-gram)
本文简述了以下内容: 神经概率语言模型NPLM,训练语言模型并同时得到词表示 word2vec:CBOW / Skip-gram,直接以得到词表示为目标的模型 (一)原始CBOW(Continuous ...
随机推荐
- Linux编译安装Qt 5.4.1(-qt-xcb是必须要指定的,卸载自带的gcc等)
转载请注明文章:Linux编译安装Qt 5.4.1 出处:多客博图 很久不写文章了,过程很简单,但是操作很多,简单说吧. 前言: 操作系统CentOS 6.6,64位的. 1.安装gcc 4.8.4, ...
- Oracle报错:不是GROUP BY 表达式
报错:不是GROUP BY 表达式 实例:select sum(hwjz),rq from JcChargeInfo where 1=1 group by rq order by jcchargec ...
- SFC游戏列表(维基百科)
SFC游戏列表 日文名 中文译名 英文版名 发行日期 发行商 スーパーマリオワールド 超级马里奥世界 Super Mario World 1990年11月21日 任天堂 エフゼロ F-Zero F-Z ...
- 升级d7的代码到2010以上版本注意事项(SetLength的参数就是字符长度,而不是字节长度,但Move函数要改)
delphi2010是delphi所有版本的分水岭,其中2010—xe10.2之间版本上的代码都有比较好的兼容性,基本上都能直接进行编译,不需要过多修改,但d7距d2010跨度4个版本以上,新版本除了 ...
- 使用百度网盘+Git,把版本控制托管到云端,附精彩评论
http://www.cnblogs.com/vajoy/p/3929675.html 我试过多个这种双向同步的网盘,在网络状况不好.系统卡顿以及某些程序BUG的情况下,同步会有错乱现象,尤其是多个电 ...
- 我们检测到您的浏览器不兼容传输层安全协议 (TLS) 1.1 或更高版本,此协议在 Internet 上用于确保您通信的安全性。
早上使用.Net WebClient类采集亚马逊数据,返回http 400 Bad Request错误,内容里面有“我们检测到您的浏览器不兼容传输层安全协议 (TLS) 1.1 或更高版本,此协议在 ...
- 梭子鱼VS多备份 虽殊途却同归
备份,对于企业来说,不仅是一个已经拥有多年历史的传统IT工作,还关系着企业自身的生死存亡.在云计算时代下,备份业务成为企业的必选项,已经成为云计算服务最为热门的领域之一.基于云的备份正在深刻改变着备份 ...
- 设置windows服务依赖项
场景还原:python2.7开发的项目,制作成了windows服务,随系统启动.系统重启后发现服务未能自动启动,检查事件查看器日志发现服务先于Mysql数据库服务启动,由于服务中必须对MySQL进行访 ...
- 布隆过滤器 - 如何在100个亿URL中快速判断某URL是否存在?
题目描述 一个网站有 100 亿 url 存在一个黑名单中,每条 url 平均 64 字节.这个黑名单要怎么存?若此时随便输入一个 url,你如何快速判断该 url 是否在这个黑名单中? 题目解析 这 ...
- 【JVM】02垃圾回收机制
垃圾回收 垃圾回收策略https://blog.csdn.net/u010425776/article/details/51189318 程序计数器.Java虚拟机栈.本地方法栈都是线程私有的,也就是 ...