Open VPU-tech opened 1 year ago
What about the probabilities? It seems you trained a model for a multiclass classification. What is the model (tree, linear classifier) and how did you convert it? There are known issues when the model is trained with double and the conversion uses float. The label may be different after the probabilites are rounded if they were close to ties. The discrepancies may be even bigger for trees. You will find more at Issues when switching to float.
We have used RandomForest Classifier for predicting label for Iris Data `Code used to convert RF model into ONNX
from skl2onnx import convert_sklearn
from skl2onnx.common.data_types import FloatTensorType
initial_type = [('float_input', FloatTensorType([None, 4]))] clr = RandomForestClassifier() onx = convert_sklearn(clr, initial_types=initial_type)
with open("rf_iris.onnx", "wb") as f:
f.write(onx.SerializeToString()) `
<html xmlns:o="urn:schemas-microsoft-com:office:office" xmlns:x="urn:schemas-microsoft-com:office:excel" xmlns="http://www.w3.org/TR/REC-html40">
python_onnx_inference_results | python_onnx_inference_probab | c_onnx_inference_results | C_onnx_inference_probab -- | -- | -- | -- 2 | {0: 0.0, 1: 0.17000000178813934, 2: 0.8299995064735413} | 2 | [0: 0.0, 1: 0.000000000, 2: 0.829999506] 2 | {0: 0.0, 1: 0.0, 2: 0.9999993443489075} | 2 | [0: 0.0, 1: 0.000000000, 2: 0.999999344] 2 | {0: 0.0, 1: 0.06999999284744263, 2: 0.9299994111061096} | 2 | [0: 0.0, 1: 0.000000000, 2: 0.929999411] 1 | {0: 0.0, 1: 0.9999993443489075, 2: 0.0} | 0 | [0: 0.0, 1: 0.000000000, 2: 0.000000000] 0 | {0: 0.9999993443489075, 1: 0.0, 2: 0.0} | 0 | [0: 0.0, 1: 0.000000000, 2: 0.000000000] 2 | {0: 0.0, 1: 0.0, 2: 0.9999993443489075} | 2 | [0: 0.0, 1: 0.000000000, 2: 0.999999344] 2 | {0: 0.0, 1: 0.12999998033046722, 2: 0.8699994683265686} | 2 | [0: 0.0, 1: 0.000000000, 2: 0.869999468] 0 | {0: 0.9999993443489075, 1: 0.0, 2: 0.0} | 0 | [0: 0.0, 1: 0.000000000, 2: 0.000000000] 2 | {0: 0.0, 1: 0.0, 2: 0.9999993443489075} | 2 | [0: 0.0, 1: 0.000000000, 2: 0.999999344] 2 | {0: 0.0, 1: 0.0, 2: 0.9999993443489075} | 2 | [0: 0.0, 1: 0.000000000, 2: 0.999999344] 0 | {0: 0.9999993443489075, 1: 0.0, 2: 0.0} | 0 | [0: 0.0, 1: 0.000000000, 2: 0.000000000] 1 | {0: 0.0, 1: 0.9799993634223938, 2: 0.019999999552965164} | 2 | [0: 0.0, 1: 0.000000000, 2: 0.020000000] 2 | {0: 0.0, 1: 0.17000000178813934, 2: 0.8299995064735413} | 2 | [0: 0.0, 1: 0.000000000, 2: 0.829999506] 0 | {0: 0.9999993443489075, 1: 0.0, 2: 0.0} | 0 | [0: 0.0, 1: 0.000000000, 2: 0.000000000] 1 | {0: 0.0, 1: 0.9899993538856506, 2: 0.009999999776482582} | 2 | [0: 0.0, 1: 0.000000000, 2: 0.010000000] 0 | {0: 0.9999993443489075, 1: 0.0, 2: 0.0} | 0 | [0: 0.0, 1: 0.000000000, 2: 0.000000000] 0 | {0: 0.9999993443489075, 1: 0.0, 2: 0.0} | 0 | [0: 0.0, 1: 0.000000000, 2: 0.000000000] 0 | {0: 0.9999993443489075, 1: 0.0, 2: 0.0} | 0 | [0: 0.0, 1: 0.000000000, 2: 0.000000000]
My ONNX Model has been built on float pointing numbers, where number accuracy is of high importance upto 10 decimal precision . ONNX model input is array of float numbers and output is label.
When I am inferring this ONNX model in C++ using 'Microsoft.ML.OnnxRuntime\1.13.1\runtimes', for same set of input, output label keeps differing. Also sometimes it is not even matching with results, when inferred same ONNX model from python, However while executing it from python, label output is not only consistent, but also same as pickle file output.
`C++ Code Snippet for ONNX Inference
// Set up options for session Ort::SessionOptions sessionOptions; sessionOptions.SetIntraOpNumThreads(1);
// Sets graph optimization level (Here, enable all possible optimizations) sessionOptions.SetGraphOptimizationLevel(GraphOptimizationLevel::ORT_ENABLE_EXTENDED);
std::string instanceName{ "Test Inference" }; mEnv = std::make_shared(OrtLoggingLevel::ORT_LOGGING_LEVEL_WARNING, instanceName.c_str());
// use it.... mSession = std::make_shared(*mEnv, pwcsName, sessionOptions);
// Create input tensors of ORT::Value, which is a tensor format used by ONNX Runtime Ort::MemoryInfo memoryInfo = Ort::MemoryInfo::CreateCpu(OrtAllocatorType::OrtDeviceAllocator, OrtMemType::OrtMemTypeCPU);
auto input_tensor = Ort::Value::CreateTensor(memoryInfo, inputTensorValues.data(),
inputTensorSize, mInputDims.data(), mInputDims.size());
auto output_tensors = mSession->Run(Ort::RunOptions{ nullptr }, inputNames.data(), &input_tensor, 1, outputNames.data(), 1);
// Get the inference result float* outArr = output_tensors.front().GetTensorMutableData()
assert(abs(outArr[0] - 0.000045) < 1e-6);
// score the model, and print scores for label classes for (int i = 0; i < count; i++) { std::cout << "Score for class [" << i << "] = " << outArr[i] << '\n';
} std::cout << std::flush;
int64_t cls_idx = std::max_element(outArr, outArr + count) - outArr; m_label = labels[cls_idx]; `
std::vectorstd::string labels = { "setosa", "versicolor", "virginica" }; Prediction Label differs only when inferred from C++
Please help me understand why results from these 2 Inferences are not matching.
Expected : Output labels from Python and C++ inferences shall be same