当前位置:   article > 正文

AI算法模型之应用部署概述_算法硬件部署

算法硬件部署

模型部署框架类型

算法模型的部署主要可以分成两个方面。一是在移动端/边缘端的部署,即嵌入式,通常以SDK形式呈现。另一个是云端/服务端,通常以服务的形式呈现;今天着重聊聊部署流程,后续移动端部署、具体厂商的智能硬件部署、云端server会开专题介绍。

边缘端

模型训练:通过pytorch、tensorflow等深度学习框架进行训练算法模型,得到模型权重文件,模型训练部分今天不着重介绍,后续专题会展开讨论训练tricks、模型调优、模型剪枝、蒸馏、量化。

模型转化:把权重文件转为对应智能硬件的形态,方便利用对应的GPU、NPU或者IPU智能硬件加速单元来达到加速效果。

算法部署:依照原模型算法推理逻辑对应实现在嵌入式端。

模型转化

包括英伟达、⾼通、华为、AMD在内的⼚家,都在神经⽹络加速⽅⾯投⼊了研发⼒量。通过量化、裁剪和压缩来降低模型尺⼨。更快的推断可以通过在降低精度的前提下使⽤⾼效计算平台⽽达到,其中包括intel MKL-DNN,ARM CMSIS,Qualcomm SNPE,Nvidia TensorRT,海思、RockChip RKNN,SigmarStar SGS_IPU等。

依TensorRT为例,其他平台的部署系列后面会出详细手把手教程。

TensorRT

方式一:把训练得到的权重文件如(pt,pb)先转化为Onnx形式,使用onnx-simplifier对模型进行图优化,得到一个简洁明了的模型图,最后通过trtexec转为对应的engine文件。

以Yolov5为例,导出onnx代码

  1. # YOLOv5 ONNX export
  2. try:
  3. check_requirements(('onnx',))
  4. import onnx
  5. LOGGER.info(f'\n{prefix} starting export with onnx {onnx.__version__}...')
  6. f = file.with_suffix('.onnx')
  7. torch.onnx.export(model, im, f, verbose=False, opset_version=opset,
  8. training=torch.onnx.TrainingMode.TRAINING if train else torch.onnx.TrainingMode.EVAL,
  9. do_constant_folding=not train,
  10. input_names=['images'],
  11. output_names=['output'],
  12. dynamic_axes={'images': {0: 'batch', 2: 'height', 3: 'width'}, # shape(1,3,640,640)
  13. 'output': {0: 'batch', 1: 'anchors'} # shape(1,25200,85)
  14. } if dynamic else None)
  15. # Checks
  16. model_onnx = onnx.load(f) # load onnx model
  17. onnx.checker.check_model(model_onnx) # check onnx model
  18. # LOGGER.info(onnx.helper.printable_graph(model_onnx.graph)) # print
  19. # Simplify
  20. if simplify:
  21. try:
  22. check_requirements(('onnx-simplifier',))
  23. import onnxsim
  24. LOGGER.info(f'{prefix} simplifying with onnx-simplifier {onnxsim.__version__}...')
  25. model_onnx, check = onnxsim.simplify(
  26. model_onnx,
  27. dynamic_input_shape=dynamic,
  28. input_shapes={'images': list(im.shape)} if dynamic else None)
  29. assert check, 'assert check failed'
  30. onnx.save(model_onnx, f)
  31. except Exception as e:
  32. LOGGER.info(f'{prefix} simplifier failure: {e}')
  33. LOGGER.info(f'{prefix} export success, saved as {f} ({file_size(f):.1f} MB)')
  34. return f
  35. except Exception as e:
  36. LOGGER.info(f'{prefix} export failure: {e}')

导出后的Onnx模型图

编辑切换为居中

Yolov5-Onnx-结构图

然后执行

trtexec --onnx=weights/yolov5s.onnx --saveEngine=weights/yolov5s.engine

对于YOLOV5,官方已经提供了一键转各种格式的脚本,具体参考

在此仅提供模型转化的方法思路。

方式二:根据TensorRT官方API文档,手动搭建模型结构,最后根据API接口把模型转成engine文件。

同样的依照Yolov5为例:

提取模型权重

  1. import sys
  2. import argparse
  3. import os
  4. import struct
  5. import torch
  6. from utils.torch_utils import select_device
  7. def parse_args():
  8. parser = argparse.ArgumentParser(description='Convert .pt file to .wts')
  9. parser.add_argument('-w', '--weights', required=True,
  10. help='Input weights (.pt) file path (required)')
  11. parser.add_argument(
  12. '-o', '--output', help='Output (.wts) file path (optional)')
  13. parser.add_argument(
  14. '-t', '--type', type=str, default='detect', choices=['detect', 'cls', 'seg'],
  15. help='determines the model is detection/classification')
  16. args = parser.parse_args()
  17. if not os.path.isfile(args.weights):
  18. raise SystemExit('Invalid input file')
  19. if not args.output:
  20. args.output = os.path.splitext(args.weights)[0] + '.wts'
  21. elif os.path.isdir(args.output):
  22. args.output = os.path.join(
  23. args.output,
  24. os.path.splitext(os.path.basename(args.weights))[0] + '.wts')
  25. return args.weights, args.output, args.type
  26. pt_file, wts_file, m_type = parse_args()
  27. print(f'Generating .wts for {m_type} model')
  28. # Load model
  29. print(f'Loading {pt_file}')
  30. device = select_device('cpu')
  31. model = torch.load(pt_file, map_location=device) # Load FP32 weights
  32. model = model['ema' if model.get('ema') else 'model'].float()
  33. if m_type in ['detect', 'seg']:
  34. # update anchor_grid info
  35. anchor_grid = model.model[-1].anchors * model.model[-1].stride[..., None, None]
  36. # model.model[-1].anchor_grid = anchor_grid
  37. delattr(model.model[-1], 'anchor_grid') # model.model[-1] is detect layer
  38. # The parameters are saved in the OrderDict through the "register_buffer" method, and then saved to the weight.
  39. model.model[-1].register_buffer("anchor_grid", anchor_grid)
  40. model.model[-1].register_buffer("strides", model.model[-1].stride)
  41. model.to(device).eval()
  42. print(f'Writing into {wts_file}')
  43. with open(wts_file, 'w') as f:
  44. f.write('{}\n'.format(len(model.state_dict().keys())))
  45. for k, v in model.state_dict().items():
  46. vr = v.reshape(-1).cpu().numpy()
  47. f.write('{} {} '.format(k, len(vr)))
  48. for vv in vr:
  49. f.write(' ')
  50. f.write(struct.pack('>f', float(vv)).hex())
  51. f.write('\n')

