跳到主要内容

TPU-MLIR 使用

目录

提示

如还没安装 TPU-MLIR 的运行环境,请参考上一章节

模型转换

本案例以 yolov5s.onnx 为例, 介绍如何编译并迁移一个 onnx 模型至 SG2300X TPU 平台运行,本章节模型编译都在上一章节安装的 TPU-MLIR docker 中运行。

转换 MLIR

  • TPU-MLIR 同级目录 下创建工作目录, 将所需模型与所需数据集(校准数据集,测试数据集)放入工作目录下

    mkdir yolov5s && cd yolov5s
    wget https://github.com/ultralytics/yolov5/releases/download/v6.0/yolov5s.onnx
    cp -r ../tpu-mlir/regression/dataset/COCO2017/ .
    cp -r ../tpu-mlir/regression/image/ .
  • ONNX 转 MLIR

    如果模型是图片输入, 在转模型之前我们需要了解模型的预处理。如果模型用预处理后的 npz 文件做输入, 则不需要考虑预处理。 官网 yolov5s 输入的图片是 rgb, 每个值会乘以 1/255 , 转换成 mean 和 scale 对应为 0.0,0.0,0.00.0039216,0.0039216,0.0039216

    模型转换命令如下:

    mkdir build && cd build
    model_transform.py \
    --model_name yolov5s \
    --model_def ../yolov5s.onnx \
    --input_shapes [[1,3,640,640]] \
    --mean 0.0,0.0,0.0 \
    --scale 0.0039216,0.0039216,0.0039216 \
    --keep_aspect_ratio \
    --pixel_format rgb \
    --test_input ../image/dog.jpg \
    --test_result yolov5s_top_outputs.npz \
    --mlir yolov5s.mlir

    model_transform.py 会生产一个中间格式模型 mlir, 通过 model_deploy.py 生成对应平台对应精度的 bmodel

    model_transform.py参数解析

    参数必需描述
    model_name模型名称
    model_def模型定义文件(.onnx.pt.tflite.prototxt
    model_data指定模型权重文件,当为caffe模型时需要(对应.caffemodel文件)
    input_shapes输入形状,例如 [[1,3,640,640]](二维数组),支持多个输入
    resize_dims要调整为的原始图像大小。如果未指定,将调整为模型的输入大小
    keep_aspect_ratio调整大小时是否保持宽高比。默认为 False。如果设置,则在不足的部分填充0
    mean图像每个通道的均值。默认为 0.0, 0.0, 0.0
    scale图像每个通道的缩放比例。默认为 1.0, 1.0, 1.0
    pixel_format图像类型,可以是 rgb、bgr、gray 或 rgbd
    output_names输出的名称。如果未指定,则使用模型的输出;否则使用指定的名称作为输出
    test_input用于验证的输入文件,可以是图像、npy 或 npz。如果未指定,将不进行验证
    test_result保存验证结果的输出文件
    excepts需要从验证中排除的网络层的名称。用逗号分隔
    debug如果开启调试,模型文件将保留;否则在转换完成后删除
    mlir输出的mlir文件名(包括路径)

生成 bmodel

MLIR 生成 F32 bmodel
model_deploy.py \
--mlir yolov5s.mlir \
--quantize F32 \
--processor bm1684x \
--test_input yolov5s_in_f32.npz \
--test_reference yolov5s_top_outputs.npz \
--model yolov5s_1684x_f32.bmodel

model_deploy.py 参数解析:

参数必需描述
mlirMlir 文件
quantize量化类型(F32/F16/BF16/INT8)
processor模型将使用的平台。目前仅支持 bm1684x/bm1684/cv183x/cv182x/cv181x/cv180x, 将来将支持更多的TPU平台
calibration_table量化表的路径。进行 INT8 量化时需要
toleranceMLIR 量化和 MLIR fp32 推断结果之间的最小相似度容差
correctnetss模拟器和 MLIR 量化推断结果之间的最小相似度容差。默认为 0.99,0.90
excepts需要从验证中排除的网络层的名称。用逗号分隔
debug如果开启调试,模型文件将保留;否则在转换完成后删除
model输出模型文件的名称(包括路径)
dynamic用于支持动态形状的动态代码生成
MLIR 生成 F16 bmodel
model_deploy.py \
--mlir yolov5s.mlir \
--quantize F16 \
--processor bm1684x \
--model yolov5s_1684x_f16.bmodel
MLIR 生成 INT8 bmodel
  • 生成校准表,转INT8模型前需要运行run_calibration.py得到校准表; 输入数据的数量根据情况准备100~1000张左右。

  • 使用校准表, 生成对称或非对称 bmodel。如果对称符合需求, 一般不建议用非对称, 因为非对称的性能会略差于对称模型。

  • 这里用现有的100张来自 COCO2017 的图片举例, 执行run_calibration.py:

    run_calibration.py yolov5s.mlir \
    --dataset ../COCO2017 \
    --input_num 100 \
    -o yolov5s_cali_table
  • 编译为INT8对称量化模型, 执行如下命令:

    model_deploy.py \
    --mlir yolov5s.mlir \
    --quantize INT8 \
    --calibration_table yolov5s_cali_table \
    --chip bm1684x \
    --model yolov5s_1684x_int8_sym.bmodel

    编译完成后, 会生成名为 yolov5s_1684x_int8_sym.bmodel 的文件

编译为 INT8 非对称量化模型

转成 INT8 非对称量化模型, 执行如下命令:

model_deploy.py \
--mlir yolov5s.mlir \
--quantize INT8 \
--asymmetric \
--calibration_table yolov5s_cali_table \
--chip bm1684x \
--model yolov5s_1684x_int8_asym.bmodel

编译完成后, 会生成名为 yolov5s_1684x_int8_asym.bmodel 的文件

编译为混合精度模型

如果 INT8 对称量化模型出现不能接受的精度损失在完成 INT8 对称量化模型的基础上, 执行如下步骤

  • 使用 run_qtable.py 生成混精度量化表, 相关参数说明如下:

    run_qtable.py yolov5s.mlir \
    --dataset ../COCO2017 \
    --calibration_table yolov5s_cali_table \
    --chip bm1684x \
    --min_layer_cos 0.999 \ #若这里使用默认的0.99时,程序会检测到原始int8模型已满足0.99的cos,从而直接不再搜素
    --expected_cos 0.9999 \
    -o yolov5s_qtable

    run_qtable.py参数功能

    参数名必选?说明
    指定 mlir 文件
    dataset指定输入样本的目录, 该路径放对应的图片, 或 npz, 或 npy
    data_list指定样本列表, 与 dataset 必须二选一
    calibration_table输入校准表
    chip指定模型将要用到的平台, 支持 bm1684x/bm1684/cv183x/cv182x/cv181x/cv180x
    fp_type指定混精度使用的 float 类型, 支持 auto,F16,F32,BF16,默认为 auto,表示由程序内部自动选择
    input_num指定输入样本数量, 默认用10个
    expected_cos指定期望网络最终输出层的最小 cos 值,一般默认为0.99即可,越小时可能会设置更多层为浮点计算
    min_layer_cos指定期望每层输出 cos 的最小值,低于该值会尝试设置浮点计算, 一般默认为0.99即可
    debug_cmd指定调试命令字符串,开发使用, 默认为空
    o输出混精度量化表
  • 生成混合精度的bmodel

    model_deploy.py \
    --mlir yolov5s.mlir \
    --quantize INT8 \
    --quantize_table yolov5s_qtable \
    --calibration_table yolov5s_cali_table \
    --chip bm1684x \
    --model yolov5s_1684x_mix.bmodel

效果对比

在 TPU-MLIR 中有用 python 写好的 yolov5 用例, 源码路径 tpu-mlir/python/samples/detect_yolov5.py, 用于对图片进行目标检测。阅读该代码可以了解模型是如何使用的: 先预处理得到模型的输入, 然后推理得到输出, 最后做后处理。 用以下代码分别来验证onnx/f32/int8的执行结果。

  • onnx 模型的执行方式如下, 得到 dog_onnx.jpg:

    detect_yolov5.py \
    --input ../image/dog.jpg \
    --model ../yolov5s.onnx \
    --output dog_onnx.jpg

    dog_onnx.webp

  • f32 bmodel 的执行方式如下, 得到 dog_f32.jpg:

    detect_yolov5.py \
    --input ../image/dog.jpg \
    --model yolov5s_1684x_f32.bmodel \
    --output dog_f32.jpg

    dog_f32.webp

  • f16 bmodel 的执行方式如下, 得到 dog_f16.jpg:

    detect_yolov5.py \
    --input ../image/dog.jpg \
    --model yolov5s_1684x_f16.bmodel \
    --output dog_f16.jpg

    dog_f16.webp

  • int8 对称 bmodel 的执行方式如下, 得到 dog_int8_sym.jpg:

    detect_yolov5.py \
    --input ../image/dog.jpg \
    --model yolov5s_1684x_int8_sym.bmodel \
    --output dog_int8_sym.jpg

    dog_int8_sym.webp

  • int8 非对称 bmodel 的执行方式如下, 得到 dog_int8_asym.jpg :

    detect_yolov5.py \
    --input ../image/dog.jpg \
    --model yolov5s_1684x_int8_asym.bmodel \
    --output dog_int8_asym.jpg

    dog_int8_asym.webp

  • 混合精度 bmodel 的执行方式如下, 得到 dog_mix.jpg :

    detect_yolov5.py \
    --input ../image/dog.jpg \
    --model yolov5s_1684x_mix.bmodel \
    --output dog_fb16.jpg

    dog_mix.webp