z
zkx_/tinyroberta-squad2-ascend
模型介绍文件和版本Pull Requests讨论分析
下载使用量0

deepset/tinyroberta-squad2 on Ascend NPU

1. 简介

本文档记录 deepset/tinyroberta-squad2 轻量级抽取式问答模型在昇腾 NPU(Ascend 910B3)上的迁移适配、精度评测与性能验证结果。

tinyroberta-squad2 是 deepset 推出的知识蒸馏版 RoBERTa,在 SQuAD 2.0 数据集上微调用于抽取式问答(extractive QA)。该模型将 RoBERTa-base 通过蒸馏压缩至 6 层(参数量从 125M 降至 82M),在保持较高问答精度的同时大幅提升推理速度。模型输入为 (question, context) 文本对,输出 start/end 位置 logits,通过 argmax 确定答案在 context 中的起止位置。

SQuAD 2.0 相比 1.1 增加了不可回答问题的处理,模型能够判断 context 中是否包含答案。

相关获取地址:

  • 权重下载地址(HuggingFace):https://huggingface.co/deepset/tinyroberta-squad2

2. 验证环境

组件版本
torch2.8.0
torch_npu2.8.0.post4
transformers5.8.1
CANN8.5.1
  • NPU:8 × Ascend 910B3
  • 精度对比基准:CPU(x86, PyTorch 2.8.0)

3. 部署使用流程

3.1 环境准备

conda create -n tinyroberta-squad2 python=3.11 -y
conda activate tinyroberta-squad2

pip install torch==2.8.0 torch_npu==2.8.0.post4 \
    -i https://pypi.tuna.tsinghua.edu.cn/simple
pip install transformers numpy \
    -i https://pypi.tuna.tsinghua.edu.cn/simple

3.2 推理脚本使用

python inference.py \
    --question "What is the capital of France?" \
    --context "Paris is the capital and most populous city of France." \
    --device npu

编程接口:

from inference import QAModel

qa = QAModel(model_path="./tinyroberta-squad2", device="npu")
results = qa.answer(
    questions=["What is the capital of France?"],
    contexts=["Paris is the capital and most populous city of France."]
)
# results[0] → {"answer": "Paris", "score": 15.2}

4. Smoke 验证

python inference.py \
    --question "What is AI?" \
    --context "Artificial intelligence is the simulation of human intelligence." \
    --device npu

预期输出:从 context 中抽取的答案文本及置信度分数,无运行时错误。

5. 性能参考

测试条件:10 对 question-context 样本(平均 context 长度约 30 tokens),batch_size=8,NPU 预热 1 轮。

指标数值
CPU 吞吐量34.0 Q/s
NPU 吞吐量127.0 Q/s
CPU/NPU 加速比3.7 ×

问答模型的加速比(3.7×)低于嵌入/分类模型,主要原因:不同样本 context 长度差异导致 batch 内大量 padding,以及每条样本的 token 序列长度不固定使 NPU 并行效率受限。实际部署中可通过按长度分组(bucketing)优化。

6. 精度评测

6.1 评测方法

分别在 CPU 和 NPU 上对 10 对 question-context 样本推理,比较 start_logits 和 end_logits 的拼接向量(flattened)余弦相似度和 MAE。start/end logits 决定了答案片段的选取,其一致性是 QA 模型精度的关键。

6.2 评测结果

指标数值
平均余弦相似度(start+end)1.000000
精度误差率0.0000%

结论:精度误差率 0.0000%,NPU 与 CPU 输出的 start/end logits 完全一致,评测通过。

7. 迁移适配说明

7.1 模型结构

  • Backbone:RobertaModel(6 层蒸馏版本,768 维,RoBERTa 知识蒸馏)
  • QA Head:两个并列线性层(768 → seq_len),分别预测 start 位置和 end 位置 logits
  • Tokenizer:BPE(Byte-Pair Encoding),使用 merges.txt + vocab.json
  • 参数量:82M(RoBERTa-base 蒸馏至 6 层,约为原版的 2/3)

7.2 适配要点

  1. AutoModelForQuestionAnswering.from_pretrained() 加载,model.to("npu:0") 迁移
  2. 输入 (question, context) 通过 tokenizer 拼接,question 在前、context 在后
  3. 分别对 start_logits 和 end_logits 取 argmax,找到答案的起止 token 位置
  4. 通过 tokenizer.decode(ids[start:end+1]) 提取答案文本
  5. 不同样本 token 长度不同,批量推理需 padding;可变长度 logits 在评测中逐样本展平比较

7.3 关键代码

import torch, torch_npu
from transformers import AutoModelForQuestionAnswering, AutoTokenizer

model = AutoModelForQuestionAnswering.from_pretrained(
    "tinyroberta-squad2"
).to("npu:0")
tokenizer = AutoTokenizer.from_pretrained("tinyroberta-squad2")

question = "What is AI?"
context = "AI is artificial intelligence."
inputs = tokenizer(question, context, return_tensors="pt", truncation=True)
inputs = {k: v.to("npu:0") for k, v in inputs.items()}

with torch.no_grad():
    outputs = model(**inputs)
    start_idx = torch.argmax(outputs.start_logits, dim=1)
    end_idx = torch.argmax(outputs.end_logits, dim=1)
    answer = tokenizer.decode(
        inputs["input_ids"][0][start_idx:end_idx+1],
        skip_special_tokens=True
    )

8. 注意事项

  1. 可变长度输入:不同 question-context 对的 token 长度差异显著,批量推理时 padding 会引入计算浪费。高吞吐场景建议按长度分桶
  2. SQuAD 2.0 特性:模型支持判断不可回答问题(no answer),当最佳答案的分数低于阈值时返回空字符串
  3. tiny 蒸馏模型:6 层 RoBERTa(vs 12 层 base),推理速度快约 2×,精度仅略低于 base 版本(F1 约降 1-2 个点)
  4. context 长度限制:RoBERTa max_position_embeddings=514,长 context 需截断或分块处理
  5. BPE tokenizer:空格前缀处理(Ġ)是 RoBERTa tokenizer 的特征,解码时建议使用 skip_special_tokens=True