New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Expose a Python interface for inference functions #4409
Conversation
0442057
to
0d33d68
Compare
@gramalingam Would you mind viewing the proposal if this sort of interface would work? In the future it could be extended to support the other arguments, they could be optional so it's backward compatible. |
Updating the pyi definition for OpSchema would be useful. |
When it comes to the Python-side interface: A node has input/output names, operator name & domain, attributes. Own name and docstring don't matter. We are missing basically only the operator version it seems, and the input types. I see some variations of the possible signature:
Also, where would we put this function? Let me know your thoughts and I'll get started on some improvements in the Python-interface area. |
@gramalingam I pushed some changes: std::unordered_map<std::string, py::bytes> CallNodeInferenceFunction(
OpSchema* schema,
const py::bytes& nodeBytes,
std::unordered_map<std::string, py::bytes> valueTypesByNameBytes,
std::unordered_map<std::string, py::bytes> inputDataByNameBytes,
std::unordered_map<std::string, py::bytes> inputSparseDataByNameBytes) {
# class OpSchema:
def infer_node_outputs(self, node_proto: bytes, value_types: Dict[str, bytes],
input_data: Dict[str, bytes], input_sparse_data: Dict[str, bytes]
) -> Dict[str, bytes]: ...
# shape_inference.py
def infer_node_outputs(
schema: onnx.defs.OpSchema, node: onnx.NodeProto, input_types: Dict[str, onnx.TypeProto],
input_data: Optional[Dict[str, onnx.TensorProto]] = None,
input_sparse_data: Optional[Dict[str, onnx.SparseTensorProto]] = None
) -> Dict[str, onnx.TypeProto]: ...
Let me know what you think of these changes! I also added some more tests. |
4363146
to
da9b92a
Compare
@@ -85,6 +136,10 @@ PYBIND11_MODULE(onnx_cpp2py_export, onnx_cpp2py_export) { | |||
return py::bytes(bytes); | |||
}) | |||
.def_property_readonly("has_context_dependent_function", &OpSchema::HasContextDependentFunction) | |||
.def("infer_node_outputs", CallNodeInferenceFunction, | |||
py::arg("nodeBytes"), py::arg("valueTypesByNameBytes"), | |||
py::arg("inputDataByNameBytes") = std::unordered_map<std::string, py::bytes>{}, |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
None is better than an empty container as a default value.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I don't think I know what you mean here. This is C++ side, so there's no None. Do you mean to make it a pointer and use nullptr/use std::optional?
I think that this wouldn't be a lot better as the map isn't mutated and also in this it makes sense that the default is "no additional information" (for the inference context we have to pass in some map, and it makes sense to make it empty as there's no input data we know).
Could you provide a code example for the change?
60d4f8a
to
c07b372
Compare
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Looks great, thanks very much!
Signed-off-by: KubinGH <kbachurski@gmail.com>
Signed-off-by: KubinGH <kbachurski@gmail.com>
Signed-off-by: KubinGH <kbachurski@gmail.com>
Signed-off-by: KubinGH <kbachurski@gmail.com>
Signed-off-by: KubinGH <kbachurski@gmail.com>
Signed-off-by: KubinGH <kbachurski@gmail.com>
Signed-off-by: KubinGH <kbachurski@gmail.com>
Signed-off-by: KubinGH <kbachurski@gmail.com>
Signed-off-by: KubinGH <kbachurski@gmail.com>
Signed-off-by: KubinGH <kbachurski@gmail.com>
Signed-off-by: KubinGH <kbachurski@gmail.com>
Signed-off-by: KubinGH <kbachurski@gmail.com>
Signed-off-by: KubinGH <kbachurski@gmail.com>
Signed-off-by: KubinGH <kbachurski@gmail.com>
Signed-off-by: KubinGH <kbachurski@gmail.com>
Signed-off-by: KubinGH <kbachurski@gmail.com>
Signed-off-by: KubinGH <kbachurski@gmail.com>
b1b8742
to
0b0d99d
Compare
Thanks! |
def infer_node_outputs( | ||
schema: onnx.defs.OpSchema, | ||
node: onnx.NodeProto, | ||
input_types: Dict[str, onnx.TypeProto], |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Do we explicitly require a dictionary for these params? If not prefer a more generic type like Mapping.
——-
Use more generic types for input parameters and specific types for return values. For example, a function may take a Sequence
and return a List
.
Diagram for reference: https://gist.github.com/justinchuby/4021cebe9e093f636759a88de325c85f
* Add an experimental infer_types implementation Signed-off-by: KubinGH <kbachurski@gmail.com> * Create infers_.py Signed-off-by: KubinGH <kbachurski@gmail.com> * Fix naming Signed-off-by: KubinGH <kbachurski@gmail.com> * Replace example script with tests Signed-off-by: KubinGH <kbachurski@gmail.com> * Use unittest Signed-off-by: KubinGH <kbachurski@gmail.com> * Use unittest Signed-off-by: KubinGH <kbachurski@gmail.com> * Fix wrapper function signature Signed-off-by: KubinGH <kbachurski@gmail.com> * Get rid of existing getter Signed-off-by: KubinGH <kbachurski@gmail.com> * Run C++ formatter Signed-off-by: KubinGH <kbachurski@gmail.com> * Improve C++ implementation, Python interface, tests Signed-off-by: KubinGH <kbachurski@gmail.com> * Fix CI Signed-off-by: KubinGH <kbachurski@gmail.com> * Use explicit enums for tensor elements Signed-off-by: KubinGH <kbachurski@gmail.com> * Run black and isort for new linter Signed-off-by: KubinGH <kbachurski@gmail.com> * Specify reshape vector dtype Signed-off-by: KubinGH <kbachurski@gmail.com> * Make binding-side attributes optional Signed-off-by: KubinGH <kbachurski@gmail.com> * Run clang-format Signed-off-by: KubinGH <kbachurski@gmail.com> * Make OpSchema method explicitly protected Signed-off-by: KubinGH <kbachurski@gmail.com> * Missed stub file protected Signed-off-by: KubinGH <kbachurski@gmail.com> Signed-off-by: KubinGH <kbachurski@gmail.com>
Exposes a node-level API for performing type/shape inference to Python bindings.
Description
(Updated)
OpSchema._infer_node_outputs
, to which serialised protobuf bytes are passed - arguments: schema, node, input types, input data/other inference context arguments, returns: inferred output types.shape_inference.infer_node_outputs
:ValidationError
s andInferenceError
s are raised.OpSchema._infer_node_outputs
is internal to the implementation.input_types
keys are named likenode
declares its inputs.input_data
andinput_sparse_data
are used for passing in known constant inputs (as per C++ usage).GraphInferenceContext
in the future.Motivation and Context