Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 0 additions & 1 deletion _doc/examples/plot_benchmark_op_leakyrelu.py
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,6 @@
.. contents::
:local:


The ONNX graphs for both implementations of LeakyRely
+++++++++++++++++++++++++++++++++++++++++++++++++++++

Expand Down
5 changes: 3 additions & 2 deletions _doc/examples/plot_benchmark_op_short.py
Original file line number Diff line number Diff line change
Expand Up @@ -149,8 +149,9 @@ def build_ort_op(op_version=14, save=None, slices=None): # opset=13, 14, ...
shape=str(shape).replace(
" ", ""), slice=str(slices).replace(
" ", ""))
r = measure_time('sess.run(None, dx)', number=number, div_by_number=True,
context={'sess': sess, 'dx': {'X': x}})
r = measure_time(lambda: sess.run(None, {'X': x}),
number=number, div_by_number=True,
context={})
obs.update(r)
obs['provider'] = 'CPU'
data.append(obs)
Expand Down
2 changes: 1 addition & 1 deletion _doc/sphinxdoc/source/conf.py
Original file line number Diff line number Diff line change
Expand Up @@ -159,7 +159,7 @@ def callback_begin():
'C_OrtValue':
'http://www.xavierdupre.fr/app/onnxcustom/helpsphinx/'
'onnxmd/onnxruntime_python/ortvalue.html#c-class-ortvaluevector',
'Contrib Operators' :
'Contrib Operators':
'http://www.xavierdupre.fr/app/onnxcustom/helpsphinx/onnxmd/'
'onnxruntime_docs/ContribOperators.html',
'Gemm':
Expand Down
2 changes: 1 addition & 1 deletion _doc/sphinxdoc/source/tutorial_onnx/challenges.rst
Original file line number Diff line number Diff line change
Expand Up @@ -121,7 +121,7 @@ Then unit test must be updated.
* Update unit test.

