Missing initializer support in node export functions
Issue
This issue concerns the fact that, as far as I understand, it is currently not possible to add initializers to an exported ONNX graph from the export node functions.
The method by which Aidge exports and adds initializers is by looking through the producers of the graph, but there are some special cases where an initializer or constant input has to be created during export.
For example, in the case of Quantizer -> QuantizeLinear
: in Aidge, a Quantizer is a meta-operator that has its producer inside, meaning the export function does not register it as an initializer. This choice has some logic behind it that I will not explain here, as it is not the subject of this issue.
But the main problem lies in the fact that if a node expects to have an initializer connected to its inputs and it is not present in the Aidge model, then the only choice is to create constant nodes to simulate the same behavior.
For clarity, an initializer is a constant tensor stored in the model's initializer list, contrary to a constant node that is simply another operator.
Personally, this solution works for inference on ONNX Runtime, but if ONNX expects an initializer, I do feel like Aidge should do its best to uphold that. Additionally, this is causing problems in the import ONNX -> Aidge, because constants are treated differently from initializers.
During import Aidge only provides the import function of a node with the initializers connected to the node which can cause problems if the initializers of a node need to be accessed (also quantizelinear's case).
Although no other issues have been observed regarding this behavior so far, it is probable that internally on ONNX too there may be some problems caused by the distinction between constant nodes and expected initializers.
Proposed solution
The solution that I have in mind includes several, but simple, changes:
- Modify the signature of the "Aidge converters"/"node exporters" so they can output initializers, which can later be added to the
onnx_initializers
list. - In
convert_aidge_to_onnx
, add the initializers output by the node export functions to theonnx_initializers
variable so they are successfully added to the graph.
The first modification would involve changing the function signature in every node export file and requiring a second output (which would be None
or an empty list []
for most nodes).
The second modification would only entail a simple inclusion of the output into the already-used onnx_initializers
list.
In code, the changes would look like this:
Signature change:
func(aidge_node: aidge_core.Node,
node_inputs_name: List[str],
node_outputs_name: List[str],
opset: Optional[int] = None,
**kwargs) -> List[helper.NodeProto]:
to
func(aidge_node: aidge_core.Node,
node_inputs_name: List[str],
node_outputs_name: List[str],
opset: Optional[int] = None,
**kwargs) -> tuple[List[helper.NodeProto], List[TensorProto]]:
Inside the exporters:
@auto_register_export("operator")
def export_operator(
aidge_node: aidge_core.Node,
node_inputs_name: List[str],
node_outputs_name: List[str],
opset: Optional[int] = None,
**kwargs) -> tuple[List[helper.NodeProto], List[TensorProto]]:
# Export actions for the node
onnx_nodes = # onnx nodes created
node_initializers = # Initializers that are to be added to the graph
return onnx_nodes, node_initializers
In most cases, this second return value would be an empty list []
or None
because of the no need to add initializers by most nodes.
aidge_onnx/onnx_export
, change:
In new_nodes = AIDGE_NODE_CONVERTER_[aidge_node.type()](
aidge_node,
node_inputs_name,
node_outputs_name,
opset=opset,
enable_custom_op=enable_custom_op
)
to
# Get new output of functions
new_nodes, new_initializers = AIDGE_NODE_CONVERTER_[aidge_node.type()](
aidge_node,
node_inputs_name,
node_outputs_name,
opset=opset,
enable_custom_op=enable_custom_op
)
# Add to the initializers list if it exists
if new_initializers != []:
onnx_initializers.extend(new_initializers)
# or
# if new_initializers is not None:
# onnx_initializers.extend(new_initializers)