数据中心/云端

使用 NVIDIA Triton 推理服务器从公共库 ModelZoo 部署不同的 AI 模型类别

如今,针对 TensorFlow 、 ONNX 、 PyTorch 、 Keras 、 MXNet 等不同框架,出现了大量最先进( SOTA )模型和建模解决方案的实现。如果您对数据集中已有的类别感兴趣,可以使用这些模型进行开箱即用的推断,也可以通过微调将其嵌入到定制业务场景中。

本文概述了流行的 DL 模型类别,并介绍了使用 NVIDIA Triton Inference Server 部署这些模型的端到端示例。客户端应用程序可以按原样使用,也可以根据用例场景进行修改。我将带领您使用 Triton 推理服务器完成图像分类、对象检测和图像分割公共模型的部署。本文中概述的步骤也可以应用于其他开源模型,只需稍作修改。

深度学习推理挑战

近年来,深度学习( DL )取得了显著进步。通过解决多年来困扰人工智能界的众多复杂问题,它彻底改变了人工智能的未来。目前,它正被用于医疗保健、航空航天工程、自动驾驶和用户认证等不同行业的快速增长的应用。

然而,深度学习在推理方面面临各种挑战:

  • 支持多个框架
  • 易于使用
  • 部署成本

支持多个框架

第一个关键挑战是支持多种不同类型的模型框架。

今天,开发人员和数据科学家正在为他们的生产模型使用各种框架。例如,如果机器学习项目是用 Keras 编写的,那么修改系统进行测试和部署可能会遇到困难,但团队成员对 TensorFlow 有更多的经验。

此外,转换模型可能是昂贵和复杂的,特别是如果需要新的数据进行训练。他们必须有一个服务器应用程序来支持这些模型中的每一个。

易于使用

下一个关键挑战是要有一个能够支持不同推理查询和用例的服务应用程序。

在某些应用程序中,您专注于实时在线推理,其中的优先级是尽可能减少延迟。另一方面,可能有一些用例需要您进行离线批处理推断,因为您专注于最大化吞吐量。

必须有能够支持每种类型的查询和用例并为其进行优化的解决方案。

部署成本

下一个挑战是管理部署成本和降低推理成本。

其中的一个关键部分是有一个服务应用程序可以支持在混合基础架构上运行。您可以创建一个单独的服务解决方案,用于在 CPU 上运行,另一个用于 GPU ,另一种用于在数据中心和边缘的云上部署。这将导致成本飙升,并导致无法扩展的实现。

Triton 推理服务器

Triton 推理服务器是一个开源服务器推理应用程序,允许在不同环境中对 CPU 和 GPU 进行推理。它支持各种后端,包括 TensorRT 、 PyTorch 、 TensorFlow 、 ONNX 和 Python 。为了获得最大的硬件利用率, NVIDIA Triton 允许不同型号的并行执行。进一步的动态批处理允许将推理查询分组在一起,以最大化不同类型查询的吞吐量。有关详细信息,请参见 NVIDIA Triton Inference Server

The figure illustrates the Triton architecture. Triton allows High-performance inference and supports multiple frameworks enabling the teams to deploy the models on any GPU- or CPU-based infrastructure.
图 2. Triton 推理服务器架构

使用 NVIDIA Triton 快速启动

安装和运行 NVIDIA Triton 的最简单方法是使用 NGC 提供的预构建 Docker 映像。

服务器:拉取 Docker 镜像

使用以下命令拉动图像:

$ docker pull nvcr.io/nvidia/tritonserver:<xx.yy>-py3

NVIDIA Triton 通过使用 GPU 进行了优化,以提供最佳的推理性能,但它也可以在仅 CPU 的系统上工作。在这两种情况下,您都可以使用相同的 Docker 映像。

使用以下命令在您刚刚创建的示例模型存储库中运行 NVIDIA Triton :

docker run --gpus=1 --rm --net=host -v /path/to/the/repo/server/models:/models nvcr.io/nvidia/tritonserver:<xx.yy>-py3 tritonserver --model-repository=/models --exit-on-error=false --repository-poll-secs=10 --model-control-mode="poll"

客户端:获取客户端库

使用 docker pull 获取客户端库。

$ docker pull nvcr.io/nvidia/tritonserver:<xx.yy>-py3-sdk

在此命令中,<xx.yy>是要拉取的版本。运行客户端映像。

要启动客户端,请运行以下命令:

$ docker run -it --rm --net=host /path/to/the/repo/client/:/python_examples nvcr.io/nvidia/tritonserver:<xx.yy>-py3-sdk

端到端模型部署

NVIDIA Triton 项目提供了 C ++和 Python 中的几个客户端库,以简化通信。这些 API 使与 NVIDIA Triton 的通信变得容易。在这些 API 的帮助下,客户端应用程序处理输入并与 NVIDIA Triton 通信以执行推理。

