从Keras模型转换成tensorrt的方法

1 流程
对于目前找到的最有效的方式是将Keras模型保存为savedmodel格式,也就是说一个只含有计算图的.pb,一个variables文件和一个json合并的一个文件夹。tf-trt加速的话会还给你一个优化过后的.pb和variable,并不是我们希望使用的engine形式。
最稳妥的流程为:savedmodel–>onnx–>engine
下载tf2onnx,使用如下命令:
python3 -m tf2onnx.convert --saved-model /lsj/checkpoint_germany_savedmodel/ --opset 7 --inputs input_1:0[1,224,224,3] --output /lsj/germany_model.onnx
具体参数GitHub有说明。
注意:一定要在root目录下运行此命令,否则会报错关于__path__。
最后使用onnx-trt工具,命令如下:
onnx2trt /lsj/germany_model.onnx -o /lsj/germany.engine
即可成功生成engine
2环境
TensorFlow 1.14.0
CUDA 10.0
TensorRT 7.0.0.11
cmake 3.18.2
protobuf 3.12.2
pycuda 2019.1.2
onnx 1.6.0
tf2onnx 1.6.1
编译安装这些包时会碰到一些坑,没有整理,解决了就不记得了。
下载tar.gz的tensorrt解压安装,onnx2trt需要Git clone下来切换分支后,编译安装,建议使用github.com.cnpmjs.org镜像clone,会快一点,最后将路径写入系统环境变量,保存在/etc/bashrc,source一下生效即可。
3踩坑
savedmodel在tf1.x的Keras是被弃用的,无法使用model.save里的参数save format="tf’来解决,必须使用如下函数保存,缺点就是没法使用Keras的checkpoint callback进行监测"val loss"或者其他的指标对模型进行选择性保存,而是在训练完成后保存,同时也不会保存optimizer的状态,建议使用tf.train的optimizer,但我认为问题应该不大:
从Keras模型转换成tensorrt的方法

开始将.h5转为有图有变量的pb,然后使用tf工具将pb转uff,在经过使用trt官方文档里代码得到疯狂折磨人的bug报错:elementwise inputs must have same dimensions or follow broadcast rules (input dimensions were [112,112,32] and [32,1,1])后,本来我以为是版本问题,把我元素相乘自动转置了,结果改模型,换版本都不行,把trt从5.1.5一直换到7.1.3,CUDA10.0,10.1,10.2都用了,无法解决问题,于是尝试寻找新的解决方案。尝试了Keras2onnx工具,仍无法正常转换engine。使用onnx-trt工具将onnx转换为engine时,报错:

从Keras模型转换成tensorrt的方法
这个dynamic shape在trt6.0以后支持,意思就是在训练时模型有些不确定维度,onnx parser无法解析,经查阅各种资料,尝试结合使用GitHub及帮助文档的说法,编写如下代码:
从Keras模型转换成tensorrt的方法
其中官方给出建议尝试加入的explicit和config没用,还是会报错:Segmentation fault (core dumped),最后通过查阅源代码得知tensorrt支持的opset应设为7,同时,将tf2onnx工具 的–input参数的batchsize设为固定的1即可。出现这种错误主要是因为输入tensor的batch维度是runtime指定的,模型无法进行trt优化。
4结尾
目前看暂时解决了这个问题,下一步进行C++调用的时候若有问题会同步记录在此贴。