Android端ONNX sklearn模型仅返回类别标签,如何获取置信度?
问题排查与解决方案
一、先排查模型转换环节的问题
1. 检查转换代码的参数配置是否正确
sklearn转ONNX时,仅加zipmap参数不够,必须指定output_scores=True才能让模型输出概率分数。正确的转换配置应该是这样:
from skl2onnx import convert_sklearn from skl2onnx.common.data_types import FloatTensorType # 假设clf是你的训练好的分类器,n_features是输入特征数 initial_type = [('float_input', FloatTensorType([None, n_features]))] # 关键配置:让分类器输出概率,zipmap=False让概率以数组形式输出(而非字典) options = {type(clf): {"output_scores": True, "zipmap": False}} onnx_model = convert_sklearn(clf, initial_types=initial_type, options=options) # 保存模型 with open("your_model.onnx", "wb") as f: f.write(onnx_model.SerializeToString())
2. 验证转换后的模型输出节点
用Netron工具打开转换好的ONNX模型,查看输出节点:
- 如果模型有两个输出(比如
label和probabilities),说明转换没问题; - 如果只有一个输出节点(仅类别标签),说明转换时的配置没生效,需要重新调整参数后转换。
二、再排查Android调用环节的问题
1. 确认是否指定了所有输出节点
OrtSession.run()默认只返回第一个输出节点(通常是类别标签),必须明确指定要获取的输出节点名称才能拿到概率。修改Android代码如下:
// 获取所有输出节点信息并打印 List<OrtSession.OutputInfo> outputInfoList = ortSession.getOutputInfo().values().stream().toList(); for (OrtSession.OutputInfo info : outputInfoList) { Log.d("ONNX_DEBUG", "输出节点名称:" + info.getName()); } // 构造输出节点名称数组,同时获取标签和概率 String[] outputNames = new String[outputInfoList.size()]; for (int i = 0; i < outputInfoList.size(); i++) { outputNames[i] = outputInfoList.get(i).getName(); } // 调用模型时指定输出节点 OrtSession.Result result = ortSession.run( Collections.singletonMap(inputName, inputTensor), List.of(outputNames) ); // 读取概率结果 float[][] probabilities = (float[][]) result.get(1).getValue();
2. 检查版本兼容性
你用的ONNX Runtime是1.14.1,确认Python端转换模型时用的skl2onnx和onnxruntime版本是否和Android端兼容。如果版本差异过大,可能导致输出节点不匹配,建议升级skl2onnx到最新稳定版后重新转换模型。
3. 确认输入数据格式一致
Android端的输入数据维度、数据类型要和Python测试时完全一致:
- 比如Python用的是float32类型,Android也要用float数组;
- 输入维度(比如batch size、特征数)必须和模型要求匹配。
三、快速排查步骤
- 用Netron看模型输出节点,确认是否有概率输出;
- 对比Python测试代码,确认Python是通过获取第二个输出节点拿到概率的;
- 修改Android代码,打印所有输出节点名称,然后指定输出节点调用模型;
- 如果还是不行,重新转换模型,确保加上
output_scores=True配置。
内容的提问来源于stack exchange,提问作者ImMathan
相关产品推荐
相关产品推荐

