梳理TensorFlow模型在Jetson TX2上进行inference的主要流程

内容概述

本文档主要内容:梳理TensorFlow模型在Jetson TX2进行inference的主要流程涉及相关软件的安装依赖库的编译配置以及PC的深度网络模型在Jetson TX2的移植步骤。

开发环境

注意PC和Jetson TX2所使用TensorRT安装包是不一样的前者使用的Tesla GPUs版本而后者使用的是Jetson Platforms版本

2.1 PC

1) PycharmPython程序的开发环境

2) Python 3.5

3) TensorFlow:数值计算的开源软件库,主要用于深度学习模型的搭建

4) TensorRT Python API:在PC使用TensorRT所需Python库,以whl文件形式存在,存放在TensorRT安装包python目录下;

5) UFF Python API:转换uff文件的Python库,存放在TensorRT安装包uff目录下。

2.2 Jetson TX2端

1) TensorRT 3.0NVIDIA提供API包括c++ API和Python API,用于加速基于NVIDIA gpu硬件平台的深度网络模型inference程序,目前主要支持caffeTensorFlow模型的转换

2) CUDA 8.0cuDNN 7.0;

3) OpenCV 3.3:图像处理开源库,在Jetson TX2平台上需使用cmake方式进行编译安装;

深度网络模型移植

本文移植主要针对利用TensorFlow搭建的网络模型下面用图例简单介绍深度网络模型traininginference的整个流程图中NVIDIA DIGITS为NVIDIA开发的方便模型训练的web应用

PC训练模型到TX2进行inference,主要有三个步骤

1) 训练模型并保存为pb文件

2) Pb文件转uff文件

3) 利用TensorRT加载并运行模型

前两个步骤是在PC执行,最后一个步骤是在Jetson TX2上进行本教程引用了TensorRT-3-User-Guide.pdf文档中的部分内容

3.1 训练模型保存为pb文件PC端)

Pb文件包含网络结构和模型参数,TensorFlow训练得到的模型保存为pb的方法参考网址

保存pb文件最核心的代码是:

constant_graph = graph_util.convert_variables_to_constants(sess, sess.graph_def, ["output"])

with tf.gfile.FastGFile(pb_file_path, mode='wb') as f:

f.write(constant_graph.SerializeToString())

3.2 pb文件uff文件PC端)

为了将生成的pb格式的模型文件转为TensorRT 3.0可以解析uff文件,需在命令行执行以下命令

convert-to-uff tensorflow -o name_of_output_uff_file --input_file  name_of_input_pb_file  -O  name_of_output_tensor

加粗部分是需要更改name_of_output_uff_file是即将输出的uff文件名字

name_of_input_pb_file输入的pb模型文件名字,name_of_output_tensorpb模型图输出的节点名字

可通过以下命令得到网络各个节点的名称:

convert-to-uff tensorflow --input_file name_of_input_pb_file –l

pb文件转换至uff文件时,必须指定输出节点名称。

3.3 加载并运行模型(Jetson端)

在运用TensorRT进行inference主要包括两个阶段:build构建网络)deployment运行,编程语言c++,技术文档请参考doc路径下TensorRT-3-User-Guide.pdf章节3.3 SampleUffMNIST UFF Usage。示例程序请参考sample/ sampleUffMNIST路径下的程序文件sampleUffMNIST.cpp

3.3.1 构建阶段(build

1) 创建builder

// 创建network解析变量parser

auto parser = createUffParser();     

// 为parser指定网络模型的输入和输出

parser->registerInput("Input_0", DimsCHW(1, 28, 28));     

parser->registerOutput("Binary_3");

// 创建builder变量

IBuilder* builder = createInferBuilder(gLogger);

INetworkDefinition* network = builder->createNetwork();

2) 解析uff modelnetwork

parser->parse(uffFile, *network, nvinfer1::DataType::kFLOAT);

uffFile是uff文件的路径

3) 创建engine

builder->setMaxBatchSize(maxBatchSize);     // 设置输入数据的batch

builder->setMaxWorkspaceSize(MAX_WORKSPACE);  

// 设置engine运行时空间(即内存)大小这里MAX_WORKSPACE可设置为1<<30

ICudaEngine* engine = builder->buildCudaEngine(*network);  // engine返回值

3.3.2 执行阶段deployment

1) 创建execution context

IExecutionContext* context = engine.createExecutionContext();

2) 获取enginebinding个数以及索引

int nbBindings = engine.getNbBindings();

3) 计算输入、输出节点维度大小和数据类型

auto buffersSizes = calculateBindingBufferSizes(engine, nbBindings, batchSize);

4) 为输入输出节点分配CUDA内存

参考sampleUffMNIST.cpp中的safeCudaMalloc函数,得到buffers数组包括输入节点和输出节点的内存

5) 将输入数据导入输入节点的内存中

参考createMnistCudaBuffer()函数,可根据需要进行改写;

6) 执行inference

context->execute(batchSize, buffers);  // buffers为存储输入输出节点内存的数组;

7) 输出结果

根据上一步得到输出节点数据,即buffers[1],一般为分类结果,或者语义分割的输出数据。根据需要,进行后续处理。

猜你喜欢

转载自blog.csdn.net/scutjy2015/article/details/78662057