def lightgbm_classifier_shape_extractor(operator): N = operator.inputs[0].type.shape[0] class_labels = operator.raw_operator.classes_ if all(isinstance(i, numpy.ndarray) for i in class_labels): class_labels = numpy.concatenate(class_labels) if all(isinstance(i, str) for i in class_labels): operator.outputs[0].type = StringTensorType(shape=[N]) operator.outputs[1].type = SequenceType(DictionaryType(StringTensorType([]), FloatTensorType([])), N) elif all(isinstance(i, (numbers.Real, bool, numpy.bool_)) for i in class_labels): operator.outputs[0].type = Int64TensorType(shape=[N]) operator.outputs[1].type = SequenceType(DictionaryType(Int64TensorType([]), FloatTensorType([])), N) else: raise ValueError('Unsupported or mixed label types')
def test_model_dict_vectorizer_issue(self): key_value_map = [{1: 'A', 2: 'B'}, {1: 'C', 3: 'D'}, {1: 'C', 3: 'A'}] model = DictVectorizer(sparse=False).fit(key_value_map) with self.assertRaises(RuntimeError): convert_sklearn(model, 'dv', [("input", DictionaryType(Int64TensorType([1]), StringTensorType([1])))])
def test_model_dict_vectorizer(self): model = DictVectorizer() data = [{'amy': 1., 'chin': 200.}, {'nice': 3., 'amy': 1.}] model.fit_transform(data) model_onnx = convert_sklearn(model, 'dictionary vectorizer', [('input', DictionaryType(StringTensorType([1]), FloatTensorType([1])))]) self.assertTrue(model_onnx is not None) dump_data_and_model(data, model, model_onnx, basename="SklearnDictVectorizer-OneOff-SkipDim1", allow_failure="StrictVersion(onnxruntime.__version__) <= StrictVersion('0.1.3') or StrictVersion(onnx.__version__) < StrictVersion('1.3.0')")
def _problem_for_feature_hasher(dtype=numpy.float32): """ Returns a problem for the :epkg:`sklearn:feature_extraction:DictVectorizer`. """ data = load_iris() # X = data.data y = data.target y2 = [{("cl%d" % _): dtype(1000 + i)} for i, _ in enumerate(y)] y2[0]["cl2"] = -2 itt = [("X", DictionaryType(StringTensorType([1]), FloatTensorType([1])))] y2 = numpy.array(y2) return (y2, y, itt, 'transform', 0, y2)
def test_dict_vectorizer(self): model = DictVectorizer() data = [{"amy": 1.0, "chin": 200.0}, {"nice": 3.0, "amy": 1.0}] model.fit_transform(data) exp = model.transform(data) model_def = convert_sklearn(model, "dictionary vectorizer", [("input", DictionaryType(StringTensorType([1]), FloatTensorType([1])))]) oinf = OnnxInference(model_def) array_data = numpy.array(data) got = oinf.run({'input': array_data}) self.assertEqual(list(sorted(got)), ['variable']) self.assertEqualArray(exp.todense(), got['variable'].todense())
def _problem_for_dict_vectorizer(dtype=numpy.float32, n_features=None): """ Returns a problem for the :epkg:`sklearn:feature_extraction:DictVectorizer`. """ data = load_iris() # X = data.data y = data.target y2 = [{_: dtype(1000 + i)} for i, _ in enumerate(y)] y2[0][2] = -2 cltype = FloatTensorType if dtype == numpy.float32 else DoubleTensorType itt = [("X", DictionaryType(StringTensorType([1]), cltype([1])))] y2 = numpy.array(y2) y = y.astype(numpy.int64) return (y2, y, itt, 'transform', 0, y2)
def test_model_dict_vectorizer(self): model = DictVectorizer() data = [{"amy": 1.0, "chin": 200.0}, {"nice": 3.0, "amy": 1.0}] model.fit_transform(data) model_onnx = convert_sklearn( model, "dictionary vectorizer", [( "input", DictionaryType(StringTensorType([1]), FloatTensorType([1])), )], target_opset=TARGET_OPSET) self.assertTrue(model_onnx is not None) dump_data_and_model(data, model, model_onnx, basename="SklearnDictVectorizer-OneOff-SkipDim1")
def test_model_dict_vectorizer_sort_false(self): model = DictVectorizer(sparse=False, sort=False) data = [{1: 1.0, 2: 200.0}, {1: 3.0, 3: 1.0}] model.fit_transform(data) model_onnx = convert_sklearn( model, "dictionary vectorizer", [( "input", DictionaryType(Int64TensorType([1]), FloatTensorType([1])), )], target_opset=TARGET_OPSET) self.assertTrue(model_onnx is not None) dump_data_and_model( data, model, model_onnx, basename="SklearnDictVectorizerSortFalse-OneOff-SkipDim1")
def test_model_dict_vectorizer(self): model = DictVectorizer() data = [{"amy": 1.0, "chin": 200.0}, {"nice": 3.0, "amy": 1.0}] model.fit_transform(data) model_onnx = convert_sklearn(model, "dictionary vectorizer", [( "input", DictionaryType(StringTensorType([1]), FloatTensorType([1])), )]) self.assertTrue(model_onnx is not None) dump_data_and_model( data, model, model_onnx, basename="SklearnDictVectorizer-OneOff-SkipDim1", allow_failure="StrictVersion(onnxruntime.__version__)" " <= StrictVersion('0.1.3') or " "StrictVersion(onnx.__version__)" " < StrictVersion('1.3.0')")
def test_model_dict_vectorizer_sort_false(self): model = DictVectorizer(sparse=False, sort=False) data = [{1: 1.0, 2: 200.0}, {1: 3.0, 3: 1.0}] model.fit_transform(data) model_onnx = convert_sklearn( model, "dictionary vectorizer", [( "input", DictionaryType(Int64TensorType([1]), FloatTensorType([1])), )], ) self.assertTrue(model_onnx is not None) dump_data_and_model( data, model, model_onnx, basename="SklearnDictVectorizerSortFalse-OneOff-SkipDim1", allow_failure="StrictVersion(onnxruntime.__version__)" " <= StrictVersion('0.1.3') or " "StrictVersion(onnx.__version__)" " < StrictVersion('1.3.0')", )
def custom_parser(scope, model, inputs, custom_parsers=None): if custom_parsers is not None and model in custom_parsers: return custom_parsers[model](scope, model, inputs, custom_parsers=custom_parsers) if all( isinstance(i, (numbers.Real, bool, np.bool_)) for i in model.classes_): label_type = Int64TensorType() else: label_type = StringTensorType() output_label = scope.declare_local_variable( 'output_label', label_type) this_operator = scope.declare_local_operator( 'LgbmClassifier', model) this_operator.inputs = inputs probability_map_variable = scope.declare_local_variable( 'output_probability', SequenceType(DictionaryType(label_type, scope.tensor_type()))) this_operator.outputs.append(output_label) this_operator.outputs.append(probability_map_variable) return this_operator.outputs
print(r2_score(y_test, pred)) #################################### # Conversion to ONNX format # +++++++++++++++++++++++++ # # We use module # `sklearn-onnx <https://github.com/onnx/sklearn-onnx>`_ # to convert the model into ONNX format. from skl2onnx import convert_sklearn from skl2onnx.common.data_types import DictionaryType, FloatTensorType, Int64TensorType, SequenceType # initial_type = [('float_input', DictionaryType(Int64TensorType([1]), FloatTensorType([])))] initial_type = [("float_input", DictionaryType(Int64TensorType([1]), FloatTensorType([])))] onx = convert_sklearn(pipe, initial_types=initial_type) with open("pipeline_vectorize.onnx", "wb") as f: f.write(onx.SerializeToString()) ################################## # We load the model with ONNX Runtime and look at # its input and output. import onnxruntime as rt from onnxruntime.capi.onnxruntime_pybind11_state import InvalidArgument sess = rt.InferenceSession("pipeline_vectorize.onnx", providers=rt.get_available_providers()) import numpy
def get_defined_outputs(outputs, onnx_node, typed_inputs=None, variables=None, dtype=None, schema=None, schema_inputs=None): """ Gets types of predefined outputs when they cannot be inferred. Some part of it should be automated based on type constraints. :param outputs: requested outputs :param onnx_node: :epkg:`ONNX` node definition :param typed_inputs: known typed inputs of the node as `tuple(name, type)` :param variables: registered variables created by previous operators :param dtype: float computational type :param schema: defined outputs by schema (*expected_outputs*) :param schema_inputs: defined inputs by schema (*expected_inputs*) :return: typed outputs as ``tuple(name, type)`` """ if schema is None: ft = DoubleTensorType if dtype == numpy.float64 else FloatTensorType elif len(schema) != 1: raise ValueError( # pragma: no cover "schema should only contain one output not {}.".format(schema)) else: if isinstance(schema, DataType): ft = schema[0].__class__ else: ft = schema[0][1].__class__ if onnx_node.op_type in { 'ZipMap', 'ArgMin', 'ArgMax', 'Shape', 'Greater', 'Less', 'Equal', 'TopK', 'Cast', 'ArrayFeatureExtractor', 'Reshape', 'Transpose', 'Scan', 'ConstantOfShape' }: if onnx_node.op_type == "ZipMap": # ZipMap otype = SequenceType(DictionaryType(Int64Type(), ft())) outputs = [(name, otype) for name in outputs] elif (onnx_node.op_type in ("ArgMin", "ArgMax", 'Shape') and len(outputs) == 1): # ArgMin, ArgMax, Shape outputs = [(outputs[0], Int64TensorType())] elif (onnx_node.op_type in ("Greater", "Less", 'Equal') and len(outputs) == 1): # Greater, Less, Equal outputs = [(outputs[0], BooleanTensorType())] elif onnx_node.op_type == "TopK" and len(outputs) == 2: # TopK if len(typed_inputs) != 2: raise RuntimeError( # pragma: no cover "Wrong typed_inputs, got {}.".format(typed_inputs)) outputs = [(outputs[0], typed_inputs[0][1]), (outputs[1], Int64TensorType())] elif onnx_node.op_type == "Cast" and len(outputs) == 1: # Cast ttyp = _guess_type_proto(onnx_node.attribute[0].i, dims=None) outputs = [(outputs[0], ttyp)] elif onnx_node.op_type == "ArrayFeatureExtractor": # ArrayFeatureExtractor if len(typed_inputs) != 2: raise RuntimeError( # pragma: no cover "Wrong typed_inputs, got {}.".format(typed_inputs)) outputs = [(outputs[0], typed_inputs[0][1])] elif onnx_node.op_type in ('Reshape', 'Transpose'): # Reshape outputs = [(outputs[0], typed_inputs[0][1].__class__())] elif onnx_node.op_type == 'Scan': # Scan if len(outputs) != len(typed_inputs): raise RuntimeError( # pragma: no cover "Dimension mismatch, operator Scan should have " "the same number of inputs and outputs {} != {}" ".".format(len(outputs), len(typed_inputs))) outputs = [(o, t[1].__class__()) for o, t in zip(outputs, typed_inputs)] elif onnx_node.op_type == "ConstantOfShape": # ConstantOfShape outputs = [(outputs[0], ft())] elif 'Classifier' in onnx_node.op_type: # Good chance that's a classifier. outputs = [(outputs[0], Int64TensorType()), (outputs[1], ft())] else: if schema_inputs is not None and schema is not None: dt = {} for got, exp in zip(typed_inputs, schema_inputs): if isinstance(exp[1], str): dt[exp[1]] = got out = [] for i in range(len(outputs)): # pylint: disable=C0200 o = outputs[i] if isinstance(o, str): exp = schema[i] if exp[1] in dt: out.append((o, dt[exp[1]][1].__class__())) else: nt = _guess_type_proto_str(exp[1], None) out.append((o, nt)) elif (isinstance(o, tuple) and (isinstance(o[1], str) or o[1] is None)): exp = schema[i] if exp[1] in dt: out.append((o[0], dt[exp[1]][1].__class__())) else: nt = _guess_type_proto_str(exp[1], None) out.append((o[0], nt)) else: out.append(o) outputs = out elif len(typed_inputs) == 1 and len(outputs) == 1: # Default case # Assuming the only output is the same as the only input. outputs = [(outputs[0], typed_inputs[0][1])] else: # Default outputs = [(name, ft()) for name in outputs] for name, typ in outputs: if typ in ('T', None, '', 'I'): raise NotImplementedError( # pragma: no cover "Undefined output type: %r (outputs=%r, typed_inputs=%r, " "dtype=%r, schema=%r, schema_inputs=%r, onnx_node=%r, " "variables=%r)." % (typ, outputs, typed_inputs, dtype, schema, schema_inputs, onnx_node, variables)) if not isinstance(name, str): raise NotImplementedError( # pragma: no cover "Undefined output type: %r (outputs=%r, typed_inputs=%r, " "dtype=%r, schema=%r, schema_inputs=%r, onnx_node=%r, " "variables=%r)." % (typ, outputs, typed_inputs, dtype, schema, schema_inputs, onnx_node, variables)) return outputs
def proto2vars(values): """ Converts proto values to Variables. """ def ptype2vttype(it, shape): if it == TensorProto.FLOAT: # pylint: disable=E1101 return FloatTensorType(shape) if it == TensorProto.DOUBLE: # pylint: disable=E1101 return DoubleTensorType(shape) if it == TensorProto.INT64: # pylint: disable=E1101 return Int64TensorType(shape) if it == TensorProto.INT32: # pylint: disable=E1101 return Int32TensorType(shape) if it == TensorProto.BOOL: # pylint: disable=E1101 return BooleanTensorType(shape) if it == TensorProto.STRING: # pylint: disable=E1101 return StringTensorType(shape) if Float16TensorType is None: if it == TensorProto.FLOAT16: # pylint: disable=E1101 return Float16TensorType(shape) raise NotImplementedError( # pragma: no cover "Unrecognized proto type {} with shape {}".format(it, shape)) def ptype2vtype(it): if it == TensorProto.FLOAT: # pylint: disable=E1101 return FloatType() if it == TensorProto.INT64: # pylint: disable=E1101 return Int64Type() raise NotImplementedError( # pragma: no cover "Unrecognized proto type {}".format(it)) res = [] for v_ in values: v = v_ name = v.name if hasattr(v, 'name') else None if hasattr(v, 'type') and str(v.type) != '': t = v.type v = proto2vars([t])[0][1] elif hasattr(v, 'sequence_type') and str(v.sequence_type) != '': subtype = proto2vars([v.sequence_type.elem_type])[0][1] v = SequenceType(subtype) elif hasattr(v, 'tensor_type') and str(v.tensor_type) != '': tt = v.tensor_type el = tt.elem_type shape = tt.shape dim = shape.dim if len(dim) == 0: shape = [] else: shape = [dim[i].dim_value for i in range(len(dim))] v = ptype2vttype(el, shape) elif hasattr(v, 'map_type') and str(v.map_type) != '': mt = v.map_type keyt = ptype2vtype(mt.key_type) valt = proto2vars([mt.value_type])[0][1] v = DictionaryType(keyt, valt) else: raise RuntimeError( # pragma: no cover "Unable to build a variable from {}.".format(v)) if v.shape is not None and 0 in v.shape: # Replaces 0 by None new_shape = tuple(None if d == 0 else d for d in v.shape) if new_shape in ((None, ), None): v = v.__class__() else: v = v.__class__(new_shape) if v.shape is not None and 0 in v.shape: raise RuntimeError( # pragma: no cover "Shape cannot be empty: '{}': {}.".format(name, v_)) res.append((name, v)) return res
pred = pipe.predict(X_test_dict) print(r2_score(y_test, pred)) #################################### # Conversion to ONNX format # +++++++++++++++++++++++++ # # We use module # `sklearn-onnx <https://github.com/onnx/sklearn-onnx>`_ # to convert the model into ONNX format. from skl2onnx import convert_sklearn from skl2onnx.common.data_types import FloatTensorType, Int64TensorType, DictionaryType, SequenceType # initial_type = [('float_input', DictionaryType(Int64TensorType([1]), FloatTensorType([])))] initial_type = [('float_input', DictionaryType(Int64TensorType([1]), FloatTensorType([])))] onx = convert_sklearn(pipe, initial_types=initial_type) with open("pipeline_vectorize.onnx", "wb") as f: f.write(onx.SerializeToString()) ################################## # We load the model with ONNX Runtime and look at # its input and output. import onnxruntime as rt from onnxruntime.capi.onnxruntime_pybind11_state import InvalidArgument sess = rt.InferenceSession("pipeline_vectorize.onnx") import numpy inp, out = sess.get_inputs()[0], sess.get_outputs()[0] print("input name='{}' and shape={} and type={}".format(inp.name, inp.shape, inp.type))
def get_defined_outputs(outputs, onnx_node, typed_inputs=None, variables=None, dtype=None): """ Gets types of predefined outputs when they cannot be inferred. Some part of it should be automated based on type constraints. @param outputs requested outputs @param onnx_node :epkg:`ONNX` node definition @param typed_inputs known typed inputs of the node as ``tuple(name, type)`` @param variables registered variables created by previous operators @param dtype float computational type @return typed outputs as ``tuple(name, type)`` """ ft = DoubleTensorType if dtype == numpy.float64 else FloatTensorType # ZipMap if onnx_node.op_type == "ZipMap": otype = SequenceType(DictionaryType( Int64Type(), ft())) outputs = [(name, otype) for name in outputs] # ArgMin, ArgMax, Shape elif onnx_node.op_type in ("ArgMin", "ArgMax", 'Shape') and len(outputs) == 1: outputs = [(outputs[0], Int64TensorType())] # Greater, Less, Equal elif onnx_node.op_type in ("Greater", "Less", 'Equal') and len(outputs) == 1: outputs = [(outputs[0], BooleanTensorType())] # TopK elif onnx_node.op_type == "TopK" and len(outputs) == 2: if len(typed_inputs) != 2: raise RuntimeError( "Wrong typed_inputs, got {}.".format(typed_inputs)) outputs = [(outputs[0], typed_inputs[0][1]), (outputs[1], Int64TensorType())] # Cast elif onnx_node.op_type == "Cast" and len(outputs) == 1: ttyp = _guess_type_proto(onnx_node.attribute[0].i, dims=None) outputs = [(outputs[0], ttyp)] # ArrayFeatureExtractor elif onnx_node.op_type == "ArrayFeatureExtractor": if len(typed_inputs) != 2: raise RuntimeError( "Wrong typed_inputs, got {}.".format(typed_inputs)) outputs = [(outputs[0], typed_inputs[0][1])] elif 'Classifier' in onnx_node.op_type: # Good chance that's a classifier. outputs = [(outputs[0], Int64TensorType()), (outputs[1], ft())] # Reshape elif onnx_node.op_type in ('Reshape', 'Transpose'): outputs = [(outputs[0], typed_inputs[0][1].__class__())] # Scan elif onnx_node.op_type == 'Scan': if len(outputs) != len(typed_inputs): raise RuntimeError("Dimension mismatch, operator Scan should have " "the same number of inputs and outputs {} != {}" ".".format(len(outputs), len(typed_inputs))) outputs = [(o, t[1].__class__()) for o, t in zip(outputs, typed_inputs)] # ConstantOfShape elif onnx_node.op_type == "ConstantOfShape": outputs = [(outputs[0], ft())] # Default case # Assuming the only output is the same as the only input. elif len(typed_inputs) == 1 and len(outputs) == 1: outputs = [(outputs[0], typed_inputs[0][1])] # Default else: outputs = [(name, ft()) for name in outputs] return outputs
def _init(self, variables=None): """ Initializes the node. :param variables: registered variables created by previous operators The current implementation for operator *Scan* only works for matrices. """ custom_nodes = self.options.get('nodes', None) if (custom_nodes is not None and self.onnx_node.op_type in custom_nodes): self.alg_class = custom_nodes[self.onnx_node.op_type] else: try: self.alg_class = getattr(alg2, 'Onnx' + self.onnx_node.op_type) except AttributeError: try: self.alg_class = getattr( alg, 'Onnx' + self.onnx_node.op_type) except AttributeError: self.alg_class = getattr( alg3, 'Onnx' + self.onnx_node.op_type) inputs = list(self.onnx_node.input) self.mapping, self.inputs = self._name_mapping(inputs) self.outputs = list(self.onnx_node.output) options = self.options.copy() options.pop('nodes', None) target_opset = options.pop('target_opset', None) domain = options.pop('domain', None) disable_optimisation = options.pop('disable_optimisation', False) session_options = options.pop('session_options', False) ir_version = options.pop('ir_version', None) if domain == '' and target_opset < 9: # target_opset should be >= 9 not {} for main domain. # We assume it was the case when the graph was created. pass if self.onnx_node.op_type == 'ZipMap': self.inst_ = self.alg_class(*self.inputs, output_names=self.outputs, op_version=target_opset, **options) inputs = get_defined_inputs( self.inputs, variables, dtype=self.dtype) name = (self.outputs[0] if len(self.outputs) == 1 else self.inst_.expected_outputs[0][0]) otype = (Int64TensorType if 'classlabels_int64s' in options else StringTensorType) outvar = [(name, DictionaryType(otype([1]), FloatTensorType([1])))] self.onnx_ = self.inst_.to_onnx(inputs, outputs=outvar) forced = True elif self.onnx_node.op_type == 'ConstantOfShape': for k in options: v = options[k] if isinstance(v, numpy.ndarray): options[k] = make_tensor( k, self._guess_proto_type(v.dtype), v.shape, v.tolist()) self.inst_ = self.alg_class(*self.inputs, output_names=self.outputs, op_version=target_opset, **options) inputs = get_defined_inputs( self.inputs, variables, dtype=self.dtype) try: self.onnx_ = self.inst_.to_onnx(inputs, target_opset=target_opset, domain=domain) if "dim_value: 0" in str(self.onnx_): raise RuntimeError( # pragma: no cover "Probable issue as one dimension is null.\n--\n{}".format( self.onnx_)) except AttributeError as e: # pragma: no cover # older version of skl2onnx self.onnx_ = self.inst_.to_onnx(inputs) if "dim_value: 0" in str(self.onnx_): raise RuntimeError( "Probable issue as one dimension is null.\n--\n{}".format( self.onnx_)) from e forced = False elif self.onnx_node.op_type == 'Scan': self.inst_ = self.alg_class( *self.inputs, output_names=self.outputs, op_version=target_opset, **options) inputs = get_defined_inputs( self.inputs, variables, dtype=self.dtype) outputs = get_defined_outputs( self.outputs, self.onnx_node, inputs, variables, dtype=self.dtype) inputs = [(name, cl.__class__([None, None])) for (name, cl) in inputs] outputs = [(name, cl.__class__([None, None])) for (name, cl) in outputs] self.onnx_ = self.inst_.to_onnx(inputs, outputs=outputs, target_opset=target_opset, domain=domain) if "dim_value: 0" in str(self.onnx_): raise RuntimeError( # pragma: no cover "Probable issue as one dimension is null.\n--\n{}".format( self.onnx_)) forced = True else: self.inst_ = self.alg_class(*self.inputs, output_names=self.outputs, op_version=target_opset, domain=domain, **options) inputs = get_defined_inputs( self.inputs, variables, dtype=self.dtype, schema=self.alg_class.expected_inputs) try: self.onnx_ = self.inst_.to_onnx( inputs, target_opset=target_opset, domain=domain) if "dim_value: 0" in str(self.onnx_): raise RuntimeError( # pragma: no cover "Probable issue as one dimension is null.\n--\n{}\n---\n{}".format( self.onnx_, inputs)) forced = False except (RuntimeError, ValueError, InferenceError) as eo: # Let's try again by forcing output types. forced = True outputs = get_defined_outputs( self.outputs, self.onnx_node, inputs, variables, dtype=self.dtype, schema=self.alg_class.expected_outputs, schema_inputs=self.alg_class.expected_inputs) try: self.onnx_ = self.inst_.to_onnx(inputs, outputs=outputs, target_opset=target_opset, domain=domain) except NotImplementedError as e: # pragma: no cover raise NotImplementedError( "Unable to instantiate node {} inputs={} " "self.inputs={} outputs={} variables={} " "dtype={} e={} eo={}".format( self.alg_class, inputs, self.inputs, outputs, variables, self.dtype, e, eo)) from e if "dim_value: 0" in str(self.onnx_): raise RuntimeError( # pragma: no cover "Probable issue as one dimension is null.\n--\n{}".format( self.onnx_)) from e if len(self.onnx_.graph.output) != len(self.outputs): # pragma: no cover # Something is wrong, falls back to default plan. forced = True outputs = get_defined_outputs( self.outputs, self.onnx_node, inputs, variables, dtype=self.dtype, schema=self.alg_class.expected_outputs) self.onnx_ = self.inst_.to_onnx(inputs, outputs=outputs, target_opset=target_opset, domain=domain) if "dim_value: 0" in str(self.onnx_): raise RuntimeError( # pragma: no cover "Probable issue as one dimension is null.\n--\n{}".format( self.onnx_)) else: lo = list(self.onnx_.graph.output) outputs = proto2vars(lo) sess_options = session_options or SessionOptions() self.run_options = RunOptions() if session_options is None: try: sess_options.session_log_severity_level = 3 # sess_options.sessions_log_verbosity_level = 0 except AttributeError: # pragma: no cover # onnxruntime not recent enough. pass try: self.run_options.run_log_severity_level = 3 # self.run_options.run_log_verbosity_level = 0 except AttributeError: # pragma: no cover # onnxruntime not recent enough. pass if disable_optimisation: sess_options.graph_optimization_level = ( # pragma: no cover GraphOptimizationLevel.ORT_DISABLE_ALL) elif disable_optimisation: raise RuntimeError( # pragma: no cover "session_options and disable_optimisation cannot be defined " "at the same time.") if ir_version is not None: self.onnx_.ir_version = ir_version try: self.sess_ = InferenceSession( self.onnx_.SerializeToString(), sess_options=sess_options) except (RuntimeError, OrtNotImplemented, OrtInvalidGraph, OrtFail) as e: raise RuntimeError( "Unable to load node '{}' (output type was {}) inputs={} " "self.inputs={} self.onnx_node.input={} " "variables={} mapping={} " "expected_inputs={}\n{}".format( self.onnx_node.op_type, "guessed" if forced else "inferred", inputs, self.inputs, self.onnx_node.input, variables, self.mapping, self.alg_class.expected_inputs, self.onnx_)) from e self.typed_outputs_ = outputs