Source code for mlprodict.onnxrt.model_checker
"""
Investigate issues happening with float32.
:githublink:`%|py|5`
"""
import numpy
from numpy.random import randint
[docs]def astype_range(arr, dtype=numpy.float32, force=1):
"""
Computes ranges for every number in an array
once converted into *float32*. The function returns
two matrices which produces two numbers
*a* et *b*, the number rounded to float32
is in interval :math:`[a, b]`.
:param arr: array
:param dtype: type to convert to
:param force: does something like *[i] +/- force |i - [i]|*
:return: minimum, maximum
:githublink:`%|py|21`
"""
conv = arr.astype(dtype)
delta = numpy.abs(arr - conv)
delta = numpy.maximum(numpy.abs(arr) * 1e-7, delta)
maxa = (conv + delta * force).astype(dtype)
mina = (conv - delta * force).astype(dtype)
return mina, maxa
[docs]def onnx_shaker(oinf, inputs, output_fct, n=100, dtype=numpy.float32, force=1):
"""
Shakes a model :epkg:`ONNX`.
Explores the ranges for every prediction.
Uses :func:`astype_range <mlprodict.onnxrt.model_checker.astype_range>`
:param oinf: object of type :class:`OnnxInference <mlprodict.onnxrt.onnx_inference.OnnxInference>`
:param inputs: inputs
:param output_fct: output function which extracts
a single array from the output
:param dtype: type to convert to
:param force: does something like *[i] +/- force |i - [i]|*
:return: ranges for each predictions
See notebook :ref:`onnxshakerrst` for an example of use.
:githublink:`%|py|74`
"""
results = None
for i, new_inputs in enumerate(enumerate_random_inputs(
inputs, n=n, dtype=dtype, force=force)):
res_ = oinf.run(new_inputs)
res = output_fct(res_)
sq = numpy.squeeze(res)
if len(sq.shape) != 1:
raise ValueError( # pragma: no cover
"The function only works with shape={}".format(sq.shape))
if results is None:
results = numpy.empty((sq.shape[0], n), dtype=sq.dtype)
results[:, i] = sq
results.sort(axis=1)
return results