「YOLO-V8」 香橙派AIpro 上量化(int8/fp16)和部署 yolov8 目标检测模型(1)
收藏回复举报
「YOLO-V8」 香橙派AIpro 上量化(int8/fp16)和部署 yolov8 目标检测模型(1)
发表于2024-02-17 17:55:18
0 查看

AI Pro 部署 yolov8 目标检测模型 -- 导出int8量化模型(1)

yolov8 是一个单阶段的CV模型,包含目标检测,也可以用于分类、分割和关键点预测(https://github.com/ultralytics/ultralytics)。作为项目部署是个不错的选择,试试部署+运行在边缘设备香橙派AIpro。yolov8-nano 模型速度为 102fps,resnet50 速度为280fps。看看表现吧。

image.png

前置工作

使用笔记本电脑,ssh远程连接到AI pro。

  • 「AI pro」使用镜像 opiaipro_ubuntu22.04_desktop_aarch64_20240202.img.xz
  • 「AI pro」使用 root 账号登陆。因为NPU的调度需要 root 权限,即使 sudo 都不好使。
  •  (推荐)「AI pro」开启 mindx sdk,执行命令 source /usr/local/Ascend/mxVision/set_env.sh
  • 「AI pro 或 笔记本」安装 amct_onnx 昇腾模型量化工具,不量化就忽略该操作。
  • 「AI pro 或 笔记本」 pip install onnx onnxruntime 等工具包。在安装 amct_onnx 时,已经自动安装了。
  • 「笔记本」下载和安装 ultralytics-yolo 的开发环境。

由于 AI pro 上已经配置了 CANN + MINDX 环境,再装一个 amct 就容易凑齐全家桶了。从零开始配置笔记本的 CANN + MINDX + acmt 太费劲。

工作流程

非量化模型,fp16

pytorch -> onnx -> om

模型pytorch ->onnx->om
文件yolov8n.ptyolov8n.onnxyolov8n.om
工具

ultralytics

atc

量化模型,int8, 算力翻倍

pytorch -> onnx -> onnx_deploy (int8) -> om

模型pytorch ->onnx->onnx_deploy->om
文件yolov8n.ptyolov8n.onnx

yolov8n_deploy_model.onnx

yolov8n_deploy_model.om
工具

ultralytics

amct_onnx

atc

1. 下载或训练自己的yolo模型 [笔记本电脑]

这里我选用的是官方 yolov8-det-nano 模型。你也可以选择 seg、cls,或者将自己训练的模型导出为 ONNX 文件。

# 官方模型 yolov8n.pt
python -c "from ultralytics import YOLO;YOLO('yolov8n').export(format='onnx')"

# 自己模型
python -c "from ultralytics import YOLO;YOLO('PATH_TO_MY_YOLO.pt').export(format='onnx')"

mv yolov8n.onnx model/

得到 yolov8n.onnx, 将其从笔记本中拷贝到 香橙派 AI pro。剩下的操作都在 AI pro 中进行。

2. (可选,推荐)检查 ONNX 的输入输出维度,可以修改 batchsize

模型量化和导出,都需要知道 ONNX 模型的输入节点的维度以及名称,不能有误。可以使用作者的工具 onnx_inspect 检查。

root@orangepiaipro# onnx_inspect model/yolov8n.onnx
[I] Loading model: model/yolov8n.onnx
[I] ==== ONNX Model ====
    Name: torch-jit-export | ONNX Opset: 14
    
    ---- 1 Graph Input(s) ----
    images [dtype=float32, shape=(1, 3, 640, 640)]
    
    ---- 1 Graph Output(s) ----
    output0 [dtype=float32, shape=('Concatoutput0_dim_0', 'Concatoutput0_dim_1', 'Concatoutput0_dim_2')]
    
    ---- 138 Initializer(s) ----
    
    ---- 286 Node(s) ----

记录输入节点的名称 images,维度 (1, 3, 640, 640)

模型的batchsize 是1,可以将其修改为其它size,或者是 dynamic batchsize 。尤其在模型的量化中,使用dynamic batchsize更好的兼容多张图片的 Evaluation。

root@orangepiaipro# onnx_rebatch model/yolov8n.onnx --batch 0 # to dynamic
root@orangepiaipro# onnx_inspect model/yolov8n_batchdynamic.onnx
[I] Loading model: model/yolov8n_batchdynamic.onnx
[I] ==== ONNX Model ====
    Name: torch-jit-export | ONNX Opset: 14
    
    ---- 1 Graph Input(s) ----
    images [dtype=float32, shape=('N', 3, 640, 640)]
    
    ---- 1 Graph Output(s) ----
    output0 [dtype=float32, shape=('N', 'Concatoutput0_dim_1', 'Concatoutput0_dim_2')]
    
    ---- 138 Initializer(s) ----
    
    ---- 286 Node(s) ----

通过本人提供的 onnx_rebatch 工具,将 yolov8n.onnx 修改为动态batchsize 的 yolov8n_batchdynamic.onnx。修改后,输入节点的名称依然为 images,维度 (N, 3, 640, 640)

不量化,直接转 OM

这样最简单,输出的是 float16 计算精度的模型,计算速度折中。

root@orangepiaipro# atc --model=model/yolov8n.onnx --framework=5 \
  --output=model/yolov8n --input_shape="images:1,3,640,640" \
  --soc_version=Ascend310B4

root@orangepiaipro# onnx_inspect model/yolov8n.om
[I] Loading model: model/yolov8n.om
[I] ==== OM Model ====
    
    ---- 1 Graph Input(s) ----
    #0 [dtype=float32, shape=(1, 3, 640, 640)]
    
    ---- 1 Graph Output(s) ----
    #0 [dtype=float32, shape=(1, 84, 8400)]

3. 量化模型

首先,要将data/images目录下的jpg文件处理为data/calibration目录下的bin文件。

参考 python/level1_single_api/9_amct/amct_onnx/cmd · Ascend/samples - 码云 - 开源中国 (gitee.com) 里面的步骤、数据和代码。下载对应的数据集。拷贝和修改samples/python/level1_single_api/9_amct/amct_onnx/cmd/src/process_data.py 。

具体注意事项:

  • YOLO 的输入维度 (N, 3, h=640, w=640), 所以设定图片resize也为 (640, 640).
  • CALIBRATION_SIZE 是用来量化的图片总数,数量越多量化的效果越好。但它需要和onnx 的batchsize 保持一致。如果使用 yolov8n.onnx, 则必须使用 CALIBRATION_SIZE =1 。使用 yolov8n_batchdynamic.onnx 时,可以设置更大的CALIBRATION_SIZE。
  • YOLO 图片的像素数值归一化是 uint8 / 255.0,不需要设定 MEAN 和 STD。
# src/process_data.py
...

WIDTH, HEIGHT = 640, 640
CALIBRATION_SIZE = 16
...

def prepare_image_input(images, height=HEIGHT, width=WIDTH):
    """Read image files to blobs [batch_size, 3, 224, 224]"""
    input_array = np.zeros((len(images), 3, height, width), np.float32)
    mean = MEAN
    std = STD

    imgs = np.zeros((len(images), 3, height, width), np.float32)
    for index, im_file in enumerate(images):
        im_data = cv2.imread(im_file)
        im_data = cv2.resize(
            im_data, (width, height), interpolation=cv2.INTER_CUBIC)
        cv2.cvtColor(im_data, cv2.COLOR_BGR2RGB)

        imgs[index] = im_data.transpose(2, 0, 1).astype(np.float32)

    input_array = imgs
    # trans uint8 image data to float
    input_array /= 255
    return input_array

...

执行图片预处理

  • 将得到 data/calibration/calibration.bin ,是用于模型压缩的数据集,包含CALIBRATION_SIZE 张图片。
python3 ./src/process_data.py

执行ONNX模型压缩(int8 量化):

  • 将得到量化后的 ONNX 文件, yolov8n_deploy_model.onnx。由于是int8压缩,文件体积更小。

amct_onnx calibration --model model/yolov8n_batchdynamic.onnx --input_shape "images:16,3,640,640" --data_type "float32" --data_dir ./data/calibration/ --save_path ./results/yolov8n

4. 压缩的ONNX 再转 OM

用 atc 工具,正常转换就可以。

root@orangepiaipro# atc --model=model/yolov8n_deploy_model.onnx --framework=5 \
  --output=model/yolov8n_deploy_model --input_shape="images:1,3,640,640" \
  --soc_version=Ascend310B4

root@orangepiaipro# onnx_inspect model/yolov8n_deploy_model.om
[I] Loading model: model/yolov8n_deploy_model.om
[I] ==== OM Model ====
    
    ---- 1 Graph Input(s) ----
    #0 [dtype=float32, shape=(1, 3, 640, 640)]
    
    ---- 1 Graph Output(s) ----
    #0 [dtype=float32, shape=(1, 84, 8400)]
模型文件总揽
文件名文件大小功能
yolov8n.pt6.3Mpytorch 模型
yolov8n.onnx13Monnx原始的模型
yolov8n_batchdynamic.onnx13M动态batchsize
yolov8n_deploy_model.onnx4M模型用 int8 压缩
yolov8n.om

6.8M

fp16精度的模型
yolov8n_deploy_model.om4.4Mint8 精度压缩的模型

5. 性能测试

  • 不包含 图片的pre-processing, 也不包含数据的post-processing。

单独开一个终端,用于检测 NPU 的使用率

watch -n 1 npu-smi info

cke_1494571.png

检查 'mind sdk' 是否安装和配置:

  • 看到下面的输出,表明 mind sdk 的配置是成功的
root@orangepiaipro# python -c "from mindx.sdk import base, Tensor"

Begin to initialize Log.
The output directory of logs file exist.
WARNING: Logging before InitGoogleLogging() is written to STDERR
I20240217 17:21:41.766203 254529 FileUtils.cpp:336] The input file is empty
I20240217 17:21:41.766286 254529 FileUtils.cpp:480] Check Other group permission: Current permission is 4, but required no greater than 0.
Save logs information to specified directory.
FPSNPU(%)命令(onnx_speed 本人写的工具)
ONNX 模型1.840