The PR should include the modified files and the modified markdown documentation,
usually a subset of
usually a subset of
`docs/docs/Changelog-ml.md`, `docs/Changelog.md`,
`docs/Operators-ml.md`, `docs/Operators.md`,
`docs/TestCoverage-ml.md`, `docs/TestCoverage.md`.
2 changes: 1 addition & 1 deletion _doc/sphinxdoc/source/tutorial_onnx/concepts.rst
Original file line number Diff line number Diff line change
Expand Up @@ -397,7 +397,7 @@ One example is the operator CDist. Notebook `Pairwise distances with ONNX (pdist
goes into the details of it. Pairwise distances, as shown in section
:ref:`l-operator-scan-onnx-tutorial`, can be implemented with operator
Scan. However, a dedicated operator called CDist is proved significantly
faster, significantly to make the effort to implement a dedicated runtime
faster, significantly to make the effort to implement a dedicated runtime
for it.

Shape (and Type) Inference
Expand Down
25 changes: 24 additions & 1 deletion _unittests/ut_training/test_optimizers_forward_backward.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@
import io
import pickle
import logging
from pyquickhelper.pycode import ExtTestCase, ignore_warnings
from pyquickhelper.pycode import ExtTestCase, ignore_warnings, skipif_appveyor
import numpy
from onnx.helper import set_model_props
from sklearn.datasets import make_regression
Expand Down Expand Up @@ -111,6 +111,7 @@ def test_ort_gradient_optimizers_use_numpy_exc(self):
ConvergenceError)

@unittest.skipIf(TrainingSession is None, reason="not training")
@skipif_appveyor("logging issue")
def test_ort_gradient_optimizers_use_numpy_log(self):
from onnxcustom.training.optimizers_partial import OrtGradientForwardBackwardOptimizer
X, y = make_regression( # pylint: disable=W0632
Expand All @@ -135,6 +136,28 @@ def test_ort_gradient_optimizers_use_numpy_log(self):
self.assertTrue(res is train_session)
self.assertIn("[OrtGradientForwardBackwardOptimizer._iteration]", logs)

@unittest.skipIf(TrainingSession is None, reason="not training")
def test_ort_gradient_optimizers_use_numpy_log_appveyor(self):
from onnxcustom.training.optimizers_partial import OrtGradientForwardBackwardOptimizer
X, y = make_regression( # pylint: disable=W0632
100, n_features=2, bias=2, random_state=0)
X[:10, :] = 0
X = X.astype(numpy.float32)
y = (X.sum(axis=1) + y / 1000).astype(numpy.float32)
X_train, _, y_train, __ = train_test_split(X, y)
reg = LinearRegression()
reg.fit(X_train, y_train)
reg.coef_ = reg.coef_.reshape((1, -1))
onx = to_onnx(reg, X_train, target_opset=opset,
black_op={'LinearRegressor'})
# onx = onnx_rename_weights(onx)
set_model_props(onx, {'info': 'unit test'})
inits = ['coef', 'intercept']
train_session = OrtGradientForwardBackwardOptimizer(
onx, inits, enable_logging=True)
res = train_session.fit(X, y, use_numpy=True)
self.assertTrue(res is train_session)

@unittest.skipIf(TrainingSession is None, reason="not training")
def test_ort_gradient_optimizers_use_numpy_pickle(self):
from onnxcustom.training.optimizers_partial import OrtGradientForwardBackwardOptimizer
Expand Down
54 changes: 41 additions & 13 deletions _unittests/ut_training/test_orttraining_forward_backward.py
Original file line number Diff line number Diff line change
Expand Up @@ -25,12 +25,15 @@

class TestOrtTrainingForwardBackward(ExtTestCase):

def forward_no_training(self):
def forward_no_training(self, exc=None, verbose=False):
if exc is None:
exc = __name__ != '__main__'
from onnxruntime.capi._pybind_state import (
OrtValue as C_OrtValue, OrtDevice, OrtMemType)
OrtValue as C_OrtValue, OrtDevice as C_OrtDevice, OrtMemType)
from onnxruntime.capi._pybind_state import (
OrtValueVector)
from onnxcustom.training.ortgradient import OrtGradientForwardBackward

X, y = make_regression( # pylint: disable=W0632
100, n_features=10, bias=2)
X = X.astype(numpy.float32)
Expand All @@ -43,10 +46,17 @@ def forward_no_training(self):
black_op={'LinearRegressor'})

# starts testing
self.assertRaise(
lambda: OrtGradientForwardBackward(
onx, debug=True, enable_logging=True, providers=['NONE']),
ValueError)
if verbose:
print("[forward_no_training] start testing")
if exc:
if verbose:
print("[forward_no_training] check exception")
self.assertRaise(
lambda: OrtGradientForwardBackward(
onx, debug=True, enable_logging=True, providers=['NONE']),
ValueError)
if verbose:
print("[forward_no_training] instantiate")
forback = OrtGradientForwardBackward(
onx, debug=True, enable_logging=True)
self.assertEqual(repr(forback), "OrtGradientForwardBackward(...)")
Expand All @@ -64,16 +74,25 @@ def forward_no_training(self):
['X_grad', 'coef_grad', 'intercept_grad'])
self.assertEqual(forback.cls_type_._output_names, ['variable'])

if verbose:
print("[forward_no_training] expected prediction")

expected = reg.predict(X_test)
coef = reg.coef_.astype(numpy.float32).reshape((-1, 1))
intercept = numpy.array([reg.intercept_], dtype=numpy.float32)

if verbose:
print("[forward_no_training] InferenceSession")

sess0 = InferenceSession(onx.SerializeToString())
inames = [i.name for i in sess0.get_inputs()] # pylint: disable=E1101
self.assertEqual(inames, ['X'])
got = sess0.run(None, {'X': X_test})
self.assertEqualArray(expected.ravel(), got[0].ravel(), decimal=4)

if verbose:
print("[forward_no_training] evaluation")

sess_eval = forback.cls_type_._sess_eval # pylint: disable=E1101
inames = [i.name for i in sess_eval.get_inputs()]
self.assertEqual(inames, ['X', 'coef', 'intercept'])
Expand All @@ -82,8 +101,10 @@ def forward_no_training(self):
self.assertEqualArray(expected.ravel(), got[0].ravel(), decimal=4)

# OrtValue
if verbose:
print("[forward_no_training] OrtValue")
inst = forback.new_instance()
device = OrtDevice(OrtDevice.cpu(), OrtMemType.DEFAULT, 0)
device = C_OrtDevice(C_OrtDevice.cpu(), OrtMemType.DEFAULT, 0)

# list of OrtValues
inputs = []
Expand All @@ -95,6 +116,8 @@ def forward_no_training(self):
self.assertEqualArray(expected.ravel(), got[0].ravel(), decimal=4)

# OrtValueVector
if verbose:
print("[forward_no_training] OrtValueVector")
inputs = OrtValueVector()
for a in [X_test, coef, intercept]:
inputs.push_back(C_OrtValue.ortvalue_from_numpy(a, device))
Expand All @@ -104,16 +127,20 @@ def forward_no_training(self):
expected.ravel(), got[0].numpy().ravel(), decimal=4)

# numpy
if verbose:
print("[forward_no_training] numpy")
inputs = [X_test, coef, intercept]
got = inst.forward(inputs)
self.assertEqual(len(got), 1)
self.assertEqualArray(
expected.ravel(), got[0].numpy().ravel(), decimal=4)
if verbose:
print("[forward_no_training] end")

@unittest.skipIf(TrainingSession is None, reason="no training")
def test_forward_no_training(self):
res, logs = self.assertLogging(
self.forward_no_training, 'onnxcustom')
lambda: self.forward_no_training(exc=True), 'onnxcustom')
self.assertEmpty(res)
if len(logs) > 0:
self.assertIn("[OrtGradientForwardBackward]", logs)
Expand All @@ -122,7 +149,7 @@ def test_forward_no_training(self):
@unittest.skipIf(TrainingSession is None, reason="no training")
def test_forward_no_training_pickle(self):
from onnxruntime.capi._pybind_state import (
OrtValue as C_OrtValue, OrtDevice, OrtMemType)
OrtValue as C_OrtValue, OrtMemType, OrtDevice as C_OrtDevice)
from onnxruntime.capi._pybind_state import (
OrtValueVector)
from onnxcustom.training.ortgradient import OrtGradientForwardBackward
Expand Down Expand Up @@ -176,7 +203,7 @@ def test_forward_no_training_pickle(self):
# OrtValue
inst = forback.new_instance()
inputs = []
device = OrtDevice(OrtDevice.cpu(), OrtMemType.DEFAULT, 0)
device = C_OrtDevice(C_OrtDevice.cpu(), OrtMemType.DEFAULT, 0)
for a in [X_test, coef, intercept]:
inputs.append(C_OrtValue.ortvalue_from_numpy(a, device))
got_ort = inst.forward(inputs)
Expand All @@ -203,7 +230,7 @@ def test_forward_no_training_pickle(self):

def forward_training(self, model, debug=False, n_classes=3, add_print=False):
from onnxruntime.capi._pybind_state import (
OrtValue as C_OrtValue, OrtDevice, OrtMemType)
OrtValue as C_OrtValue, OrtMemType, OrtDevice as C_OrtDevice)
from onnxruntime.capi._pybind_state import (
OrtValueVector)
from onnxcustom.training.ortgradient import OrtGradientForwardBackward
Expand Down Expand Up @@ -284,7 +311,7 @@ def to_proba(yt):

# OrtValue
inst = forback.new_instance()
device = OrtDevice(OrtDevice.cpu(), OrtMemType.DEFAULT, 0)
device = C_OrtDevice(C_OrtDevice.cpu(), OrtMemType.DEFAULT, 0)

# OrtValueVector
if add_print:
Expand Down Expand Up @@ -370,4 +397,5 @@ def test_forward_training_logreg(self):


if __name__ == "__main__":
unittest.main()
# TestOrtTrainingForwardBackward().forward_no_training(verbose=True)
unittest.main(verbosity=2)
23 changes: 19 additions & 4 deletions _unittests/ut_utils/test_onnxruntime_helper.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,9 @@
import unittest
from pyquickhelper.pycode import ExtTestCase
from onnxcustom.utils.onnxruntime_helper import (
device_to_provider, provider_to_device, get_ort_device_type)
provider_to_device, get_ort_device_type,
get_ort_device, ort_device_to_string,
device_to_providers)


class TestOnnxRuntimeHelper(ExtTestCase):
Expand All @@ -15,15 +17,28 @@ def test_provider_to_device(self):
self.assertRaise(lambda: provider_to_device('NONE'), ValueError)

def test_device_to_provider(self):
self.assertEqual(device_to_provider('cpu'), 'CPUExecutionProvider')
self.assertEqual(device_to_provider('gpu'), 'CUDAExecutionProvider')
self.assertRaise(lambda: device_to_provider('NONE'), ValueError)
self.assertEqual(device_to_providers('cpu'), ['CPUExecutionProvider'])
self.assertEqual(device_to_providers('gpu'), ['CUDAExecutionProvider'])
self.assertRaise(lambda: device_to_providers('NONE'), ValueError)

def test_get_ort_device_type(self):
self.assertEqual(get_ort_device_type('cpu'), 0)
self.assertEqual(get_ort_device_type('cuda'), 1)
self.assertRaise(lambda: get_ort_device_type('none'), ValueError)

def test_ort_device_to_string(self):
for value in ['cpu', 'cuda', ('gpu', 'cuda'),
('gpu:0', 'cuda'), ('cuda:0', 'cuda'),
('gpu:1', 'cuda:1'), 'cuda:1']:
with self.subTest(device=value):
if isinstance(value, str):
a, b = value, value
else:
a, b = value
dev = get_ort_device(a)
back = ort_device_to_string(dev)
self.assertEqual(b, back)


if __name__ == "__main__":
unittest.main()
Loading