本文档记录 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 中是否包含答案。
相关获取地址:
| 组件 | 版本 |
|---|---|
torch | 2.8.0 |
torch_npu | 2.8.0.post4 |
transformers | 5.8.1 |
CANN | 8.5.1 |
8 × Ascend 910B3conda 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/simplepython 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}python inference.py \
--question "What is AI?" \
--context "Artificial intelligence is the simulation of human intelligence." \
--device npu预期输出:从 context 中抽取的答案文本及置信度分数,无运行时错误。
测试条件: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)优化。
分别在 CPU 和 NPU 上对 10 对 question-context 样本推理,比较 start_logits 和 end_logits 的拼接向量(flattened)余弦相似度和 MAE。start/end logits 决定了答案片段的选取,其一致性是 QA 模型精度的关键。
| 指标 | 数值 |
|---|---|
| 平均余弦相似度(start+end) | 1.000000 |
| 精度误差率 | 0.0000% |
结论:精度误差率 0.0000%,NPU 与 CPU 输出的 start/end logits 完全一致,评测通过。
AutoModelForQuestionAnswering.from_pretrained() 加载,model.to("npu:0") 迁移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
)skip_special_tokens=True