本文原作者:孟朋,经授权后发布。
随着深度学习的应用场景不断拓展,应用规模的不断扩大,模型推理服务的性能也受到越来越多重视。同样一个模型在同样的硬件上,专业的模型优化在同样的推理精度下可能会带来几倍甚至几十倍的性能提升。一般来说,使用专用推理框架比如TensorRT、OpenVINO等,推理性能会好于Tensorflow,Pytorch等深度学习框架,对模型的定制优化推理性能会好于直接使用专用推理框架。
对多数模型推理服务的使用者来说,首选方案是使用TensorRT、OpenVINO等专用推理框架对模型推理性能进行优化。 但新的算子、新的模型结构层出不穷,专用推理框架的更新远远跟不上模型的更新速度。很多模型,特别是较新的模型专用推理框架无法支持。针对这种情况,Tensorflow设计了TF-TRT模块,可以自动提取TF graph的子图,转换成TensorRT算子,对于TensorRT不支持的算子,继续在TF运行。通过这种方式,TensorRT大大扩展了可以加速优化的Tensorflow模型。
本文介绍的Caffe2/TRT模块,功能类似TF-TRT。Caffe2/TRT自动提取Caffe2网络子图,将子图转换为TensorRT算子。对于TensorRT不支持的算子,继续使用Caffe2算子。
本文的案例来源于某业务的Cascade R-CNN + FPN模型,我们做了两方面的工作使推理性能提升了1.6倍:
- 模型层面的优化,使Caffe2/TRT可以优化更多的子图,提升加速效果。
- Caffe2/TRT本身的优化,使其支持动态尺寸输入。同时也在图优化层,和更多TRT算子支持方面做了大幅度增强;使其在复杂模型优化能力有更多的提升,例如本文中的Cascade RCNN + FPN模型的推理。
本文会对Cascade R-CNN,FPN,以及我们的优化工作进行介绍。
Detectron是什么
Detectron是Facebook人工智能实验室于2018年1月开源的顶级物体检测研究框架。Detectron 项目的目的是在 Caffe2 的基础上建立一个快速、灵活的物体检测系统。Detectron框架集成了许多 Facebook 自己的研究项目以及主流的目标识别模型,包括Mask R-CNN,RetinaNet, Faster RCNN, RPN,FPN, R-FCN等10 多篇计算机视觉最新的成果。这些由 Detectron 支持的算法为实例分割之类的重要计算机视觉任务提供了直观的模型,也在视觉感知系统飞速发展中起到了重要作用。
除了Detectron自身实现的模型,也有很多团队基于Detectron框架扩展训练自定义模型(包括下文介绍的Cascade RCNN + FPN模型)。在 Detectron 中训练完毕的模型可以直接通过Caffe 2 运行时部署在云服务器和移动设备上【1】。目前Detetron在GitHub有22K+ Start, 5K+ fork。
FPN模型介绍
FPN(feature pyramid networks)是一种多尺度的object detection算法。原来多数的object detection算法都是只采用顶层特征做预测。但低层的特征语义信息比较少,目标位置准确,高层的特征语义信息比较丰富,目标位置比较粗略。FPN就是一种融合了底层和高层特征的目标识别模型。虽然也有些算法采用多尺度特征融合的方式,但一般是采用融合后的特征做预测,FPN不一样的地方在于预测是在不同特征层独立进行的。
用FPN方法构建的Faster R-CNN检测器的Faster R-CNN+FPN细节如图所示【3】:
Cascade R-CNN模型介绍
Cascade R-CNN算法是CVPR2018的文章,通过级联几个检测网络达到不断优化预测结果的目的,与普通级联不同的是,cascade R-CNN的几个检测网络是基于不同IOU阈值确定的正负样本上训练得到的,这是该算法的一大亮点。
对于两阶段目标识别算法,输入proposal的IOU阈值会大大影响模型性能。IOU阈值过小会使得正样本中有较多的背景,存在较多误检;IOU阈值过高,正样本的数量会较少,存在过拟合的风险。Cascade R-CNN在Faster RCNN基础上,扩展了多个检测网络,每个检测网络都基于不同IOU阈值的正负样本训练得到,前一个检测模型的输出作为后一个检测模型的输入,越往后的检测模型,其界定正负样本的IOU阈值是不断上升的【2】。
Cascade R-CNN + FPN模型结构分析
下图显示了Cascade R-CNN + FPN模型结构的目标识别部分,因为特征提取部分算子太多,这里省略了特征提取部分的Resnet101网络。这个网络结构比较复杂,而且使用了大量自定义算子。
Cascade R-CNN + FPN的特征提取网络是一个101层的Resnet网络网络,网络使用了AffineChannel代替了传统BN算子。之所以用AffineChannel代替BN,是因为Detectron网络一般BatchSize比较小,BN归一化容易带来训练的不稳定。下图显示了Resnet101网络的部分结构:
Pytorch/Caffe2为了支持Detectron网络实现了大量自定义OP。因此无法直接使用TensorRT进行推理加速。为了对Detectron网络进行推理加速,我们大幅优化了Caffe2/TRT。优化后的Caffe2/TRT可以支持类似Cascade RCNN + FPN这种复杂网络,并且可以支持输入的动态改变。
为了Caffe2/TRT可以更大限度提升模型推理性能,首先需要对模型本身做些优化。
Cascade RCNN模型优化
- 算子消除
上文介绍了Detectron特征提取Resnet网络使用了AffineChannel算子代替了传统BN算子,TensorRT并不支持AffineChannel算子,如果直接使用Caffe2/TRT对Detectron网络进行优化,结果如下:
可以看到,使用caffe2/TRT对模型进行优化后,TensorRT算子替换了caffe2模型部分算子。但因为TensorRT不支持AffineChannel算子,每个TensorRT算子只能替换相邻的支持的算子,因此每个TensorRT只能替换很小的子图。实际测试下来,caffe2/TRT优化后模型,并没有性能提升。
是否可以消除AffineChannel算子或替换为支持的算子,使得caffe2/TRT可以替换更大子图。答案是完全可以。
AffineChannel语义如下:OUTPUT = scale * INPUT + bias
根据AffineChannel语义,可以通过将AffineChannel前一层的Conv的weight除以scale,并且对Conv添加bias_add操作代替AffineChannel。
通过消除AffineChannel,整个Resnet101特征提取网络可以替换为一个TensorRT算子。
通过上图可以看出,通过消除AffineChannel算子,caffe2/TRT可以使用TensorRT算子优化整个Resnet101网络。
- 算子添加
模型优化不仅要消除算子,也要添加算子。比如下图:
上图是Cascade R-CNN网络一部分。TensorRT不支持BatchPermutation操作,但可以支持红框内所有算子。是否可以直接使用TensorRT优化红框内子图,答案是不可以。因为Caffe2/TRT首先将子图转成ONNX网络,然后使用TensorRT onnxparser将ONNX网络转为TensorRT engine。 TensorRT onnxparser不支持同一个输入在网络中输入多次,因此上图也是无法直接优化。
为了优化如上所示子图,可以通过添加Copy算子,将上图转为下图所示。
优化caffe2/TRT模块
上面介绍了模型方面优化。当前社区版Pytorch/Caffe2里面的TensorRT模块功能并不完善。无法支持Cascade RCNN + FPN这种类型的复杂网络。另外,也不支持输入的动态改变,FP16推理等。腾讯云AI基础产品中心对Caffe2/TRT模块做了大幅优化与增强,修改了子图匹配算法以及替换算法,完善了算子实现,增强了TensorRT算子实现,支持动态大小输入等。优化后的Caffe2/TRT模块可以支持Detectron框架各种算法。相关优化,会在深度学习框架加速Oteam开源。
经过框架和模型的优化,最终优化后的模型结构如图9所示。整个网络,除了自定义OP,所有子网络,被7个TensorRT算子替换。所有TensorRT算子,支持网络动态大小输入。优化后的网络,模型推理性能从4.6张图片/秒,提升到12张图片每秒。
总结
上面介绍了如何使用Caffe2/TRT加速Cascade R-CNN + FPN模型。通过模型和框架的优化,Cascade R-CNN + FPN模型的推理性能从4.6张图片/秒提升到12张图片/秒。推理性能是优化前的2.6倍。
我们会在下篇文章介绍如何实现FP16推理,如何实现图片输入大小可变,介绍FP16相比FP32推理精度差别,如何避免推理精度损失,以及模型如何上线等。