# CLIP 部署示例

该示例来自 [CLIP](https://github.com/openai/CLIP) 项目, 权重使用的是 [ViT-B-16.pt](https://openaipublic.azureedge.net/clip/models/5806e77cd80f8b59890b7e101eabd078d9fb84e6937f9e85e4ecb61988df416f/ViT-B-16.pt)。

整体步骤如下：

1. 把 ONNX 模型转换成 SG-IR(以下简称 sg 文件)，用于后续步骤的量化和编译。
2. 准备量化校准数据集，使用 rbcc 量化 sg 得到量化后的 sg。
3. 使用 rbcc 对量化后的 sg 进行编译，生成可在 CAISA 芯片上执行的 rbo 文件。
4. 对 rbo 进行性能测试和精度测试。

**目录**

- [CLIP 部署示例](#clip-部署示例)
  - [0. 模型与数据集下载](#0-模型与数据集下载)
  - [1. 模型转换](#1-模型转换)
  - [2. 模型量化](#2-模型量化)
    - [2.1 命令行方式量化](#21-命令行方式量化)
  - [3. 模型编译](#3-模型编译)
  - [4. 模型测试](#4-模型测试)
    - [4.1 精度测试](#41-精度测试)
    - [4.2 性能测试](#42-性能测试)

## 0. 模型与数据集下载

为了快速体验 CAISA 430 芯片，我们预先提供了预编译好的 sg、onnx 和 rbo 文件，您可选择快速从任一步骤开始。

1. [量化校准和测试数据集](https://modelzoo.oss-cn-shenzhen.aliyuncs.com/datasets/cifar100.zip)
2. [Vision ONNX 模型](https://modelzoo.oss-cn-shenzhen.aliyuncs.com/onnxs/clip_vision.onnx)
3. [Text ONNX 模型](https://modelzoo.oss-cn-shenzhen.aliyuncs.com/onnxs/clip_text.onnx)
4. [量化后的 vision sg](https://modelzoo.oss-cn-shenzhen.aliyuncs.com/sgs/clip_vision_8bit.sg)
5. [量化后的 text sg](https://modelzoo.oss-cn-shenzhen.aliyuncs.com/sgs/clip_text_8bit.sg)
6. [vison rbo](https://modelzoo.oss-cn-shenzhen.aliyuncs.com/rbos/clip_vision.rbo)
7. [text rbo](https://modelzoo.oss-cn-shenzhen.aliyuncs.com/rbos/clip_text.rbo)

## 1. 模型转换

因为导出 onnx 需要使用 cifar100 数据集，所以我们需要提前下载 cifar100.zip，并解压到当前目录下：

导出 onnx：

```shell
$ git clone https://github.com/openai/CLIP.git
$ cd CLIP
$ pip install -e .
$ mkdir outputs
$ python export_onnx.py ./outputs
```

导出 sg：

```shell
$ rbcc parse --onnx outputs/clip_text.onnx --sg outputs/clip_text.sg 
The version of rbcc installed is 1.2.0
2025-04-28 10:03:07 - RBCC - INFO - Start parse 'outputs/clip_text.onnx' onnx model.
2025-04-28 10:03:28 - RBCC - INFO - ONNX model parsed successfully.
2025-04-28 10:03:28 - RBCC - INFO - Model's input  0: name=input_1, shape=[1, 77], dtype=int32.
2025-04-28 10:03:28 - RBCC - INFO - Model's output 0: name=2192, shape=[1, 512], dtype=float32.
SG IR saved in outputs/clip_text.sg

$ rbcc parse --onnx outputs/clip_vision.onnx --sg outputs/clip_vision.sg 
The version of rbcc installed is 1.2.0
2025-04-28 10:04:03 - RBCC - INFO - Start parse 'outputs/clip_vision.onnx' onnx model.
2025-04-28 10:04:25 - RBCC - INFO - ONNX model parsed successfully.
2025-04-28 10:04:25 - RBCC - INFO - Model's input  0: name=input_1, shape=[1, 224, 224, 3], dtype=float32.
2025-04-28 10:04:25 - RBCC - INFO - Model's output 0: name=2022, shape=[1, 512], dtype=float32.
SG IR saved in outputs/clip_vision.sg
```

> 注：rbcc parse 命令行默认会对输入 [Batch, Channel, Height, Width] 转换成 [Batch, Height, Width, Channel] 格式。

## 2. 模型量化

在量化操作之前，我们需要从训练数据集中随机抽取 100 至 200 个样本，作为量化校准数据集。并且我们提供了两种量化方法供用户选择：命令行方式和 Python API 接口。您可以根据实际需求灵活选择适合的方式完成对 sg 的量化操作。在进行量化前请先在[模型与数据集下载](#0-模型与数据集下载)中下载数据集。

### 2.1 命令行方式量化

对数据集 `cifar100.zip` 解压，使用 [convert_quantset.py](./convert_quantset.py) 脚本对其进行处理，该脚本负责把输入图像经过模型预处理操作，最后保存成 numpy 的 `.npy` 文件格式。使用方式如下：

```shell
unzip cifar100.zip
python convert_quantset_text.py ./cifar100 outputs/Text_Quantization_100_npy
python convert_quantset_vision.py ./cifar100 outputs/Vision_Quantization_100_npy
```

然后使用 `rbcc quantize` 命令分别对 `clip_text.sg` 和 `clip_vision` 进行量化：

```shell
$ rbcc quantize outputs/clip_text.sg --data-dir outputs/Text_Quantization_100_npy --gpu-id 0 --qconfig text_qconfig.json --smooth-alpha 0.5
The version of rbcc installed is 1.2.0
Quantize Calibration - MinMax: 100%|███████████████████████████████████████| 100/100 [00:24<00:00,  4.01sample/s]
SG IR saved in outputs/clip_text_8bit.sg
```

针对 text 部分量化损失大的问题，我们使用了全 16-bit 量化。

```shell
$ rbcc quantize outputs/clip_vision.sg --data-dir outputs/Vision_Quantization_100_npy --gpu-id 0 --qconfig vision_qconfig.json --smooth-alpha 0.6
The version of rbcc installed is 1.2.0
Quantize Calibration - Histogram: 100%|█████████████████████████████████████| 100/100 [00:18<00:00,  5.46sample/s]
SG IR saved in outputs/clip_vision_8bit.sg
```

vision 部分我们采用混合量化的方式，针对模型中损失较为大的层采用 16-bit 量化，其他层保持 8-bit 量化。

> --gpu-id 0 指定使用第 0 块 GPU 对量化进行加速，如果您的环境是无 GPU 环境，不指定 --gpu-id 或指定 -1 即可。

## 3. 模型编译

获得量化后的 sg 后，使用 `rbcc gen` 即可快速完成 rbo 编译：

```shell
$ rbcc gen --sg outputs/clip_text_8bit.sg --rbo outputs/clip_text.rbo
The version of rbcc installed is 1.2.0
2025-04-29 15:19:19 - RBCC - INFO - Start loading 'outputs/clip_text_8bit.sg'.
2025-04-29 15:19:20 - RBCC - INFO - Loading sg end.
2025-04-29 15:19:20 - RBCC - INFO - Start compiling the model and generate rbo.
2025-04-29 15:19:49 - RBCC - INFO - Compilation is completed, rbo has been saved to 'outputs/clip_text.rbo'.
```

```shell
$ rbcc gen --sg outputs/clip_vision_8bit.sg --rbo outputs/clip_vision.rbo
The version of rbcc installed is 1.2.0
2025-04-29 15:20:01 - RBCC - INFO - Start loading 'outputs/clip_vision_8bit.sg'.
2025-04-29 15:20:01 - RBCC - INFO - Loading sg end.
2025-04-29 15:20:01 - RBCC - INFO - Start compiling the model and generate rbo.
2025-04-29 15:20:26 - RBCC - INFO - Compilation is completed, rbo has been saved to 'outputs/clip_vision.rbo'.
```

## 4. 模型测试

成功编译生成 rbo 后，我们需要在 CAISA 430 芯片上进行精度测试和性能测试。以下精度评估使用了远程调用的方式，环境准备参考 [rbo 远程调用](../rbo_exe.md)。

### 4.1 精度测试

| Model     | DataSet    | dtype       |  Acc@Top1  | Acc@Top5   |
| -------   | ---------- | ----------- | ---------- | ---------- |
| CLIP      | CIFAR100   | fp32        | 68.44      | 90.02      |
| CLIP-sg   | CIFAR100   | uint-8&16   | 68.07      | 90.24      |
| CLIP-rbo  | CIFAR100   | uint-8&16   | 67.89      | 90.22      |

该模型使用 cifar100 数据集进行精度评估，请先在[模型与数据集下载](#0-模型与数据集下载)中下载测试数据集，测试集结构如下：

```shell
└── cifar100
    ├── bpe_simple_vocab_16e6.txt.gz     # clip 模型字典
    └── cifar-100-python                 # cifar100 测试数据
```

评估方式如下：

```shell
# scp rbo 到硬件设备上
$ scp outputs/*.rbo root@192.168.12.169:/data/
$ python eval_acc.py /data/clip_vision.rbo /data/clip_text.rbo --data ./cifar100 --device-id 0
INFO: Init Runner.
INFO: Load model from /data/clip_text.rbo
Model uploaded successfully. Model ID: f074903899517fb4c68f87952a76964a
INFO: Load model from /data/clip_vision.rbo
Model uploaded successfully. Model ID: ad729cbf1e9fbc75a27c84e147fd9ff2
INFO: Load preprocess.
INFO: Load dataset.
INFO: Start inference.
Encoding CIFAR100 Label: 100%|████████████████████████████████████████████████████| 100/100 [00:12<00:00,  8.18it/s]
Eval in CIFAR-100: 100%|██████████████████████████████████████████████████████████| 10000/10000 [42:05<00:00,  3.96img/s]
Top1-Acc: 67.89, Top5-Acc: 90.22
```

> 评估前，确保 clip_text.rbo 和 clip_vision.rbo 已经 scp 到 430 系列盒子上的相同目录下，并且容器是可以访问到的路径。

参数介绍：

- `--data`：cifar100 数据集文件夹路径。
- `--device-id`：输入为 rbo 时，表示指定 CAISA 430 芯片引擎 id，它默认有 2 个引擎，分别使用 0 和 1 表示。输入为 sg 时，表示指定 GPU 设备 id，cpu 推理请指定 -1。

若 rbo 精度相比原浮点模型精度下降过多，无法确定具体原因时，我们建议先测试 sg，它作为 rbo 的编译输入，它的结果也至关重要，sg 精度测试方式如下：

```shell
$ python eval_acc.py outputs/clip_vision_8bit.sg outputs/clip_text_8bit.sg --data ./cifar100 --device-id 0
INFO: Init Runner.
INFO: Load model from outputs/clip_text_8bit.sg
INFO: Load model from outputs/clip_vision_8bit.sg
INFO: Load preprocess.
INFO: Load dataset.
INFO: Start inference.
Encoding CIFAR100 Label: 100%|████████████████████████████████████████| 100/100 [00:18<00:00,  5.49it/s]
Eval in CIFAR-100: 100%|██████████████████████████████████████████████| 10000/10000 [08:58<00:00, 18.56img/s]
Top1-Acc: 68.07, Top5-Acc: 90.24
```

> sg 使用 Pytorch 作为运行后端，并模拟量化计算过程，故其精度和 rbo 精度会有些许区别，这属于正常现象。

### 4.2 性能测试

参考 [rbo 性能测试](../rbo_perf.md)