The figure shows a generic workflow of a client application interaction with the Triton Inference Server. Inputs are read and preprocessed, serialized into a message, and sent to the Triton Server. The inference is performed on the Triton Inference Server, and the inferred data is sent back to the client, followed by post-processing. Depending upon the application, the output can be stored, displayed, or passed to the network.
图 3.客户端应用程序与 Triton 推理服务器交互的工作流

一般来说,客户端应用程序与 NVIDIA Triton 的交互可以总结如下:

  • 输入
  • 预处理
  • 推论
  • 后期处理
  • 输出

输入: 根据应用类型,读取一个或多个输入以由神经网络推断。

预处理 :预处理数据是深度学习工作流中常见的第一步,以网络可以接受的格式准备原始数据,例如,调整图像大小、标准化或从输入数据中去除噪声。

推理 :对于推理部分,客户端最初将推理请求序列化为消息,并将其发送到 Triton 推理服务器。消息通过网络从客户端传输到服务器,并被反序列化。请求被放置在队列中。请求将从队列中删除并计算。完成的请求在消息中序列化并发送回客户端。消息通过网络从服务器传输到客户端。消息到达客户端并被反序列化。

后处理: 当消息到达客户端应用程序时,它被处理为完成的推断请求。根据网络类型和应用程序用例,应用后处理。例如,在对象检测中,后处理包括抑制多余的框,帮助选择最佳可能的框,并将它们映射回输入图像。

输出: 在推断和处理之后,根据应用程序,输出可以被存储、显示或传递到网络。

图像分类

Image classification 是理解整个图像并为图像指定特定标签的任务。通常在图像分类中,图像中存在单个对象,并对其进行分析和理解。有关详细信息,请参见 image classification

服务器:下载模型

从 ONNX 模型动物园下载 ResNet-18 图像分类模型:

$ cd /path/to/the/repo/server/models/classification/1
$ wget https://github.com/onnx/models/raw/main/vision/classification/resnet/model/resnet18-v1-7.onnx && mv resnet18-v1-7.onnx model.onnx

以下代码示例显示了模型配置文件:

name: "classification"
platform: "onnxruntime_onnx"
max_batch_size : 1
input [
  {
    name: "data"
    data_type: TYPE_FP32
    format: FORMAT_NCHW
    dims: [ 3, 224, 224 ]
    reshape { shape: [ 3, 224, 224 ] }
  }
]
output [
  {
    name: "resnetv15_dense0_fwd"
    data_type: TYPE_FP32
    dims: [  1000 ]
    reshape { shape: [1000] }
    label_filename: "labels.txt"
  }
]

名称、平台和后端

name属性是可选的。如果未在配置中指定模型的名称,则假定该名称与包含该模型的模型存储库目录相同。该模型由 NVIDIA Triton 后端执行,它只是一个 DL 框架(如 TensorFlow 、 PyTorch 、 TensorRT 等)的包装器。有关更多信息,请参阅 backend

最大批量大小

模型可以支持的最大批处理大小由max_batch_size属性指示。零尺寸表示不支持洗澡。有关详细信息,请参见 batch size

输入和输出

对于每个模型,必须在 model configuration 文件中指定预期的输入、输出和数据类型。根据输入和输出张量,允许不同的数据类型。有关详细信息,请参见 Datatypes

图像分类模型接受单个输入,推理后返回单个输出。

在一个单独的控制台中,从 NGC NVIDIA Triton 容器中启动image_client示例。

客户端:运行图像分类客户端

要运行图像分类客户端,请使用以下命令:

$ python3 /python_examples/examples/classification/classification.py -m classification -s INCEPTION /python_examples/examples/images/tabby.jpg

首先,根据模型对输入进行预处理。对于该模型,应用了 Inception 缩放,按如下方式缩放输入:

if scaling == 'INCEPTION':
    scaled = (typed / 127.5) - 1

推断请求发送至 NVIDIA Triton ,并附上响应:

responses.append(
    triton_client.infer(FLAGS.model_name,
                        inputs,
                        request_id=str(sent_count),
                        model_version=FLAGS.model_version,
                        outputs=outputs))

最后,对从服务器获得的响应进行后处理。

postprocess(response, output_name, FLAGS.batch_size, supports_batching)

对于分类情况,模型返回包含输入图像的单个分类输出。类在控制台中被解码和打印。

for results in output_array:
    if not supports_batching:
        results = [results]
    for result in results:
        if output_array.dtype.type == np.object_:
            cls = "".join(chr(x) for x in result).split(':')
        else:
            cls = result.split(':')
        print("    {} ({}) = {}".format(cls[0], cls[1], cls[2]))

有关详细信息,请参阅classification.py

图 4 显示了示例输出。

The figure shows the sample output of an image classification model inferred over the Triton Inference Server. A Tabby image is given as an input to the network; the network correctly classifies the image.
图 4.分类网络分配给图像的分类标签

物体检测

在图像中查找特定类别的对象实例的过程称为 object detection 。对象检测问题将分类与定位结合起来。它还检查了图像可能包含多个对象的更合理的场景。有关详细信息,请参见 object detection

服务器:下载模型

下载faster_rcnn_inception_v2_coco对象检测模型:

