我已使用提供的工具将模型从 Huggingface 转换为 Onnx:
optimum-cli export onnx --model deepset/roberta-base-squad2 "roberta-base-squad2" --framework pt
转换完成,没有错误。
我用下面的代码来进行推断:
// QnA Service Configuration:
// Site: https://huggingface.co/deepset/roberta-base-squad2
Configuration QnAConfig = new Configuration(@"C:\Bert\dslimL\model.onnx")
{
ConfigurationFileName = "config.json",
HasTokenTypeIds = false,
IsCasedModel = false,
MaximumNumberOfTokens = 1,
MergesFileName = "merges.txt",
NumberOfTokens = 5,
Repository = "deepset/roberta-large-squad2",
TokenizerName = TokenizerName.Tokenizer,
VocabularyFileName = "vocab.json"
};
Configuration = QnAConfig;
labelsCount = Configuration.ModelConfiguration.IdTolabel.Count;
var sessionOptions = new SessionOptions()
{
ExecutionMode = ExecutionMode.ORT_PARALLEL,
EnableCpuMemArena = true,
EnableMemoryPattern = true,
EnableProfiling = true,
GraphOptimizationLevel = GraphOptimizationLevel.ORT_ENABLE_ALL,
InterOpNumThreads = 10
};
sessionOptions.AppendExecutionProvider_CPU(0);
Session = new InferenceSession(Configuration.ModelPath, sessionOptions);
// Set Question and Context:
Schema.Question = sentence;
Schema.Context = Context;
// Process SubContext:
Schema.Sentence = $"'question': '{sentence}',"
+ $" 'context': '{Context}'";
//
var Start = Configuration.Tokenizer.Model.TokenToId("<s>");
var End = Configuration.Tokenizer.Model.TokenToId("</s>");
var Pad = Configuration.Tokenizer.Model.TokenToId("<pad>");
//
var result = Configuration.Tokenizer.Encode(Schema.Sentence);
var decode = Configuration.Tokenizer.Decode(result.Ids);
//
var inputArray = result.Ids.ToLongArray((long)Start, (long)End);
var MyAttentionMask = AttentionMaskHelpers.BuildMask(20, 20, -0);
//
long[] attMask = new long[inputArray.Length];
for (int i = 0; i < inputArray.Length; i++)
if (i < inputArray.Length * 0.5)
attMask[i] = 1;
else
attMask[i] = 0;
//
var tensorInputIds = TensorExtensions.ConvertToTensor(inputArray, inputArray.Length);
var attention_Mask = TensorExtensions.ConvertToTensor(attMask, inputArray.Length);
var inputs = new List<NamedOnnxValue>
{
NamedOnnxValue.CreateFromTensor("input_ids", tensorInputIds),
NamedOnnxValue.CreateFromTensor("attention_mask", attention_Mask),
//NamedOnnxValue.CreateFromTensor("token_type_ids", attention_Mask)
};
////////////////////////////////////////////////////////////////////////////////////////
/// # Convert the answer (tokens) back to the original text
/// # Score: score from the model
/// # Start: Index of the first character of the answer in the context string
/// # End: Index of the character following the last character of the answer in the context string
/// # Answer: Plain text of the answer
/// See: https://github.com/huggingface/transformers/blob/main/src/transformers/pipelines/question_answering.py
/// Run the Session, infering an Output:
var inputMeta = Session.InputMetadata;
var output = Session.Run(inputs);
// Init a new Answer Id List:
List<int> AnswerIds = new List<int>();
// The Output Logits: new List<float>(); //
List<float> startLogits = output[0].AsEnumerable<float>().ToList();
List<float> endLogits = output[1].AsEnumerable<float>().ToList();
// Get Indexes of the Context:
float start = startLogits.Max();
float end = endLogits.Max();
Schema.Score = ((start + end) / 10.0f);
// Get Indexes of the top scores:
Schema.StartIndex = startLogits.IndexOf(start);
Schema.EndIndex = endLogits.IndexOf(end);
// Tokenise the Sentence:
TokenizerResult Tokens = Configuration.Tokenizer.Encode(Schema.Sentence);
// Get the List of Ids:
for (int i = Schema.StartIndex; i <= Schema.EndIndex; i++)
AnswerIds.Add(Convert.ToInt32(inputArray[i]));
// Get the Answer:
Schema.Answer = Configuration.Tokenizer.Decode(AnswerIds).Trim();
我正在使用:
using Microsoft.ML.Tokenizers;
分词器的工作原理:
Tokenizer = new Tokenizer(new EnglishRoberta(vocabFilePath, mergeFilePath, dictPath), RobertaPreTokenizer.Instance);
我已经检查了令牌和 ID,它们是匹配的,因此令牌化过程很好。
问题:所有预测都会导致开始索引和结束索引为零索引,这给了我一个开始标记结果,因此如果开始标记是“”,那么即使分数是好还是坏,结果也是“”。
模型使用 PY 脚本在 Python 中运行良好,没有错误!
from transformers import AutoModelForQuestionAnswering, AutoTokenizer, pipeline
model_name = "deepset/roberta-base-squad2"
model = AutoModelForQuestionAnswering.from_pretrained(model_name)
tokenizer = AutoTokenizer.from_pretrained(model_name)
nlp = pipeline('question-answering', model=model_name, tokenizer=model_name)
QA_input = {
'question': 'Why is model conversion important?',
'context': 'The option to convert models between FARM and transformers gives freedom to the user and let people easily switch between frameworks.'
}
res = nlp(QA_input)
print(res)
我相信这个问题与 Onnx 和 Onnxruntime 环境直接相关,除非我做错了什么。但是,我还有其他模型使用类似的代码。
我尝试过其他型号:
所有型号都有同样的问题。
我相信 onnxruntime 的 bug 比大多数人愿意承认的还要多,真是耻辱!
您似乎在使用从 Hugging Face 模型转换而来的 ONNX 模型进行推理时遇到了问题。以下一些建议可能可以帮助您排除故障并可能解决问题: 输入格式:确保提供给 ONNX 模型的输入格式与模型期望的输入格式匹配。检查输入 ID 和注意掩码的格式是否正确并符合模型的输入要求。输出解析:验证您是否正确解析 ONNX 模型的输出。检查输出张量是否包含答案范围的开始和结束位置的预期 logits 或分数。会话初始化:仔细检查 ONNX 推理会话的初始化。确保针对您的环境正确配置所有会话选项和执行提供程序。模型兼容性:确认 ONNX 转换过程成功,并且生成的 ONNX 模型与您正在使用的 ONNX 运行时版本兼容。某些模型或操作可能不完全支持,或者可能需要额外的配置。调试:添加打印语句或日志记录以在推理过程中检查中间变量和输出。这可以帮助识别输入或输出数据中的任何意外行为或不一致。 ONNX 运行时版本:确保您使用的 ONNX 运行时版本与转换后的 ONNX 模型兼容。更新或降级 ONNX 运行时版本可能会解决兼容性问题。模型评估:考虑使用其他推理框架或工具评估 ONNX 模型,以在当前环境之外验证其性能和正确性。这可以帮助确定问题是特定于 ONNX 运行时还是与模型本身相关。社区支持:从 ONNX 或 Hugging Face 社区论坛或 GitHub 存储库寻求帮助。其他用户可能也遇到过类似的问题,可以根据他们的经验提供指导或解决方案。 🤔