RetinaNet是一种One-Stage RCNN类型的检测网络,基本结构由一个Backbone、多个子网及NMS后处理组成。许多训练框架中均实现了RetinaNet,典型的框架有Detectron2。本文以Detectron2的标准RetinaNet实现为例,介绍如何使用Blade优化RetinaNet(Detectron2)类型的模型。
使用限制
本文使用的环境需要满足以下版本要求:
- 系统环境:Linux系统中使用Python 3.6及其以上版本、CUDA 10.2。
- 框架:PyTorch 1.8.1及其以上版本、Detectron2 0.4.1及其以上版本。
- 推理优化工具:Blade 3.16.0及其以上版本。
操作流程
使用Blade优化RetinaNet(Detectron2)类型模型的流程如下:
- 步骤一:导出模型
使用Detectron2提供的
TracingAdapter
或scripting_with_instances
任何一种方式导出模型。 - 步骤二:调用Blade优化模型
调用
blade.optimize
接口优化模型,并保存优化后的模型。 - 步骤三:加载运行优化后的模型
经过对优化前后的模型进行性能测试,如果对结果满意,可以加载优化后的模型进行推理。
步骤一:导出模型
Detectron2是FAIR开源的灵活、可扩展、可配置的目标检测和图像分割训练框架。由于框架的灵活性,使用常规方法导出模型可能会失败或得到错误的导出结果。为了支持TorchScript部署,Detectron2提供了TracingAdapter
和scripting_with_instances
两种导出方式,详情请参见Detectron2 Usage。
Blade支持输入任意形式的TorchScript模型,如下以scripting_with_instances
为例,介绍导出模型的过程。
import torch
import numpy as np
from torch import Tensor
from torch.testing import assert_allclose
from detectron2 import model_zoo
from detectron2.export import scripting_with_instances
from detectron2.structures import Boxes
from detectron2.data.detection_utils import read_image
# 使用scripting_with_instances导出RetinaNet模型。
def load_retinanet(config_path):
model = model_zoo.get(config_path, trained=True).eval()
fields = {
"pred_boxes": Boxes,
"scores": Tensor,
"pred_classes": Tensor,
}
script_model = scripting_with_instances(model, fields)
return model, script_model
# 下载一张示例图片。
# wget http://www.yunxiaoer.com/wp-content/uploads/2023/12/20231209231619-6574f5439b6dc.jpg -q -O input.jpg
img = read_image('./input.jpg')
img = torch.from_numpy(np.ascontiguousarray(img.transpose(2, 0, 1)))
# 尝试执行和对比导出模型前后的结果。
pytorch_model, script_model = load_retinanet("COCO-Detection/retinanet_R_50_FPN_3x.yaml")
with torch.no_grad():
batched_inputs = [{"image": img.float()}]
pred1 = pytorch_model(batched_inputs)
pred2 = script_model(batched_inputs)
assert_allclose(pred1[0]['instances'].scores, pred2[0].scores)
步骤二:调用Blade优化模型
- 调用Blade优化接口。调用
blade.optimize
接口对模型进行优化,代码示例如下。关于blade.optimize
接口详情,请参见优化PyTorch模型。import blade test_data = [(batched_inputs,)] # PyTorch的输入数据是List of tuple。 optimized_model, opt_spec, report = blade.optimize( script_model, # 上一步导出的TorchScript模型。 'o1', # 开启Blade O1级别的优化。 device_type='gpu', # 目标设备为GPU。 test_data=test_data, # 给定一组测试数据,用于辅助优化及测试。 )
- 打印优化报告并保存模型。Blade优化后的模型仍然是一个TorchScript模型。完成优化后,您可以通过如下代码打印优化报告并保存优化模型。
# 打印优化报告。 print("Report: {}".format(report)) # 保存优化后的模型。 torch.jit.save(optimized_model, 'optimized.pt')
打印的优化报告如下所示,关于优化报告中的字段详情请参见优化报告。
Report: { "software_context": [ { "software": "pytorch", "version": "1.8.1+cu102" }, { "software": "cuda", "version": "10.2.0" } ], "hardware_context": { "device_type": "gpu", "microarchitecture": "T4" }, "user_config": "", "diagnosis": { "model": "unnamed.pt", "test_data_source": "user provided", "shape_variation": "undefined", "message": "Unable to deduce model inputs information (data type, shape, value range, etc.)", "test_data_info": "0 shape: (3, 480, 640) data type: float32" }, "optimizations": [ { "name": "PtTrtPassFp16", "status": "effective", "speedup": "3.77", "pre_run": "40.64 ms", "post_run": "10.78 ms" } ], "overall": { "baseline": "40.73 ms", "optimized": "10.76 ms", "speedup": "3.79" }, "model_info": { "input_format": "torch_script" }, "compatibility_list": [ { "device_type": "gpu", "microarchitecture": "T4" } ], "model_sdk": {} }
- 对优化前后的模型进行性能测试。性能测试的代码示例如下所示。
import time @torch.no_grad() def benchmark(model, inp): for i in range(100): model(inp) torch.cuda.synchronize() start = time.time() for i in range(200): model(inp) torch.cuda.synchronize() elapsed_ms = (time.time() - start) * 1000 print("Latency: {:.2f}".format(elapsed_ms / 200)) # 对优化前的模型测速。 benchmark(pytorch_model, batched_inputs) # 对优化后的模型测速。 benchmark(optimized_model, batched_inputs)
本次测试的参考结果值如下。
Latency: 42.38 Latency: 10.77
上述结果表示同样执行200轮,优化前后的模型平均延时分别是42.38 ms和10.77 ms。
步骤三:加载运行优化后的模型
- 可选:在试用阶段,您可以设置如下的环境变量,防止因为鉴权失败而程序退出。
export BLADE_AUTH_USE_COUNTING=1
- 获取鉴权。
export BLADE_REGION=export BLADE_TOKEN=
您需要根据实际情况替换以下参数:
- :Blade支持的地域,需要加入Blade用户群获取该信息,用户群的二维码详情请参见获取Token。
- :鉴权Token,需要加入Blade用户群获取该信息,用户群的二维码详情请参见获取Token。
- 部署模型。Blade优化后的模型仍然是TorchScript,因此您无需切换环境即可加载优化后的结果。
import blade.runtime.torch import detectron2 import torch from torch.testing import assert_allclose from detectron2.utils.testing import ( get_sample_coco_image, ) pytorch_model = model_zoo.get("COCO-Detection/retinanet_R_50_FPN_3x.yaml", trained=True).eval() optimized_model = torch.jit.load('optimized.pt') img = read_image('./input.jpg') img = torch.from_numpy(np.ascontiguousarray(img.transpose(2, 0, 1))) with torch.no_grad(): batched_inputs = [{"image": img.float()}] pred1 = pytorch_model(batched_inputs) pred2 = optimized_model(batched_inputs) assert_allclose(pred1[0]['instances'].scores, pred2[0].scores, rtol=1e-3, atol=1e-2)
内容没看懂? 不太想学习?想快速解决? 有偿解决: 联系专家
阿里云企业补贴进行中: 马上申请
腾讯云限时活动1折起,即将结束: 马上收藏
同尘科技为腾讯云授权服务中心。
购买腾讯云产品享受折上折,更有现金返利:同意关联,立享优惠
转转请注明出处:https://www.yunxiaoer.com/165252.html