You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

HuggingFace RoBERTa模型转ONNX后推理起止索引全为0的问题

RoBERTa-SQuAD2 ONNX模型C#推理输出空答案的排查方案

1. 先确认ONNX模型导出是否正确

用optimum-cli转Squad任务的RoBERTa时,必须指定任务类型,不然导出的模型可能没正确生成start/end logits节点。

  • 正确的导出命令要加--task question-answering:
    optimum-cli export onnx --model deepset/roberta-base-squad2 --task question-answering ./roberta-onnx
    
  • 导出后用Netron打开模型,检查输出节点里有没有start_logits和end_logits,且维度是[batch_size, sequence_length],少一个都不行。

2. 核对C#里的ONNX输入格式

RoBERTa的输入要求很严,这几点必须盯死:

  • 输入名称:模型输入节点名一般是input_ids、attention_mask,部分模型可能要token_type_ids,要和ONNX模型里的输入名完全一致,别拼错。
  • 数据类型:input_ids和attention_mask必须是int64类型,用int32的话输出直接乱掉。
  • 张量形状:输入的batch和序列长度要匹配模型预期,比如动态batch的话,输入形状得是[1, 实际分词长度],不能随便填固定值。

3. 检查分词的特殊Token和拼接格式

RoBERTa分词必须带<s>和</s>,而且问题和上下文的拼接格式不能错:

  • 正确拼接:<s> 问题 </s></s> 上下文 </s>
  • 用Microsoft.ML.Tokenizers分词时,得确认自动加了这些特殊Token,同时attention_mask要把padding的位置标0,有效Token标1,别搞反。

4. 修正输出索引的计算逻辑

C#里解析ONNX输出时,别直接取第一个元素,要对整个序列的logits取最大值对应的索引:

// 示例:从start_logits数组里找最大值的索引
int startIndex = Array.IndexOf(startLogits, startLogits.Max());
int endIndex = Array.IndexOf(endLogits, endLogits.Max());

另外要注意,索引是对应整个拼接后的序列,得确保索引落在上下文的Token范围内,别跑到问题的Token里去了。

5. 交叉验证Python和C#的输入输出

把C#里分词得到的input_ids、attention_mask复制到Python,用同一个ONNX模型跑推理:

  • 如果Python用ONNX Runtime跑结果正常,那就是C#的ONNX调用或输入处理有问题;
  • 如果Python跑出来也是start/end为0,那肯定是模型导出的问题,重新用正确命令导出一遍。

内容的提问来源于stack exchange,提问作者Rusty Nail

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.28 10:55:07