关于人工智能:AWS自研AI芯片助力高效低成本跑起人体姿态估计

2次阅读

共计 11624 个字符,预计需要花费 30 分钟才能阅读完成。

一些童鞋可能晓得,AWS Inferentia 是 AWS 自行设计研发的 AI 专用芯片,能够用相较于传统 GPU 更高的性能和更低的老本进行机器学推理。目前一些 AWS EC2 实例曾经装备了这块芯片。不过具体来说,它的性能到底有多强?老本又能低多少?本文将通过人体姿势预计的实例向大家展现。

在本文中,咱们将应用 AWS Neuron 编译一套开源的 TensorFlow 版本的 OpenPose,并针对基于 AWS Inferentia 的实例对推理性能进行调优。与基于 GPU 的实例相比,咱们须要在本演练中设置基准测试环境、掂量图像处理管道的吞吐量,并量化该零碎的性价比改良状况。

对于 OpenPose

人体姿势预计,属于一类机器学习(ML)与计算机视觉(CV)相结合的技术利用方向,可用于反对行人用意预估、AR 和体育赛事中的静止跟踪等多种用例。姿势预计的外围在于辨认图像(关节与关键点)的具体坐标,将这些坐标串连起来以形成一个人的骨骼示意。对身材姿势的精确表白,将成为机器人交互设计乃至静止姿势量化等利用指标的实现前提。

目前市面上存在诸多可用于人体姿势预计的办法,其中 OpenPose 采取深度学习凭借自下而上的办法(由卡耐基梅隆大学认知计算实验室于 2018 年公布)吸引到泛滥拥趸。OpenPose 是一种多人 2D 姿势预计模型,其中采纳一种称为“部位亲和域”(PAF)的技术对身材各部位进行关联,并借此在图像上建设起多个独自的骨架构造。在这种自下而上的办法中,模型可能辨认出各个关键点,并据此将骨架构造拼凑在一起。

为了实现这一指标,OpenPose 应用了两步式流程。首先,它应用 VGG-19 模型提取图像特色,并将这些特色传递至并行运行的一对卷积神经网络(CNN)当中。

其中一套 CNN 负责计算置信度图,借此检测图像中的各个身材部位。另一套 CNN 则计算 PAF,并将各个局部合并起来,形成人体骨骼构造。咱们能够多次重复这些并行分支,借此欠缺置信度图与 PAF 预测后果。

下图所示,为来自 VGG 的特色 F,此特色被馈送至 OpenPose 模型的 PAF 与置信度图分支当中。(起源:应用部位亲和域进行实时多人 2D 姿势预计)

原始 OpenPose 代码依赖于 Caffe 模型与预统计的 C ++ 库。出于应用便捷性与可移植性的思考,咱们在本轮演练中应用 GitHub repo 中的 tf-pose-estimation 基于 TensorFlow 1.15 从新实现了 OpenPose 的神经网络。此 Repo 还提供 ML 管道脚本,大家能够用 OpenPose 对图像及视频进行预处理与后处理。

先决条件

在本轮演练中,须要筹备一个有权拜访 AWS 治理控制台的 AWS 账户,同时保障有权限应用公开 IP 创立 Amazon Elastic Compute Cloud (Amazon EC2) 实例和创立 Amazon Simple Storage Service (Amazon S3)存储桶。

另外,如果相熟如何应用 AWS Deep Learning AMI 与 Jupyter notebooks 中的 Conda 环境则更好,但并非硬性要求。

对于 AWS Inferentia与 Neuron SDK

AWS Inferentia 芯片是一款由 AWS 定制构建,旨在提供更高推理性能的芯片计划,可能立足云端实现最低推理老本,并帮忙大家轻松将 ML 集成至规范应用程序性能当中。