onnx_speed model/yolov8n.onnx

OM FP16

85.157onnx_speed model/yolov8n.om
多线程 c=4102.168

echo "1 2 3 4" | xargs -n 1 -P 0 onnx_speed model/yolov8n.om -i 

OM INT8

85.147onnx_speed model/yolov8_deploy_model.om
多线程 c=4101.955echo "1 2 3 4" | xargs -n 1 -P 0 onnx_speed model/yolov8_deploy_model.om -i 

可以看到 YOLOV8n 经过模型量化(int8)之后,在AI pro上的速度为 102 fps。相较于 CPU 上的模型提升 50x,NPU 的确更适合模型推理。模型量化前后,没有提升,可能存在瓶颈。

YOLOV8n 没法吃满 NPU 的算力,即使多线程也只能使用NPU一半的性能。这应该是 CPU float32(1, 3, 640, 640) ==> NPU 数据传输太慢的问题。在跑 resnet50.om 量化模型的时候,输入尺寸(1,3,224,224), NPU 能够占用NPU 88%,fps 达200,说明NPU本身没有问题。而 AI pro 的CPU和内存都比较慢,大体积的数组拷贝非常吃力。

即使 numpy 数组在内存中克隆, AI pro速度也是非常慢的,是香橙派5(rk3588, 8G内存)的约 1/4 速度。详细数据未展示。

Resnet 模型推断速度

resnet (224x224) 推理速度

FPSNPU(%)命令

Resnet50

184.487onnx_speed model/resnet50.om

INT8 量化

286.578onnx_speed model/resnet50_deploy_model.om
Resnet101120.291onnx_speed model/resnet101.om
INT8 量化205.085onnx_speed model/resnet101_deploy_model.om

模型量化前后,速度有提升。接近理论的2倍提升。

6. 总结

这套模型量化,可以适用 yolo 系列,也可以用于 resnet 等其它网络。受限于内存的瓶颈,int8 量化对于 yolo 轻量模型没有增益。对于计算密集的模型,量化才有显著的提升作用

本帖最后由 匿名用户2025/04/01 16:45:19 编辑

我要发帖子