根据API接口构建编译Yolov5模型结构

核心代码块

具体参照tensorrtx

方式三:跟方式一一样先转成onnx图模型,根据TensorRT-onnx_parser模型转成engine文件。

核心代码块

具体参照tensort_pro

至此模型转化这部分完成。

三种方式的优缺点:

方式一、方式三相对于方式二更为简单方便快捷,特别方式一零代码即可实现模型的转化,反观方式二需要清晰模型结构,清晰API接口算子并手撸代码完成构建engine。但方式一、方式三对于一些模型如transform、Vit模型由于一些算子还未支持,故不能一键转化,而方式二则可完成,总体来说方式二相比其他更为灵活,但上手难度更大。

算法部署

整体流程

编辑切换为居中

流程图

输入:着重说下视频流如rtsp、webrtc、rtmp这种实时视频流,我们需要先对流进行解码从而得到RGB图像(YUV420、NV12、NV21 -> RGB),其中解码又分为软解码和硬解码,软解码如libx264,libx265等,硬解码如Nvidia的CUVID以及海思,RockChip的Mpp等,关于视频流的编解码后续会开专题详细介绍。

预处理:把得到的RGB图像依照跟训练时进行同样的预处理,如Yolov5需要自适应缩放、归一化操作;人脸检测scrfd需要自适应缩放、减均值127.5,除方差128等操作;对于自适应缩放可以采用仿射变换、letterbox的形式实现;对于减均值、除方差,NVIDIA可以采用CUDA进行操作,从而达到提速的效果。

模型推理:把经过上边两步的图像data送进序列化好的engine进行model_forward,得到output_tensor。

后处理:把上述得到的output_tensor,进行后处理decode,依照目标检测为例这个操作一般为general_anchor、nms、iou,坐标映射到原图(transform_pred)等操作;分类模型则一般为get_max_pred;姿态识别模型一般为keypoints_from_heatmap、transform_pred等。

输出:经过后处理后,就得到了最终的输出结果,如检测项,分类类别,keypoints,人脸坐标等等,最终可根据实际场景进行告警推送等应用开发,或者把告警图片进行编码(RGB->YUV420)以视频流的方式推送到流媒体服务器。

生成SDK

对于Hisi3516、3519或者rv1126、rv1109这类平台,flash空间小,需要交叉编译,可打包成动态链接库,提供接口函数供上层应用调用;对于rv3399、rk3568、jetson产品自带Ubuntu或者Linaro系统,可终端机自行编译,并且可部署python,可利用pybind11进行衔接交互。

云服务端

关于模型的云端部署,业界也有许多开源的解决方案,但目前为止来看,还没有一种真的可以一统业界,或者说称得上是绝对主流的方案。

针对云端部署的框架里,我们可以大致分为两类,一种是主要着力于解决推理性能,提高推理速度的框架,这一类里有诸如tensorflow的tensorflow serving、NVIDIA基于他们tensorRt的Triton(原TensorRt Serving),onnx-runtime,国内的paddle servering等, 将模型转化为某一特定形式(转化的过程中可能伴有一些优化的操作), 并对外提供服务,以此来获得相对较高的性能。

另一类框架主要着眼于结合模型整个生命周期,对模型部署进行管理,比如mlflow、seldon、bentoml、cortex等等,这些框架的设计与思路其实五花八门,有的为了和训练部分接轨,把模型文件管理也纳入了。有的则是只管到容器编排的部分,用户需要自己做好容器,它帮你发到k8s上之类的(这种情况甚至能和第一类框架连起来用)。当然也有专注于模型推理这一小块的。

写在最后

算法应用落地部署已然成为AI领域关键的一环,由于国外产品制裁,我们也大力支持国产智能硬件AI落地,已在海思、瑞芯微、sigmastar、寒武纪、地平线等国产芯片部署多款算法,如目标检测(YOLOV5等)、人脸识别(scrfd+arcface等)、姿势识别(lite-hrnet等)、动作序列识别(tsm等),目标追踪(MOT,bytetrack),拥有多行业、多领域真实数据集,并形成多款AI智能产品,落地应用在安防、加油站、充电桩、火车站、商场等各大行业,后续也会开设专题介绍各大智能硬件、各大算法的详细部署流程,致力于发展壮大国产AI部署社区生态。

今天就先到这里,谢谢,点点关注不迷路。

编辑切换为全宽

智驱力

智驱力-科技驱动生产力

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/weixin_40725706/article/detail/126623
推荐阅读
相关标签
  

闽ICP备14008679号