$ cd /path/to/the/repo/server/models/detection/1
$ wget http://download.tensorflow.org/models/object_detection/faster_rcnn_inception_v2_coco_2018_01_28.tar.gz && tar xvf faster_rcnn_inception_v2_coco_2018_01_28.tar.gz && cp faster_rcnn_inception_v2_coco_2018_01_28/frozen_inference_graph.pb ./model.graphdef &&  rm -r faster_rcnn_inception_v2_coco_2018_01_28 faster_rcnn_inception_v2_coco_2018_01_28.tar.gz

以下代码示例显示了对象检测模型的模型配置文件:

name: "detection"
platform: "tensorflow_graphdef"
max_batch_size: 1
input [
  {
    name: "image_tensor"
    data_type: TYPE_UINT8
    format: FORMAT_NHWC
    dims: [ 600, 1024, 3 ]
  }
]
output [
  {
    name: "detection_boxes"
    data_type: TYPE_FP32
    dims: [ 100, 4]
    reshape { shape: [100,4] }
  },
  {
    name: "detection_classes"
    data_type: TYPE_FP32
    dims: [ 100 ]
    reshape { shape: [ 1, 100 ] }  
  },
  {
    name: "detection_scores"
    data_type: TYPE_FP32
    dims: [ 100 ]

  },
  {
    name: "num_detections"
    data_type: TYPE_FP32
    dims: [ 1 ]
    reshape { shape: [] }
  }
]

检测模型接受单个图像作为输入,并返回四个不同的输出。

客户端 :运行对象检测客户端

要运行对象检测客户端,请使用以下命令:

$ python3 /python_examples/examples/detection/detection.py -m detection /python_examples/examples/images/car.jpg

对象检测模型返回四个不同的输出,这些输出在后处理步骤中被解码:

detection_boxes = results.as_numpy(output_name[0].name)
detection_classes = results.as_numpy(output_name[1].name)
detection_scores = results.as_numpy(output_name[2].name)
num_detections = results.as_numpy(output_name[3].name)

最后,在输入上绘制边界框,如下所示:

for idx, detection_box in enumerate(detection_boxes[0,0:int(num_detections),:]):
    y_min=int(detection_box[0]*w)
    x_min=int(detection_box[1]*h)
    y_max=int(detection_box[2]*w)
    x_max=int(detection_box[3]*h)
    start_point = (x_min,y_min)
    end_point = (x_max,y_max)
    shape = (start_point, end_point)   
    draw.rectangle(shape, outline ="red")
    draw.text((int((x_min+x_max)/2),y_min), "class-"+str(int(detection_classes[0,idx])), fill=(0,0,0))

有关详细信息,请参阅detection.py

图 5 显示了示例输出。

The figure shows the sample output of an object detection model inferred over the Triton Inference Server. A car image is given as an input to the network; the network correctly localizes and classifies the car.
图 5.使用物体检测来识别和定位车辆(来源: MathWorks.com )

图像分割

对图像中与同一对象类相对应的部分进行聚类的过程称为 image segmentation 。图像分割需要将图像或视频帧分割成多个对象或片段。有关详细信息,请参见 image segmentation

服务器:下载模型

要下载模型,请使用以下命令:

$ cd /path/to/the/repo/server/models/segmentation/1
$ wget https://github.com/onnx/models/raw/main/vision/object_detection_segmentation/fcn/model/fcn-resnet50-11.onnx &&  mv fcn-resnet50-11.onnx model.onnx

以下代码示例显示了图像分割模型的模型配置文件:

name: "segmentation"
platform: "onnxruntime_onnx"
max_batch_size : 0
input [
  {
    name: "input"
    data_type: TYPE_FP32
    format: FORMAT_NCHW
    dims: [  3, -1, -1 ]
    reshape { shape: [ 1, 3, -1, -1 ] }
  }
]
output [
    {
    name: "out"
    data_type: TYPE_FP32
    dims: [  -1, 21, -1, -1 ]
  }
]

客户端:运行图像分类客户端

要运行图像分类客户端,请运行以下命令:

$ pip install opencv-python
$ python3 /python_examples/examples/segmentation/segmentation.py -m segmentation -s INCEPTION /python_examples/examples/images/people.jpg

分割模型接受单个输入并返回单个输出。推理后,模型返回基于生成分割和混合图像的输出。

# generate segmented image
result_img = colorize(raw_labels)
# generate blended image
blended_img = cv2.addWeighted(image[:, :, ::-1], 0.5, result_img, 0.5, 0)

有关详细信息,请参阅segmentation.py文件。

图 6 显示了示例输出。

The figure shows the sample output of an instance segmentation model inferred over the Triton Inference Server. The network correctly detects and segments the objects in the image.
图 6.用于语义图像分割的注释图像。来源: Visio.ai

资源

立即在 GPU 、 CPU 或两者上试用 Triton 推理服务器。 NVIDIA Triton Inference Server container 可以从 NGC 下载,其源代码可以在 /triton-inference-server GitHub repo 上获得。

 

Tags