# Bert 部署示例

该示例使用 [ModelTC/bert-base-uncased-cola](https://huggingface.co/ModelTC/bert-base-uncased-cola) 权重。

整体步骤如下：

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

**目录**

- [Bert 部署示例](#bert-部署示例)
  - [0. 模型与数据集下载](#0-模型与数据集下载)
  - [1. 模型转换](#1-模型转换)
  - [2. 模型量化](#2-模型量化)
  - [3. 模型编译](#3-模型编译)
  - [4. 模型测试](#4-模型测试)
    - [4.1 精度测试](#41-精度测试)
    - [4.2 性能测试](#42-性能测试)

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

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

1. [ONNX 模型](https://modelzoo.oss-cn-shenzhen.aliyuncs.com/onnxs/bert.onnx)
2. [量化后的 sg](https://modelzoo.oss-cn-shenzhen.aliyuncs.com/sgs/bert_8bit.sg)
3. [rbo](https://modelzoo.oss-cn-shenzhen.aliyuncs.com/rbos/bert.rbo)

数据集使用 huggingface 在线下载，安装 huggingface 依赖：

```shell
# 配置 hugging face 镜像
$ export HF_ENDPOINT=https://hf-mirror.com
$ pip install transformers==4.51.3 datasets==3.5.1
```

## 1. 模型转换

首先我们需要使用 `export_onnx.py` 脚本导出 onnx 模型:

```shell
$ mkdir outputs
$ python export_onnx.py outputs/bert.onnx
```

导出 sg：

```shell
$ rbcc parse --onnx outputs/bert.onnx --sg outputs/bert.sg
The version of rbcc installed is 1.2.0
2025-04-24 17:26:30 - RBCC - INFO - Start parse 'outputs/bert.onnx' onnx model.
2025-04-24 17:26:46 - RBCC - INFO - ONNX model parsed successfully.
2025-04-24 17:26:46 - RBCC - INFO - Model's input  0: name=attention_mask, shape=[1, 128], dtype=int64.
2025-04-24 17:26:46 - RBCC - INFO - Model's input  1: name=input_id, shape=[1, 128], dtype=int64.
2025-04-24 17:26:46 - RBCC - INFO - Model's output 0: name=1430, shape=[1, 2], dtype=float32.
SG IR saved in outputs/bert.sg
```

> Bert 模型有两个输入，我们需要记住这两个输入的名称，后续量化和编译时需要使用。

## 2. 模型量化

在量化操作之前，我们需要从训练数据集中随机抽取 100 至 200 个样本，作为量化校准数据集。量化数据集从 [nyu-mll/glue](https://huggingface.co/datasets/nyu-mll/glue) 中选择 cola 数据集的 train 数据集中抽取 100 个数据作为量化数据集。

量化步骤如下：

```shell
$ python quantize_sg.py outputs/bert.sg
Quantize Calibration - Histogram: 100%|████████████████████████████████████| 100/100 [01:30<00:00,  1.10sample/s]
100it [01:52,  1.12s/it]
```

> bert 模型量化时需要指定残差连接（shortcut）不量化，以保证模型量化精度损失在可接受范围内，在 SG-IR 中，残差连接是 `Eltwise` 算子，我们通过传入 `qconfig` 参数指定，具体用法请参考 rbcc 手册量化部分使用文档。

当我们的 sg 是多输入模型时，需要通过 `inputs=['input_id', 'attention_mask']` 指定多输入的顺序，此顺序与返回的量化校准数据集的输入顺序保持一致。

## 3. 模型编译

获得量化的 sg 后，使用 `rbcc gen` 即可编译模型生成 rbo：

```shell
$ rbcc gen --sg outputs/bert_8bit.sg --inputs input_id,attention_mask --rbo outputs/bert.rbo
The version of rbcc installed is 1.2.0
2025-04-29 11:08:55 - RBCC - INFO - Start loading 'outputs/bert_8bit.sg'.
2025-04-29 11:08:55 - RBCC - INFO - Loading sg end.
2025-04-29 11:08:55 - RBCC - INFO - Start compiling the model and generate rbo.
2025-04-29 11:09:32 - RBCC - INFO - Compilation is completed, rbo has been saved to 'outputs/bert.rbo'
```

当我们的 sg 是多输入模型时，编译时需要通过 `--inputs input_id,attention_mask` 指定多输入的顺序，后续 rbo 的输入也和此时指定的顺序一致。

## 4. 模型测试

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

### 4.1 精度测试

| Model       | DataSet          |  dtype  | matthews_corrcoef |
| ----------- | ---------------- | ------- | ----------------- |
| Bert        | nyu-mll/glue     |  fp32   | 59.604            |
| Bert-sg     | nyu-mll/glue     |  uint8  | 58.914            |
| Bert-rbo    | nyu-mll/glue     |  uint8  | 58.803            |

该模型使用 nyu-mll/glue 数据集 cola 子集进行精度评估。

评估方式如下：

```shell
# 把 rbo scp 到 430 系列盒子上
$ scp outputs/bert.rbo root@192.168.12.169:/data/
$ python eval_acc.py /data/bert.rbo --device-id 0
INFO: Init Runner.
INFO: Load model from /data/bert.rbo
Model uploaded successfully. Model ID: 219cac87335b411b37427c8668a14ef6
INFO: Load dataset.
INFO: Start inference.
Eval bert on cola: 1043img [01:06, 15.58img/s]
INFO: matthews_corrcoef: 58.803
```

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

```shell
$ python eval_acc.py outputs/bert.sg --device-id 0
INFO: Init Runner.
INFO: Load model from outputs/bert.sg
INFO: Load dataset.
INFO: Start inference.
Eval bert on cola: 1043img [01:58,  8.77img/s]
INFO: matthews_corrcoef: 59.604
```

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

### 4.2 性能测试

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