> ## Documentation Index
> Fetch the complete documentation index at: https://dragonwingdocs-staging.qualcomm.com/llms.txt
> Use this file to discover all available pages before exploring further.

# 转换和量化 AI 模型

> 使用 SNPE 或 QNN 工具,转换和量化来自 PyTorch、TensorFlow、ONNX 或 LiteRT 的 AI 模型,以便部署到 Qualcomm 硬件。

<Tabs>
  <Tab title="Neural Processing Engine">
    ## 使用 Qualcomm Neural Processing Engine SDK 移植模型

    <Frame>
      <img src="https://mintcdn.com/qualcomm-staging/uWQLnBcS9sxlZhgB/Key-Documents/AI-Developer-Workflow/_images/snpe-model-porting-flow.png?fit=max&auto=format&n=uWQLnBcS9sxlZhgB&q=85&s=d3c3d6e6656d9226be7dd6dc830525f1" width="55%" data-path="Key-Documents/AI-Developer-Workflow/_images/snpe-model-porting-flow.png" />
    </Frame>

    ### 模型转换

    将来自 PyTorch、ONNX、TensorFlow 或 TFLite 的 32 位浮点精度预训练模型输入到 SNPE 转换器工具(`snpe-<framework>-to-dlc`),将模型转换为称为深度学习容器(DLC)的 Qualcomm 专用中间表示。

    除了来自源框架的输入模型外,转换器还需要有关输入模型的额外详情,例如输入节点名称、其对应的输入维度,以及任何输出张量名称(适用于具有多个输出的模型)。

    有关所有可配置参数,请参阅 [converters](https://docs.qualcomm.com/doc/80-63442-10/topic/SNPE_general_tools.html),或运行以下命令查看命令行帮助:

    ```shell theme={null}
    snpe-<framework>-to-dlc --help
    ```

    **输出:**

    ```
    required arguments:

    -d INPUT_NAME INPUT_DIM, --input_dim INPUT_NAME INPUT_DIM
        The names and dimensions of the network input layers specified in the format
        [input_name comma-separated-dimensions], for example:
        'data' 1,224,224,3
         Note that the quotes should always be included in order to handle special
         characters, spaces, etc.
         For multiple inputs specify multiple --input_dim on the command line like:
         --input_dim 'data1' 1,224,224,3 --input_dim 'data2' 1,50,100,3
    --out_node OUT_NAMES, --out_name OUT_NAMES
         Name of the graph's output Tensor Names. Multiple output names should be
         provided separately like:
         --out_name out_1 --out_name out_2
    --input_network INPUT_NETWORK, -i INPUT_NETWORK
         Path to the source framework model.
    ```

    <Note>
      如果您的工作环境中没有 `yaml` 包,请使用以下命令安装:

      ```shell theme={null}
      pip install pyyaml
      ```
    </Note>

    以下示例使用从 [ONNX Model Zoo](https://github.com/onnx/models/blob/main/Computer_Vision/inception_v3_Opset16_timm/inception_v3_Opset16.onnx) 下载的 ONNX 模型(*inception\_v3\_opset16.onnx*)。

    将模型以 `inception_v3.onnx` 为名下载到您的工作区。在本示例中,我们将模型下载到 `~/models` 目录。

    运行以下命令以生成 `inception_v3.dlc` 模型。

    ```shell theme={null}
    ${QAIRT_ROOT}/bin/x86_64-linux-clang/snpe-onnx-to-dlc --input_network ~/models/inception_v3.onnx --output_path ~/models/inception_v3.dlc --input_dim 'x' 1,3,299,299
    ```

    <Frame>
      <img src="https://mintcdn.com/qualcomm-staging/uWQLnBcS9sxlZhgB/Key-Documents/AI-Developer-Workflow/_images/snpe-model-conversion.png?fit=max&auto=format&n=uWQLnBcS9sxlZhgB&q=85&s=8e0652be6a3230e304572c4b0245ddde" width="55%" data-path="Key-Documents/AI-Developer-Workflow/_images/snpe-model-conversion.png" />
    </Frame>

    ### 模型量化

    要在 Hexagon Tensor Processor(HTP)上运行模型,必须对转换后的 DLC 进行量化。SNPE 提供了一个工具(`snpe-dlc-quant`),可使用其自有的量化算法将 DLC 模型量化为 INT8/INT16 DLC。有关 SNPE 量化的更多信息,请参阅 [Quantized models](https://docs.qualcomm.com/doc/80-63442-10/topic/quantized_models.html)。

    SNPE 的量化过程需要两个步骤:

    1. **量化模型内的权重和偏置。**

       权重和偏置的量化是一个静态步骤,即不需要用户提供额外的输入数据。

    2. **量化激活层(或没有权重的层)。**

       量化激活层需要一组来自训练数据集的输入图像作为校准数据。这些校准数据集图像以 `.raw` 格式的预处理图像文件列表形式输入。这些输入 `.raw` 文件的文件大小必须与模型的输入大小相匹配。

    `snpe-dlc-quant` 的输入是转换后的 DLC 模型,以及一个包含校准数据集图像路径的纯文本文件。此输入列表包含以 `.raw` 格式保存为 NumPy 数组的预处理图像的路径。预处理图像的大小必须与模型的输入分辨率相匹配。

    `snpe-dlc-quant` 工具的输出是量化后的 DLC。

    ```
    [ --input_dlc=<val> ]
                 Path to the dlc container
                 containing the model for which fixed-point encoding metadata should be generated.
                 This argument is required.
    [ --input_list=<val> ] Path to a file
                 specifying the trial inputs. This file should be a plain text file, containing one
                 or more absolute file paths per line. These files will be taken to constitute the
                 trial set. Each path is expected to point to a binary file containing one trial
                 input in the 'raw' format, ready to be consumed by the tool without any further
                 modifications. This is similar to how input is provided to snpe-net-run
                 application.
    [ --output_dlc=<val> ] Path at which the
                 metadata-included quantized model container should be written. If this argument is
                 omitted, the quantized model will be written at
                 <unquantized_model_name>_quantized.dlc.
    ```

    <Note>
      使用 [Netron](https://github.com/lutzroeder/netron) 图可视化工具来识别模型的输入/输出层维度。
    </Note>

    <Frame>
      <img src="https://mintcdn.com/qualcomm-staging/uWQLnBcS9sxlZhgB/Key-Documents/AI-Developer-Workflow/_images/snpe-model-quant-properties.png?fit=max&auto=format&n=uWQLnBcS9sxlZhgB&q=85&s=42e3a9fbda4e52e6a3244d1bf330ebf6" width="55%" data-path="Key-Documents/AI-Developer-Workflow/_images/snpe-model-quant-properties.png" />
    </Frame>

    出于演示目的,我们可以使用随机输入文件来评估量化过程。可以使用下面为 `inception_v3.onnx` 模型编写的简单 Python 脚本生成输入文件。将该脚本以 `generate_random_input.py` 为名保存在您的工作区 `~/models/` 目录中,并在主机上使用 `python ~/models/generate_random_input.py` 运行它。

    以下示例 Python 代码创建一个 input\_list,其中包含用于量化模型的校准数据集图像路径。

    ```python theme={null}
    import os
    import numpy as np

    input_path_list =[]
    BASE_PATH = "/tmp/RandomInputsForInceptionV3"

    if not os.path.exists(BASE_PATH):
        os.mkdir(BASE_PATH)

    # generate 10 random inputs and save as raw
    NUM_IMAGES = 10

    #binary files
    for img in range(NUM_IMAGES):
        filename = "input_{}.raw".format(img)
        randomTensor = np.random.random((1, 299, 299, 3)).astype(np.float32)
        filename = os.path.join(BASE_PATH, filename)
        randomTensor.tofile(filename)
        input_path_list.append(filename)

    #for saving as input_list text
    with open("input_list.txt", "w") as f:
        for path in input_path_list:
            f.write(path)
            f.write("\n")
    ```

    上述脚本生成 10 个示例输入文件,保存在 `/tmp/RandomInputsForInceptionV3/` 目录中,以及一个包含每个生成样本路径的 `input_list.txt` 文件。

    现在,`snpe-dlc-quant` 工具所需的所有输入都已就绪,可以对模型进行量化。

    ```shell theme={null}
    ${QAIRT_ROOT}/bin/x86_64-linux-clang/snpe-dlc-quant --input_dlc ~/models/inception_v3.dlc --output_dlc ~/models/inception_v3_quantized.dlc --input_list ~/models/input_list.txt
    ```

    这会生成一个量化的 inception\_v3 DLC 模型(`inception_v3_quantized.dlc`)。默认情况下,模型按 INT8 位宽量化。

    通过为 `snpe-dlc-quant` 工具指定 `--act_bitwidth 16` 和/或 `--weights_bitwidth 16` 选项,可自定义量化,使用 16 位而不是默认的 INT8。

    请参阅 [snpe-dlc-quant](https://docs.qualcomm.com/doc/80-63442-10/topic/SNPE_general_tools.html#snpe-dlc-quant) 工具文档,或运行 `snpe-dlc-quant --help` 查看所有可用的自定义项,包括量化模式、优化等。

    <Frame>
      <img src="https://mintcdn.com/qualcomm-staging/uWQLnBcS9sxlZhgB/Key-Documents/AI-Developer-Workflow/_images/snpe-model-quantization.png?fit=max&auto=format&n=uWQLnBcS9sxlZhgB&q=85&s=87f3cfed5077f20dd86921e57e8149c5" width="55%" data-path="Key-Documents/AI-Developer-Workflow/_images/snpe-model-quantization.png" />
    </Frame>

    #### 模型优化

    量化后的模型 DLC 需要一个图准备步骤,以针对在 HTP 上执行优化模型。为了让模型 DLC 能够在 HTP 上执行,SNPE 提供了 `snpe-dlc-graph-prepare` 工具,该工具以量化模型和硬件特定详情(例如芯片组)作为输入。

    <Note>
      针对 HTP 等硬件的优化取决于芯片组上存在的特定 HTP 版本。为确保将正确的优化集应用于执行图,以最优地利用 HTP,向 `snpe-dlc-graph-prepare` 工具提供正确的芯片组 ID 非常重要。
    </Note>

    根据 HTP 版本和芯片组 ID,该工具会创建一个缓存,其中包含在 HTP 硬件上执行模型 DLC 的执行策略。如果没有这一步,网络初始化期间会产生额外开销,因为 SNPE 运行时必须实时创建执行策略。

    ```shell theme={null}
    ${QAIRT_ROOT}/bin/x86_64-linux-clang/snpe-dlc-graph-prepare --input_dlc ~/models/inception_v3_quantized.dlc --output_dlc ~/models/inception_v3_quantized_with_htp_cache.dlc --htp_socs qcs6490
    ```

    <Frame>
      <img src="https://mintcdn.com/qualcomm-staging/uWQLnBcS9sxlZhgB/Key-Documents/AI-Developer-Workflow/_images/snpe-model-optimization.png?fit=max&auto=format&n=uWQLnBcS9sxlZhgB&q=85&s=fe4e4a10f04e053c67a343dafc9838f9" width="55%" data-path="Key-Documents/AI-Developer-Workflow/_images/snpe-model-optimization.png" />
    </Frame>

    #### HTP 缓存信息

    `snpe-dlc-graph-prepare` 步骤完成后,HTP 缓存记录就会添加到 DLC 中。可以使用 `snpe-dlc-info` 工具查看该缓存信息。

    ```shell theme={null}
    ${QAIRT_ROOT}/bin/x86_64-linux-clang/snpe-dlc-info -i ~/models/inception_v3_quantized_with_htp_cache.dlc
    ```

    <Frame>
      <img src="https://mintcdn.com/qualcomm-staging/uWQLnBcS9sxlZhgB/Key-Documents/AI-Developer-Workflow/_images/snpe-cache.png?fit=max&auto=format&n=uWQLnBcS9sxlZhgB&q=85&s=70c0efc69670ad73880ebeeef5943756" width="55%" data-path="Key-Documents/AI-Developer-Workflow/_images/snpe-cache.png" />
    </Frame>
  </Tab>

  <Tab title="AI Engine Direct">
    ## 使用 AI Engine Direct 移植模型

    ### 模型转换和量化

    将来自 PyTorch、ONNX、TensorFlow 或 TFLite 的预训练 FP32 模型输入到 QNN 转换器工具(`qnn-<framework>-converter`),转换为以高级可读 C++ 图形式表示的 QNN 图。

    在 HTP 上加速模型时,必须对模型进行量化。模型量化可以与转换在同一步骤中完成。执行此量化步骤进行静态量化时,必须提供校准数据集。

    要在转换的同时启用量化,请使用 `--input_list INPUT_LIST` 选项进行静态量化。

    有关更多信息,请参阅 [quantization support](https://docs.qualcomm.com/doc/80-63442-10/topic/quantization.html)。

    以下示例使用从 [ONNX Model Zoo](https://github.com/onnx/models/blob/main/Computer_Vision/inception_v3_Opset16_timm/inception_v3_Opset16.onnx) 下载的 ONNX 模型(`inception_v3_opset16.onnx`)。

    将模型以 `inception_v3.onnx` 为名下载到您的工作区。在本示例中,模型下载到 `~/models` 目录。

    #### 模型转换:CPU 后端

    要将模型转换为在基于 x86/Arm 的 CPU 上运行,请运行以下命令以生成 `inception_v3.cpp` 和 `inception_v3.bin`。

    ```shell theme={null}
    ${QAIRT_ROOT}/bin/x86_64-linux-clang/qnn-onnx-converter --input_network ~/models/inception_v3.onnx --output_path ~/models/inception_v3.cpp --input_dim 'x' 1,3,299,299
    ```

    <Frame>
      <img src="https://mintcdn.com/qualcomm-staging/uWQLnBcS9sxlZhgB/Key-Documents/AI-Developer-Workflow/_images/qnn-conversion-output.png?fit=max&auto=format&n=uWQLnBcS9sxlZhgB&q=85&s=c559f822c1266d584ba862417a2db9f6" width="55%" data-path="Key-Documents/AI-Developer-Workflow/_images/qnn-conversion-output.png" />
    </Frame>

    `inception_v3.cpp` 文件包含转换后模型的高级图表示。

    `inception_v3.bin` 文件包含模型的权重/偏置。

    #### 模型转换和量化:HTP 后端

    要在 HTP 上运行模型,需要进行量化步骤。

    在 AI Engine Direct(QNN)SDK 中进行量化时,需要向 QNN 转换器提供来自训练数据集的 50 到 200 张图像作为校准数据集。校准数据集中的图像经过预处理(缩放、归一化等)并以 `.raw` 格式保存为 NumPy 数组。这些输入 `.raw` 文件的大小必须与模型的输入大小相匹配。

    <Note>
      使用 Netron 图可视化工具来识别模型的输入/输出层维度。
    </Note>

    <Frame>
      <img src="https://mintcdn.com/qualcomm-staging/uWQLnBcS9sxlZhgB/Key-Documents/AI-Developer-Workflow/_images/qnn-conversion-model-props.png?fit=max&auto=format&n=uWQLnBcS9sxlZhgB&q=85&s=5a94dfb9295845f74d5719a7fdc4d6bc" width="55%" data-path="Key-Documents/AI-Developer-Workflow/_images/qnn-conversion-model-props.png" />
    </Frame>

    出于演示目的,您可以使用随机输入文件来评估量化过程。可以使用下面为 `inception_v3.onnx` 模型编写的 Python 脚本生成输入文件。将该脚本以 `generate_random_input.py` 为名保存在 `~/models/` 目录中,并使用 `python ~/models/generate_random_input.py` 运行它。

    以下 Python 代码创建一个 input\_list,其中包含用于量化模型的校准数据集。

    ```python theme={null}
    import os
    import numpy as np

    input_path_list =[]

    BASE_PATH = "/tmp/RandomInputsForInceptionV3"

    if not os.path.exists(BASE_PATH):
        os.mkdir(BASE_PATH)

    # generate 10 random inputs and save as raw
    NUM_IMAGES = 10

    #binary files
    for img in range(NUM_IMAGES):
        filename = "input_{}.raw".format(img)
        randomTensor = np.random.random((1, 299, 299, 3)).astype(np.float32)
        filename = os.path.join(BASE_PATH, filename)
        randomTensor.tofile(filename)
        input_path_list.append(filename)

    #for saving as input_list text
    with open("input_list.txt", "w") as f:
        for path in input_path_list:
            f.write(path)
            f.write("\n")
    ```

    运行以下命令进行转换和量化。

    默认情况下,模型按 INT8 位宽量化。您可以指定 `--act_bitwidth 16` 和/或 `--weights_bitwidth 16` 以使用 INT16 量化。

    ```shell theme={null}
    ${QAIRT_ROOT}/bin/x86_64-linux-clang/qnn-onnx-converter --input_network ~/models/inception_v3.onnx --output_path ~/models/inception_v3_quantized.cpp --input_list ~/models/input_list.txt --input_dim "x" 1,3,299,299
    ```

    这会在 `~/models/` 目录中生成 `inception_v3_quantized.cpp` 和 `inception_v3_quantized.bin` 文件。

    请参阅 [qnn-\<framework>-converter](https://docs.qualcomm.com/doc/80-63442-10/topic/general_tools.html) 或运行 `qnn-<framework>-converter --help`,查看量化的所有可用自定义项,包括量化模式、优化等。

    ### 模型编译

    转换/量化步骤完成后,使用 `qnn-model-lib-generator` 将生成的 C++ 图编译为共享对象(.so),使应用能够动态加载模型以执行推理。

    对于 x86,使用 Clang 编译器工具链将 C++ 图编译为 .so 库。对于 Linux 嵌入式设备(例如 Qualcomm Dragonwing™ RB3 Gen 2 和 IQ-9075),必须使用相应的编译器工具链(`aarch64-oe-linux-gcc11.2`)。

    #### 编译模型以在 x86 上运行

    1. 安装 GCC 12 版本的 GNU 标准 C++ 库开发包。

       ```shell theme={null}
       sudo apt install libstdc++-12-dev
       ```

       该软件包包含编译和链接 C++ 程序所需的标准库头文件(例如 `<limits>`、`<vector>` 和 `<string>`)、静态库和支持文件。

    2. 生成用于在基于 x86 的 Linux 机器上运行的共享对象模型。

       ```shell theme={null}
       ${QAIRT_ROOT}/bin/x86_64-linux-clang/qnn-model-lib-generator -c ~/models/inception_v3.cpp -b ~/models/inception_v3.bin -o ~/models/libs/ -t x86_64-linux-clang
       ```

       这会使用 Clang-14 编译器工具链将 C++ 图编译为与 x86 主机兼容的 QNN 模型 `.so`,并生成 `inception_v3.so`。

    <Frame>
      <img src="https://mintcdn.com/qualcomm-staging/uWQLnBcS9sxlZhgB/Key-Documents/AI-Developer-Workflow/_images/qnn-port-x86.png?fit=max&auto=format&n=uWQLnBcS9sxlZhgB&q=85&s=4e3b8df4c7890839d270b65a3aac960d" width="55%" data-path="Key-Documents/AI-Developer-Workflow/_images/qnn-port-x86.png" />
    </Frame>

    #### 编译模型以在目标设备上运行

    在为设备端执行(aarch64 架构)编译模型时,务必使用正确的交叉编译工具链,以确保编译出的共享对象(.so)与设备操作系统兼容。

    以下步骤安装将模型 cpp 文件编译为 .so 库所需的交叉编译工具链。有关安装相应交叉编译工具链的说明,请参阅 [Download and install the Platform SDK](https://imsdkdocs.qualcomm.com/advanced/yocto-build#download-and-install-the-sdk)。

    在新的命令行终端中安装平台 SDK 并设置好交叉编译环境之后。

    1. 检查环境是否已正确设置。

       ```shell theme={null}
       echo $SDKTARGETSYSROOT
       ```

       ```shell theme={null}
       echo $TARGET_PREFIX
       ```

       如果上述环境变量未被填充,请在新的命令行终端中重复步骤 1。

    2. 设置 QAIRT 环境。

       ```shell theme={null}
       source ${QAIRT_ROOT}/bin/envsetup.sh
       ```

    #### 编译模型以在基于 Arm 的 CPU 上运行

    交叉编译器设置完成后,使用以下命令在 `~/model/libs/aarch64-oe-linux-gcc11.2` 中生成 `libinception_v3.so`。通过命令行参数将此位置提供给 `qnn-model-lib-generator` 工具。

    <Note>
      此处使用的编译器工具链为 `aarch64-oe-linux-gcc11.2`。
    </Note>

    ```shell theme={null}
    ${QAIRT_ROOT}/bin/x86_64-linux-clang/qnn-model-lib-generator -c ~/models/inception_v3.cpp -b ~/models/inception_v3.bin -o ~/models/libs -t aarch64-oe-linux-gcc11.2
    ```

    #### 编译模型以在 HTP 上运行

    要在 HTP 上运行模型,以下命令会在 `~/models/libs/aarch64-oe-linux-gcc11.2` 中生成 `libinception_v3_quantized.so`。

    <Note>
      此处使用的编译器工具链为 `aarch64-oe-linux-gcc11.2`。
    </Note>

    ```shell theme={null}
    ${QAIRT_ROOT}/bin/x86_64-linux-clang/qnn-model-lib-generator -c ~/models/inception_v3_quantized.cpp -b ~/models/inception_v3_quantized.bin -o ~/models/libs/ -t aarch64-oe-linux-gcc11.2
    ```
  </Tab>
</Tabs>