AWS Neuron 是一款软件开发套件(SDK),由编译器、运行时以及配置文件工具独特组成,这些工具可进一步优化 Inferentia 芯片的 ML 推理性能。Neuron 曾经与 TensorFlow、PyTorch 以及 MXNet 等风行 ML 框架顺畅集成,且预装在 AWS Deep Learning AMI 中。在 AWS Inferentia 上部署深度学习模型的具体形式,与其余平台上的相似环境无甚区别,能够轻松享受到这款芯片带来的性能晋升与老本优化。

在 AWS Neuron GitHub 上公布的最新 Neuron 版本,减少了对更多模型(包含 OpenPose)的反对选项,咱们将在后文中重点加以介绍。此外,Neuron 新版本还将 Neuron PyTorch 降级到最新稳定版(1.5.1),容许大家在 AWS Inferentia 上编译并运行更多模型。

应用 Neuron SDK编译 TensorFlow OpenPose模型

咱们能够在 AWS 中设置 EC2 实例,借此开启模型编译流程。本文倡议大家应用 z1d.xlarge 实例类型,其领有杰出的单核性能与内存容量。在 US East(北弗吉尼亚州)区域内,应用 AWS Deep Learning AMI(Ubuntu 18.04)的 29.0 版本(ami-043f9aeaf108ebc37)。此 AMI 预打包有 Neuron SDK 以及 AWS Inferentia 所需的 Neuron 运行时。

对于在 EC2 实例上运行 AWS Deep Learning AMI 的更多详细信息,请参阅启动并配置 DLAMI。

在通过 SSH 接入该实例时,能够激活 aws_neuron_tensorflow_p36 Conda 环境,并将 Neuron 编译器更新至最新版本。编译脚本的失常运行,依赖于 requirements-compile.txt 文件中列出的具体要求。对于编译脚本与需要文件,请参阅 GitHub repo。咱们能够应用以下代码,将其下载并装置至指标环境当中:

source activate aws_neuron_tensorflow_p36
pip install neuron-cc --upgrade --extra-index-url=https://pip.repos.neuron.amazonaws.com
git clone https://github.com/aws/aws-neuron-sdk.git /tmp/aws-neuron-sdk && cp /tmp/aws-neuron-sdk/src/examples/tensorflow/<name_of_the_new_folder>/* . && rm -rf /tmp/aws-neuron-sdk/
pip install -r requirements-compile.txt

接下来,咱们就能够开始编译过程。咱们能够编译 tf-pose-estimation 网络解冻图,在 GitHub repo 上能够找到。上面将下载到的原始脚本调整为单行 wget 命令:

wget -c --tries=2 $(wget -q -O - http://www.mediafire.com/file/qlzzr20mpocnpa3/graph_opt.pb | grep -o 'http*://download[^"]*' | tail -n 1 ) -O graph_opt.pb

当下载实现后,运行 convert_graph_opt.py 脚本认为 AWS Inferentia 芯片编译。因为 Neuron 属于提前(AOT)编译器,大家须要在编译之前定义特定的图像大小。咱们能够应用 net_resolution 参数(例如 net_resolution=656×368)来调整网络输出图像的分辨率。

编译后的模型能够在推理运行过程中承受任意批次大小的输出。此属性能够对模型的大规模部署进行基准测试;然而,示例 tf-pose-estimation repo 中用于图像及视频解决管道的批次大小设置为 1。

要开始编译流程,请输出以下代码:

python convert_graph_opt.py graph_opt.pb graph_opt_neuron_656x368.pb

编译流程最多可能须要 20 分钟。在此期间,编译器会优化 TensorFlow 图运算并为已保留的模型生成 AWS Inferentia 版本。在编译过程中,零碎会保留详尽的编译日志,例如:

2020-07-15 21:44:43.008627: I bazel-out/k8-opt/bin/tensorflow/neuron/convert/segment.cc:460] There are 11 ops of 7 different types in the graph that are not compiled by neuron-cc: Const, NoOp, Placeholder, RealDiv, Sub, Cast, Transpose, (For more information see https://github.com/aws/aws-neuron-sdk/blob/master/release-notes/neuron-cc-ops/neuron-cc-ops-tensorflow.md).
INFO:tensorflow:fusing subgraph neuron_op_ed41d2deb8c54255 with neuron-cc
INFO:tensorflow:Number of operations in TensorFlow session: 474
INFO:tensorflow:Number of operations after tf.neuron optimizations: 474
INFO:tensorflow:Number of operations placed on Neuron runtime: 465

在评估编译后的模型性能前,须要切换至由 AWS Inferentia 芯片提供反对的 EC2 Inf1 实例。要在两个实例之间共享编译实现的模型,请应用以下代码创立一个 S3 存储桶:

aws s3 mb s3://<MY_BUCKET_NAME>
aws s3 cp graph_opt_neuron_656x368.pb s3://<MY_BUCKET_NAME>/graph_model.pb

在 AWS EC2 Inf1实例上应用 Jupyter notebook对推理工夫进行基准测试

在将编译实现的 graph_model.pb 模型保留在 S3 存储桶后,咱们须要批改 GitHub repo 上的 ML 管道脚本,借此依据图像与视频预计人体姿势。

要设置基准 Inf1 实例,能够反复以上在 z1d 实例上配置编译的步骤。大家能够应用雷同的 AMI,只须要留神将实例类型更改为 inf1.xlarge。本文倡议应用 g4dn.xlarge 实例,在设置根本不变的状况下,这样的类型抉择将帮忙咱们更间接地将运行在 GPU 上的根底 tf-pose-estimation 模型性能与 AWS Inferentia 编译模型进行比拟。

通过本文,咱们将应用 Jupyter Lab 服务器与指标实例及模型进行交互。对于在 Amazon EC2 上配置 Jupyter Lab 的更多详细信息,请参阅如何设置 Jupyter Notebook 服务器。

为 tf-pose设置 Conda环境

在登录至 Jupyter Lab 服务器之后,即可克隆蕴含有 TensorFlow 版 OpenPose 的 GitHub repo。

在 Jupyter Launcher 页面中的 Other 之下,抉择 Terminal。

在终端内,激活蕴含有 Neuron SDK 的 aws_neuron_tensorflow_p36 环境。环境激活与克隆操作须要应用以下代码:

conda activate aws_neuron_tensorflow_p36
git clone https://github.com/ildoonet/tf-pose-estimation.git
cd tf-pose-estimation

在克隆实现之后,倡议依照软件包装置阐明进行操作,分步实现 Repo 装置。在同一终端屏幕内,能够通过装置 GitHub repo 中 requirements.txt 文件所列出的 opencv-python 与依赖项进行环境定制。

须要运行两条 Pip 命令:第一条命令负责解决 opencv-python;第二条负责实现 requirements.txt 中指定的装置步骤:

pip install opencv-python
pip install -r requirements.txt

当初,大家能够开始构建 Notebook 了。

在 Repo 的 root 目录中,抉择 Notebook,Environment(conda_aws_neuron_tensorflow_p36)以创立一个新的 Jupyter notebook。在 Notebook 的第一个单元格中,导入 run.py 脚本中定义的库 —— 此脚本将作为图像处理的参考管道。在后续单元格中,创立一个记录器以记录基准测试后果。详见以下代码:

import argparse
import logging
import sys
import time
from tf_pose import common
import cv2
import numpy as np
from tf_pose.estimator import TfPoseEstimator
from tf_pose.networks import get_graph_path, model_wh
logger = logging.getLogger('TfPoseEstimatorRun')
logger.handlers.clear()
logger.setLevel(logging.DEBUG)
ch = logging.StreamHandler()
ch.setLevel(logging.DEBUG)
formatter = logging.Formatter('[%(asctime)s] [%(name)s] [%(levelname)s] %(message)s')
ch.setFormatter(formatter)
logger.addHandler(ch)

定义次要推理函数 main()与辅助绘图函数 plotter()。这些函数是间接从 run.py 处复制的 OpenPose 推理管道。咱们须要对其做出简略批改,即增加 repeats 参数,借此顺次运行多个推理步骤并改良对均匀模型吞吐量的度量能力(以每张图像的解决秒数为单位):

def main(argString='--image ./images/contortion1.jpg --model cmu', repeats=10):
 parser = argparse.ArgumentParser(description='tf-pose-estimation run')
 parser.add_argument('--image', type=str, default='./images/apink2.jpg')
 parser.add_argument('--model', type=str, default='cmu',
 help='cmu / mobilenet_thin / mobilenet_v2_large / mobilenet_v2_small')
 parser.add_argument('--resize', type=str, default='0x0',
 help='if provided, resize images before they are processed.'
 'default=0x0, Recommends : 432x368 or 656x368 or 1312x736')
 parser.add_argument('--resize-out-ratio', type=float, default=2.0,
 help='if provided, resize heatmaps before they are post-processed. default=1.0')
 args = parser.parse_args(argString.split())
 w, h = model_wh(args.resize)
 if w == 0 or h == 0:
 e = TfPoseEstimator(get_graph_path(args.model), target_size=(432, 368))
 else:
 e = TfPoseEstimator(get_graph_path(args.model), target_size=(w, h))
 # estimate human poses from a single image !
 image = common.read_imgfile(args.image, None, None)
 if image is None:
 logger.error('Image can not be read, path=%s' % args.image)
 sys.exit(-1)
 t = time.time()
 for _ in range(repeats):
 humans = e.inference(image, resize_to_default=(w > 0 and h > 0), upsample_size=args.resize_out_ratio)
 elapsed = time.time() - t
 logger.info('%d times inference on image: %s at %.4f seconds/image.' % (repeats, args.image, elapsed/repeats))
 image = TfPoseEstimator.draw_humans(image, humans, imgcopy=False)
 return image, e
def plotter(image):
 try:
 import matplotlib.pyplot as plt
 fig = plt.figure(figsize=(12,12))
 a = fig.add_subplot(1, 1, 1)
 a.set_title('Result')
 plt.imshow(cv2.cvtColor(image, cv2.COLOR_BGR2RGB))
 except Exception as e:
 logger.warning('matplitlib error, %s' % e)
 cv2.imshow('result', image)
 cv2.waitKey()

另外,如果比拟喜爱冒险,也能够依据 run_video.py 或 run_directory.py 批改用于推理视频或批量图像的代码构造。本轮演练仅供参考,大家无妨放松心态,纵情尝试!

其中 main()函数会将 GitHub repo 中 Test Inference 局部形容的参数字符串作为输出。要测试 Notebook 的实现成果,请应用一组参考参数(请应用原始下载脚本以确保下载 cmu 模型):

img, e = main('--model cmu --resize 656x368 --image=./images/ski.jpg --resize-out-ratio 2.0')
plotter(img)

日志内容显示,第一个多人姿势剖析工作曾经实现:

‘[TfPoseEstimatorRun] [INFO] 10 times inference on image: ./images/ski.jpg at 1.5624 seconds/image.’

能够看到,以后吞吐量每秒有余一帧(FPS),代表性能体现比拟差。在这种状况下,咱们理论是未应用 GPU 资源运行 TesnorFlow 图–model cmu。很多敌人都分明,这类模型在 CPU 上无奈获得最佳运行性能。如果反复设置步骤,并抉择应用搭载英伟达 T4 GPU 的 g4dn.xlarge 实例,则后果将大为不同:

‘[TfPoseEstimatorRun] [INFO] 10 times inference on image: ./images/ski.jpg at 0.1708 seconds/image’

结果显示 5.85 FPS,性能失去了显著晋升。

应用 Neuron编译实现的 CMU模型

到这里,咱们曾经应用了 repo 自带的模型工件。接下来,咱们换一种形式:不再应用原始下载脚本来获取 CMU 模型,而是将 Neuron 编译实现的模型复制到./models/graph/cmu/graph_model.pb,而后再次运行测试:

aws s3 cp s3://<MY_BUCKET_NAME>/graph_opt.pb ./models/graph/cmu/graph_model.pb

如果之前曾经对未经 Neuron 编译的模型进行过测试,请确保在 Notebook 上重新启动 Python 内核。重新启动内核,可能保障敞开所有 TensorFlow 会话,为基准测试提供齐全等效的空白环境。再次运行同一 Notebook,将失去以下日志条目:

‘[TfPoseEstimatorRun] [INFO] 10 times inference on image: ./images/ski.jpg at 0.1709 seconds/image.’

结果显示,与 g4dn.xlarge 实例相比,新环境可能在升高约 30% 经营老本的前提下实现雷同的帧速率。这意味着将工作负载转移至基于 AWS Inferentia 的实例尽管无奈在吞吐量层面带来直观可见的性能晋升,但却的确具备老本劣势。例如,当迁徙至 AWS Inferentia 时,Amazon Alexa 文本到语音转换团队得以将推理老本升高达 50%。

咱们决定分析已编译的图版本,并进一步寻求对 OpenPose 管道进行端到端推理性能调优的空间。Neuron 与 TensorFlow 相集成之后,可实现对本地配置文件库的拜访。要分析 Neuron 编译图,咱们应用 TensorFlow Python 分析器,在 estimator 办法上检测 TensorFlow 会话所运行的命令:

from tensorflow.core.protobuf import config_pb2
from tensorflow.python.profiler import model_analyzer, option_builder
run_options = config_pb2.RunOptions(trace_level=config_pb2.RunOptions.FULL_TRACE)
run_metadata = config_pb2.RunMetadata()
peaks, heatMat_up, pafMat_up = self.persistent_sess.run([self.tensor_peaks, self.tensor_heatMat_up, self.tensor_pafMat_up], feed_dict={self.tensor_image: [img], self.upsample_size: upsample_size
 },
 options=run_options, run_metadata=run_metadata
)
options = option_builder.ProfileOptionBuilder.time_and_memory()
model_analyzer.profile(self.persistent_sess.graph, run_metadata, op_log=None, cmd='scope', options=options)
The model_analyzer.profile method prints on StdErr the time and

其中 model_analyzer.profile 办法会在 StdErr 上输入 TensorFlow 图上各项操作所对应的工夫与内存耗费。应用原始代码,Neuron 操作与平滑操作占据整个图运行工夫中的大部分比例。以下 StdErr 日志输入结果显示,总图运行工夫为 108.02 毫秒,其中平滑操作消耗 43.07 毫秒:

node name | requested bytes | total execution time | accelerator execution time | cpu execution time
_TFProfRoot (--/16.86MB, --/108.02ms, --/0us, --/108.02ms)
…
 TfPoseEstimator/conv5_2_CPM_L1/weights/neuron_op_ed41d2deb8c54255 (430.01KB/430.01KB, 58.42ms/58.42ms, 0us/0us, 58.42ms/58.42ms)
…
smoothing (0B/2.89MB, 0us/43.07ms, 0us/0us, 0us/43.07ms)
 smoothing/depthwise (2.85MB/2.85MB, 43.05ms/43.05ms, 0us/0us, 43.05ms/43.05ms)
 smoothing/gauss_weight (47.50KB/47.50KB, 18us/18us, 0us/0us, 18us/18us)
…

其中,OpenPose 中平滑办法提供针对置信度图计算得出的高斯含糊后果。通过对此项计算进行优化,咱们可能从端到端姿势预计当中榨取出更好的性能。咱们将 estimator.py 脚本上的平滑器 filter 参数从 25 批改为 5。在应用新配置之后,总运行工夫升高至 67.44 毫秒,其中平滑计算现在只须要 2.37 毫秒 —— 工夫节约量达 37%!而在 g4dn 实例上,雷同的优化对于运行工夫简直没有任何影响。大家还能够更改同一参数,并通过本地正本重新安装 tf-pose-estimation repo 的形式优化端到端管道版本。

咱们应用七种不同的实例类型与大小运行了同一项基准测试,借此评估端到端图像处理管道的性能与推理老本优化成果。为了进行直观比拟,咱们还纳入了 Amazon EC2 按需实例的计费指标。

结果显示,即便是 Inf1 实例中最小的 xlarge 实例,其吞吐量也要比 g4dn 实例中最强劲的 8xlarge 实例高 2 倍,且解决 1000 张图像的老本仅为后者的十二分之一。比照最优的两个选项,inf1.xlarge 和 g4dn.xlarge(老本最低的 GPU 选项),Inf1 可能将每 1000 张图像的解决老本较 g4dn.xlarge 升高 72%,相当于性价比晋升 3.57 倍。下表整顿了此次基准测试的各项发现:

inf1.xlarge inf1.2xlarge inf1.6xlarge g4dn.xlarge _g4dn.2xlarge _g4dn.4xlarge _g4dn.8xlarge
图像处理工夫(秒 / 图像) 0.0703 0.0677 0.0656 0.1708 0.1526 0.1477 0.1427
吞吐量(FPS) 14.22 14.77 15.24 5.85 6.55 6.77 7.01
1000 张图像处理工夫(秒) 70.3 67.7 65.6 170.8 152.6 147.7 142.7
按需实例价格 $ 0.368 $ 0.584 $ 1.904 $ 0.526 $ 0.752 $ 1.204 $ 2.176
每 1000 张图像处理老本 $ 2.176 $ 0.011 $ 0.035 $ 0.025 $ 0.032 $ 0.049 $ 0.086

以下图表,总结了 xlarge 与 2xlarge 实例在解决 1000 张图像时的吞吐量与老本状况。

通过在端到端管道中引入数据并行处理办法,咱们又进一步升高了 Inf1 实例的图像处理老本并晋升了 tf-pose-estimation 吞吐量。上表中列出的数值,与繁多 AWS Inferentia 解决外围(即 Neuron 外围)的应用形式无关。基准实例中蕴含 4 个外围,因而仅应用其中 1 个显然会产生资源节约。咱们应用 Python joblib 库以比拟毛糙的形式将 main ()函数调用实现并发扩大至四个线程当中。这种模式可能将吞吐量晋升至 56.88FPS,并将每 1000 张图像的老本升高至 0.002 美元以下。这意味着更好的批处理策略能够让 OpenPose 在 AWS Inferentia 实例上的运行性价比失去更进一步的改善。

规模较大的 CMU 模型还能提供更好的姿势预计性能。例如,大家能够在蕴含多重景深与相应拍摄对象的场景下(参见下图),应用 Neuron SDK 编译模型进行多姿势检测。


平安敞开并进行资源清理

在 Amazon EC2 管制台上抉择编译与推理实例,而后从 Actions 下拉菜单中抉择 Terminate。编译之后的模型将被保留在 s3://_<MY_BUCKET_NAME>_当中以备后续重复使用。如果对实例中的代码做出了更改,也请留神进行保留。实例终止仅会导致存储在实例主卷内的数据失落。

总结
在本文中,咱们分步实现了对 OpenPose TensorFlow 版开源模型的编译,更新自定义端到端图像处理管道,并体验了可能在 EC2 Infi1 实例之上对 ML 推理工夫做出剖析及深度优化的工具。在调优之后,Neuron 编译的 TensorFlow 模型较现有费率最低的 GPU 实例实现 72% 的老本节约,且性能仍旧保持一致。本文中论述的各项操作步骤,也实用于其余 ML 模型类型与框架。对于更多详细信息,请参阅 AWS Neuron SDK GitHub repo。

感兴趣的敌人能够参阅对于 AWS Inferentia 芯片与 Amazon EC2 Inf1 实例的更多详细信息,应用 Neuron SDK 在 AWS Inferentia 上运行本人的定制化 ML 管道。

正文完
 0