def test_onnxt_idi(self): idi = numpy.identity(2).astype(numpy.float32) onx = OnnxAdd('X', idi, output_names=['Y'], op_version=TARGET_OPSET) model_def = onx.to_onnx({'X': idi.astype(numpy.float32)}) oinf = OnnxInference(model_def, runtime="python_compiled") res = oinf.run({'X': idi.astype(numpy.float32)}) self.assertEqual(idi * 2, res['Y']) self.assertIn('_run_compiled', oinf.__dict__) self.assertIn('_run_compiled_code', oinf.__dict__) code = oinf._run_compiled_code # pylint: disable=W0212,E1101 self.assertIsInstance(code, str) self.assertIn('def compiled_run(dict_inputs, yield_ops=None):', code) self.assertIn('(Y, ) = n0_add(X, Ad_Addcst)', code) self.assertIn(' def compiled_run(dict_inputs, yield_ops=None):', str(oinf))
def test_onnxt_dot_shape(self): idi = numpy.identity(2) idi2 = numpy.identity(2) * 2 onx = OnnxAdd(OnnxAdd('X', idi), idi2, output_names=['Y']) model_def = onx.to_onnx({'X': idi.astype(numpy.float32)}) oinf = OnnxInference(model_def) dot = oinf.to_dot(add_rt_shapes=True) self.assertIn('Add [', dot) self.assertIn('Add1 [', dot) self.assertIn('Add\\n(Ad_Add)', dot) self.assertIn('Add\\n(Ad_Add1)', dot) self.assertIn('X -> Ad_Add;', dot) self.assertIn('Ad_Addcst1 -> Ad_Add1;', dot) self.assertIn('Ad_Addcst -> Ad_Add;', dot) self.assertIn('Ad_Add1 -> Y;', dot) self.assertIn('shape=(n, 2)', dot) self.assertIn('inplace', dot)
def test_onnx_micro_runtime(self): opset = TestOnnxMicroRuntime.opset dtype = numpy.float32 x = numpy.array([1, 2, 4, 5, 5, 4]).astype(numpy.float32).reshape( (3, 2)) cop = OnnxAdd('X', numpy.array([1], dtype=dtype), op_version=opset) cop4 = OnnxAdd(cop, numpy.array([2], dtype=dtype), op_version=opset, output_names=['Y']) model_def = cop4.to_onnx({'X': x}, target_opset=opset) rt = OnnxMicroRuntime(model_def) out = rt.run({'X': x}) self.assertIn('X', out) self.assertIn('Y', out) self.assertIn('Ad_Addcst', out) self.assertEqual(len(out), 5)
def test_onnxt_text(self): idi = numpy.identity(2).astype(numpy.float32) idi2 = (numpy.identity(2) * 2).astype(numpy.float32) onx = OnnxAdd(OnnxAdd('X', idi, op_version=TARGET_OPSET), idi2, output_names=['Y'], op_version=TARGET_OPSET) model_def = onx.to_onnx({'X': idi.astype(numpy.float32)}, target_opset=TARGET_OPSET) oinf = OnnxInference(model_def) text = oinf.to_text() self.assertIn('Init', text) self.assertIn('Input-0', text) self.assertIn('Output-0', text) self.assertIn('inout', text) self.assertIn('O0 I0', text) self.assertIn('Ad_Addcst', text)
def test_onnx_if_algebra_indirect_unnamed_clear_input_recursive(self): opv = TARGET_OPSET x1 = np.array([[0, 3], [7, 0]], dtype=np.float32) x2 = np.array([[1, 0], [2, 0]], dtype=np.float32) node_xy = OnnxMul('x1', 'x2', op_version=opv) node_then = OnnxAdd( 'x1', 'xy', output_names=['absxythen'], op_version=opv) then_body = node_then.to_onnx( {'x1': x1, 'xy': x2}, target_opset=opv, outputs=[('absxythen', FloatTensorType())]) node_else = OnnxSub( 'x1', 'x2', output_names=['absxyelse'], op_version=opv) else_body = node_else.to_onnx( {'x1': x1, 'x2': x2}, target_opset=opv, outputs=[('absxyelse', FloatTensorType())]) cond = OnnxGreater( OnnxReduceSum('x1', op_version=opv), OnnxReduceSum('x2', op_version=opv), op_version=opv) ifnode = OnnxIf(cond, then_branch=then_body.graph, else_branch=else_body.graph, op_version=opv, output_names=['yt'], clear_subgraph_inputs=True) subgraph = ifnode.to_onnx( {'x1': x1, 'x2': x2}, target_opset=opv, outputs=[('yt', FloatTensorType())]) cond2 = OnnxGreater( OnnxReduceMin('x1', op_version=opv), OnnxReduceMin('x2', op_version=opv), op_version=opv) ifnode2 = OnnxIf(cond2, then_branch=then_body.graph, else_branch=subgraph.graph, op_version=opv, output_names=['y'], global_context={'xy': node_xy}, clear_subgraph_inputs=True) model_def = ifnode2.to_onnx( {'x1': x1, 'x2': x2}, target_opset=opv, outputs=[('y', FloatTensorType())]) sess = InferenceSession(model_def.SerializeToString()) res = sess.run(None, {'x1': x1, 'x2': x2}) assert_almost_equal(x1 + x1 * x2, res[0])
def test_onnxt_pickle_check(self): idi = numpy.identity(2).astype(numpy.float32) onx = OnnxAdd('X', idi, output_names=['Y'], op_version=TARGET_OPSET) model_def = onx.to_onnx({'X': idi.astype(numpy.float32)}, target_opset=TARGET_OPSET) oinf = OnnxInference(model_def) shape = oinf.shape_inference() self.assertNotEmpty(shape) if not sys.platform.startswith('win'): # Crashes (onnx crashes). try: oinf.check_model() except ValidationError as e: warnings.warn("Why? " + str(e)) # pylint: disable=E1101 pkl = pickle.dumps(oinf) obj = pickle.loads(pkl) self.assertEqual(str(oinf), str(obj))
def test_onnxt_dot(self): idi = numpy.identity(2).astype(numpy.float32) idi2 = (numpy.identity(2) * 2).astype(numpy.float32) onx = OnnxAdd(OnnxAdd('X', idi, op_version=TARGET_OPSET), idi2, output_names=['Y'], op_version=TARGET_OPSET) model_def = onx.to_onnx({'X': idi.astype(numpy.float32)}, target_opset=TARGET_OPSET) oinf = OnnxInference(model_def) dot = oinf.to_dot() self.assertIn('Add [', dot) self.assertIn('Add1 [', dot) self.assertIn('Add\\n(Ad_Add)', dot) self.assertIn('Add\\n(Ad_Add1)', dot) self.assertIn('X -> Ad_Add;', dot) self.assertIn('Ad_Addcst1 -> Ad_Add1;', dot) self.assertIn('Ad_Addcst -> Ad_Add;', dot) self.assertIn('Ad_Add1 -> Y;', dot)
def test_onnxt_graph(self): idi = numpy.identity(2).astype(numpy.float32) idi2 = (numpy.identity(2) * 2).astype(numpy.float32) onx = OnnxAdd(OnnxAdd('X', idi, op_version=TARGET_OPSET), idi2, output_names=['Y'], op_version=TARGET_OPSET) model_def = onx.to_onnx({'X': idi.astype(numpy.float32)}, target_opset=TARGET_OPSET) oinf = OnnxInference(model_def) js = oinf.to_sequence() self.assertIn('inits', js) self.assertIn('inputs', js) self.assertIn('outputs', js) self.assertIn('intermediate', js) self.assertIn('nodes', js) self.assertIn('sequence', js) self.assertEqual(len(js['sequence']), 2) self.assertEqual(len(js['intermediate']), 2)
def test_bug_add(self): coef = numpy.array([-8.43436238e-02, 5.47765517e-02, 6.77578341e-02, 1.56675273e+00, -1.45737317e+01, 3.78662574e+00 - 6.52943746e-03 - 1.39463522e+00, 2.89157796e-01 - 1.53753213e-02 - 9.88045749e-01, 1.00224585e-02, -4.96820220e-01], dtype=numpy.float64) intercept = 35.672858515632 X_test = (coef + 1.).reshape((1, coef.shape[0])) onnx_fct = OnnxAdd( OnnxMatMul('X', coef.astype(numpy.float64), op_version=TARGET_OPSET), numpy.array([intercept]), output_names=['Y'], op_version=TARGET_OPSET) onnx_model64 = onnx_fct.to_onnx({'X': X_test.astype(numpy.float64)}) oinf = OnnxInference(onnx_model64) ort_pred = oinf.run({'X': X_test.astype(numpy.float64)})['Y'] self.assertEqualArray(ort_pred, numpy.array([245.19907295849504]))
def test_grad_helper_fillgrad(self): opv = opset node = OnnxAdd('X', numpy.array([1], dtype=numpy.float32), op_version=opv, output_names=['Y']) onx = node.to_onnx({'X': FloatTensorType([None, 10])}, {'Y': FloatTensorType([None, 10])}, target_opset=opv) self.assertRaise( lambda: onnx_derivative( onx, weights=[], options=DerivativeOptions.FillGrad), ValueError) new_onx = onnx_derivative(onx, weights=[], options=(DerivativeOptions.FillGrad | DerivativeOptions.KeepOutputs)) input_names = set(i.name for i in new_onx.graph.input) self.assertNotIn('Y_grad', input_names) self.check_runtime(new_onx, 'test_grad_helper_fillgrad', verbose=False)
def test_onnxt_idi_debug(self): idi = numpy.identity(2) onx = OnnxAdd('X', idi, output_names=['Y'], op_version=get_opset_number_from_onnx()) model_def = onx.to_onnx({'X': idi.astype(numpy.float32)}) oinf = OnnxInference(model_def, runtime="python_compiled_debug") res, out, err = self.capture( lambda: oinf.run({'X': idi.astype(numpy.float32)})) self.assertEmpty(err) self.assertIn("-='i.X'", out) self.assertIn("-='o.Y'", out) self.assertEqual(idi * 2, res['Y']) self.assertIn('_run_compiled', oinf.__dict__) self.assertIn('_run_compiled_code', oinf.__dict__) code = oinf._run_compiled_code # pylint: disable=W0212,E1101 self.assertIsInstance(code, str) self.assertIn('def compiled_run(dict_inputs):', code) self.assertIn('(Y, ) = n0_add(X, Ad_Addcst)', code) self.assertIn(' def compiled_run(dict_inputs):', str(oinf))
def test_onnx_init_sparse_coo(self): row = np.array([0, 0, 1, 3, 1], dtype=np.float32) col = np.array([0, 2, 1, 3, 1], dtype=np.float32) data = np.array([1, 1, 1, 1, 1], dtype=np.float32) X = coo_matrix((data, (row, col)), shape=(4, 4)) node = OnnxAdd('X', X, output_names=['Y'], op_version=onnx.defs.onnx_opset_version()) model_def = node.to_onnx({'X': X}, outputs=[('Y', FloatTensorType())]) try: sess = InferenceSession(model_def.SerializeToString()) except (RuntimeError, OrtInvalidArgument): # Sparse tensor is not supported for constant. return res = sess.run(None, {'X': X})[0] assert_almost_equal(X + X, res)
def generate_onnx_graph(dim, nbnode, input_name='X1'): """Generates a series of consecutive additions.""" matrices = [] i1 = input_name for i in range(nbnode - 1): i2 = random_binary_classification(1, dim)[0].astype(numpy.float32) matrices.append(i2) node = OnnxAdd(i1, i2, op_version=__max_supported_opset__) i1 = node i2 = random_binary_classification(1, dim)[0].astype(numpy.float32) matrices.append(i2) node = OnnxAdd(i1, i2, output_names=['Y'], op_version=__max_supported_opset__) onx = node.to_onnx([(input_name, FloatTensorType((None, dim)))], outputs=[('Y', FloatTensorType((None, dim)))]) onx.ir_version = get_ir_version(__max_supported_opset__) return onx, matrices
def test_onnxt_runtime_add(self): idi = numpy.identity(2, dtype=numpy.float32) onx = OnnxAdd('X', idi, output_names=['Y1'], op_version=TARGET_OPSET) model_def = onx.to_onnx({'X': idi.astype(numpy.float32)}) X = numpy.array([[1, 2], [3, 4]], dtype=numpy.float32) model_def.ir_version = get_ir_version(TARGET_OPSET) oinf = OnnxInference(model_def, runtime='onnxruntime1') got = oinf.run({'X': X}) self.assertEqual(list(sorted(got)), ['Y1']) self.assertEqualArray(idi + X, got['Y1'], decimal=6) oinf = OnnxInference(model_def, runtime='onnxruntime2') got = oinf.run({'X': X}) self.assertEqual(list(sorted(got)), ['Y1']) self.assertEqualArray(idi + X, got['Y1'], decimal=6) oinf = OnnxInference(model_def, runtime='onnxruntime1', inplace=False) got = oinf.run({'X': X}, intermediate=True) self.assertEqual(list(sorted(got)), ['Ad_Addcst', 'X', 'Y1']) self.assertEqualArray(idi + X, got['Y1'], decimal=6)
def test_onnx_init_sparse_coo(self): row = np.array([0, 0, 1, 3, 1], dtype=np.float32) col = np.array([0, 2, 1, 3, 1], dtype=np.float32) data = np.array([1, 1, 1, 1, 1], dtype=np.float32) X = coo_matrix((data, (row, col)), shape=(4, 4)) node = OnnxAdd('X', X, output_names=['Y'], op_version=TARGET_OPSET) model_def = node.to_onnx({'X': X}, outputs=[('Y', FloatTensorType())]) try: sess = InferenceSession(model_def.SerializeToString()) except (RuntimeError, OrtInvalidArgument): # Sparse tensor is not supported for constant. return try: res = sess.run(None, {'X': X})[0] except RuntimeError as e: # Sparse tensor is not supported for constant. warnings.warn("Unable to run with %r\n---\n%s\n%s" % ({ 'X': X }, model_def, e)) return assert_almost_equal(X + X, res)
def test_onnx_shape_inference_lr(self): dtype = numpy.float32 x = numpy.array([1, 2, 4, 5, 5, 4]).astype(numpy.float32).reshape( (3, 2)) for opset in TestOnnxShapeInference.opsets: with self.subTest(opset=opset): cop = OnnxAdd('X', numpy.array([[1, 1]], dtype=dtype), op_version=opset) cop4 = OnnxAdd(cop, numpy.array([[2]], dtype=dtype), op_version=opset, output_names=['Y']) model_def = cop4.to_onnx({'X': x}, target_opset=opset) rt = OnnxShapeInference(model_def) self.assertIn('OnnxShapeInference(', repr(rt)) out = rt.run({'X': x}) self.assertIn('X', out) self.assertIn('Y', out) self.assertIn('Ad_Addcst', out) self.assertEqual(len(out), 5) self.assertIn( "'Ad_C0': ShapeResult('Ad_C0', ['_0', 2], dtype('float32')", str(out)) self.check_infer_shapes(model_def, rt.run(), rt) cons = rt.known_shapes_.get_all_constraints() self.assertEqual(len(cons), 1) self.assertEqual(list(cons), ['_1']) self.assertEqual(len(cons['_1']), 1) cst = cons['_1'][0] self.assertEqual(cst.name, '_1') self.assertEqual(cst.values, {'_0'}) self.assertEqual(rt.known_shapes_.names, { '_0': ('', 'X', 0), '_1': ('', 'Y', 0) })
import sklearn import numpy import matplotlib.pyplot as plt import os from onnx.tools.net_drawer import GetPydotGraph, GetOpNodeProducer from onnx import ModelProto import onnx from skl2onnx.algebra.onnx_ops import OnnxAdd, OnnxMul onnx_fct = OnnxAdd(OnnxMul('X', numpy.array([2], dtype=numpy.float32)), numpy.array([[1, 0], [0, 1]], dtype=numpy.float32), output_names=['Y']) X = numpy.array([[4, 5], [-2, 3]], dtype=numpy.float32) model = onnx_fct.to_onnx({'X': X}) print(model) filename = "example1.onnx" with open(filename, "wb") as f: f.write(model.SerializeToString()) ################################# # Draw a model with ONNX # ++++++++++++++++++++++ # We use `net_drawer.py # <https://github.com/onnx/onnx/blob/master/onnx/tools/net_drawer.py>`_ # included in *onnx* package. # We use *onnx* to load the model # in a different way than before.
def _onnx_n_penalty_elastic_error(target_opset=None, dtype=numpy.float32, weight_name=None, l1_weight=0.01, l2_weight=0.01, n_tensors=1, loss_shape=(1, 1)): """ Returns the ONNX graph for function :math:`Y = f(W) = \\beta \\lVert W \\rVert + \\alpha \\lVert W \\rVert^2` *l1_weight* is :math:`\\beta` and *l2_weight* is :math:`\\alpha`. It does that for *n_tensors* and adds all of the results to an input loss. .. gdot:: :script: DOT-SECTION from mlprodict.onnxrt import OnnxInference from onnxcustom.utils.onnx_function import function_onnx_graph model_onnx = function_onnx_graph( 'n_penalty_elastic_error', n_tensors=2) oinf = OnnxInference(model_onnx, inplace=False) print("DOT-SECTION", oinf.to_dot()) """ from skl2onnx.algebra.onnx_ops import (OnnxMul, OnnxAdd, OnnxReduceSumSquare, OnnxReduceSum, OnnxAbs, OnnxReshape) if n_tensors <= 0: raise ValueError( # pragma: no cover "This function is useless if the number of tensors is null.") var_type = dtype_to_var_type(dtype) varsx = [('loss', var_type(loss_shape))] names = ['loss'] for n in range(n_tensors): name = 'W%d' % n abs_diff = OnnxAbs(name, op_version=target_opset) res_l1 = OnnxReduceSum(abs_diff, op_version=target_opset) # res2_l1 = OnnxSign(diff, op_version=target_opset) res_l2 = OnnxReduceSumSquare(name, op_version=target_opset) # res2_l2 = diff res = OnnxAdd(OnnxMul(res_l1, numpy.array([l1_weight], dtype=dtype), op_version=target_opset), OnnxMul(res_l2, numpy.array([l2_weight], dtype=dtype), op_version=target_opset), op_version=target_opset) names.append(res) varsx.append(('W%d' % n, var_type())) if len(names) == 2: res = OnnxAdd(*names, op_version=target_opset) else: res = OnnxAdd(names[1], names[2], op_version=target_opset) for i in range(3, len(names)): res = OnnxAdd(res, names[i], op_version=target_opset) res = OnnxAdd(names[0], res, op_version=target_opset) res = OnnxReshape(res, numpy.array([-1], numpy.int64), op_version=target_opset, output_names=['Y']) onx = res.to_onnx(varsx, outputs=[('Y', var_type([None]))], target_opset=target_opset) return onx
def _onnx_grad_penalty_elastic_error(target_opset=None, dtype=numpy.float32, l1_weight=0.01, l2_weight=0.01): """ Returns the ONNX graph for function :math:`Y = f(W) = \\beta \\lVert W \\rVert + \\alpha \\lVert W \\rVert^2` *l1_weight* is :math:`\\beta` and *l2_weight* is :math:`\\alpha`. .. gdot:: :script: DOT-SECTION from mlprodict.onnxrt import OnnxInference from onnxcustom.utils.onnx_function import function_onnx_graph model_onnx = function_onnx_graph('grad_penalty_elastic_error') oinf = OnnxInference(model_onnx, inplace=False) print("DOT-SECTION", oinf.to_dot()) """ from skl2onnx.algebra.onnx_ops import (OnnxMul, OnnxAdd, OnnxReduceSumSquare, OnnxReduceSum, OnnxSign, OnnxAbs, OnnxReshape) diff = 'X' abs_diff = OnnxAbs(diff, op_version=target_opset) res_l1 = OnnxReduceSum(abs_diff, op_version=target_opset) res2_l1 = OnnxSign(diff, op_version=target_opset) res_l2 = OnnxReduceSumSquare(diff, op_version=target_opset) res2_l2 = diff res = OnnxAdd(OnnxMul(res_l1, numpy.array([l1_weight], dtype=dtype), op_version=target_opset), OnnxMul(res_l2, numpy.array([l2_weight], dtype=dtype), op_version=target_opset), op_version=target_opset) res = OnnxReshape(res, numpy.array([-1], numpy.int64), op_version=target_opset, output_names=['Y']) res2 = OnnxAdd(OnnxMul(res2_l1, numpy.array([l1_weight], dtype=dtype), op_version=target_opset), OnnxMul(res2_l2, numpy.array([l2_weight * (2)], dtype=dtype), op_version=target_opset), op_version=target_opset, output_names=['Y_grad']) var_type = dtype_to_var_type(dtype) varsx = [('X', var_type([None, None]))] onx = res.to_onnx(varsx, outputs=[('Y', var_type([None])), ('Y_grad', var_type())], target_opset=target_opset, other_outputs=[res2]) return onx
import matplotlib.pyplot as plt import os from onnx.tools.net_drawer import GetPydotGraph, GetOpNodeProducer from onnx import ModelProto import onnx from skl2onnx.algebra.onnx_ops import OnnxAdd, OnnxMul onnx_fct = OnnxAdd(OnnxMul('X', numpy.array([2], dtype=numpy.float32), op_version=12), numpy.array([[1, 0], [0, 1]], dtype=numpy.float32), output_names=['Y'], op_version=12) X = numpy.array([[4, 5], [-2, 3]], dtype=numpy.float32) model = onnx_fct.to_onnx({'X': X}, target_opset=12) print(model) filename = "example1.onnx" with open(filename, "wb") as f: f.write(model.SerializeToString()) ################################# # Draw a model with ONNX # ++++++++++++++++++++++ # We use `net_drawer.py # <https://github.com/onnx/onnx/blob/master/onnx/tools/net_drawer.py>`_ # included in *onnx* package. # We use *onnx* to load the model # in a different way than before.