diff --git a/.github/workflows/ci-platform-generic.yml b/.github/workflows/ci-platform-generic.yml index 6d690befc1..3df422a742 100644 --- a/.github/workflows/ci-platform-generic.yml +++ b/.github/workflows/ci-platform-generic.yml @@ -94,4 +94,5 @@ jobs: miniMobileNet miniMobileNetv2 CCT/CCT_1_16_16_8 + CCT/CCT_2_32_32_128_Opset20 testFloatDemoTinyViT diff --git a/.github/workflows/ci-platform-siracusa.yml b/.github/workflows/ci-platform-siracusa.yml index bee1263539..7c6a5f7541 100644 --- a/.github/workflows/ci-platform-siracusa.yml +++ b/.github/workflows/ci-platform-siracusa.yml @@ -85,5 +85,6 @@ jobs: MLPerf/ImageClassification MLPerf/AnomalyDetection CCT/CCT_1_16_16_8 + CCT/CCT_2_32_32_128_Opset20 testTrainCCT/CCT1_Classifier_Training/CCT_1_16_16_8 num-cores: 8 diff --git a/CHANGELOG.md b/CHANGELOG.md index d14570d4b1..24ca048aaa 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -13,6 +13,7 @@ This file contains the changelog for the Deeploy project. The changelog is divid - Node Mangling to avoid duplication [#93](https://github.com/pulp-platform/Deeploy/pull/93) - Prepare Post v0.2.0 Release [#104](https://github.com/pulp-platform/Deeploy/pull/104) - Use Docker digests instead of arch-specific tags [#106](https://github.com/pulp-platform/Deeploy/pull/106) +- Fix `Unsqueeze` Op. when using ONNX opset 13 or higher (from attribute to input) [#119](https://github.com/pulp-platform/Deeploy/pull/119) ### Added - Add manual type inference feature (CLI: `--input-type-map`/`--input-offset-map`) to resolve ambiguities when test inputs are not representative enough @@ -74,6 +75,7 @@ This file contains the changelog for the Deeploy project. The changelog is divid - Fixed multiple typos in variable and method names, such as changing `includeGobalReferences` to `includeGlobalReferences` and `dicardedMappers` to `discardedMappers` - Corrected method usage in `importDeeployState` to call `NetworkContext.importNetworkContext` instead of the incorrect method name - Correctly return `signProp` from `setupDeployer` instead of hardcoding the value to `False` in `testMVP.py` +- Fixed `Unsqueeze` Op. when using ONNX opset 13 or higher (from attribute to input) ### Removed - Delete outdated and unused `.gitlab-ci.yml` file diff --git a/Deeploy/Targets/Generic/Parsers.py b/Deeploy/Targets/Generic/Parsers.py index 39372c5144..3c3a3472c0 100644 --- a/Deeploy/Targets/Generic/Parsers.py +++ b/Deeploy/Targets/Generic/Parsers.py @@ -940,10 +940,19 @@ def __init__(self): def parseNode(self, node: gs.Node) -> (bool): - ret = all(['axes' in node.attrs, len(node.inputs) == 1, len(node.outputs) == 1]) + # ONNX v11: 'axes' is a node attribute + if 'axes' in node.attrs: + ret = all(['axes' in node.attrs, len(node.inputs) == 1, len(node.outputs) == 1]) + # ONNX v13+: 'axes' becomes an input with the data + # Source: https://onnx.ai/onnx/operators/onnx__Unsqueeze.html + else: + ret = all([len(node.inputs) == 2, len(node.outputs) == 1]) - if ret: - self.operatorRepresentation['axes'] = node.attrs['axes'] + if ret and 'axes' in node.attrs: + axes_attr = node.attrs['axes'] + self.operatorRepresentation['axes'] = [int(axes_attr)] if isinstance(axes_attr, int) \ + else [int(a) for a in axes_attr] + # For opset 13+, axes will be extracted from the second input in parseNodeCtxt return ret @@ -952,13 +961,26 @@ def parseNodeCtxt(self, node: gs.Node, channels_first: bool = True) -> Tuple[NetworkContext, bool]: - inputs = ['data_in'] outputs = ['data_out'] - - for idx, inputNode in enumerate(node.inputs): - self.operatorRepresentation[inputs[idx]] = ctxt.lookup(inputNode.name).name - for idx, outputNode in enumerate(node.outputs): - self.operatorRepresentation[outputs[idx]] = ctxt.lookup(outputNode.name).name + if len(node.inputs) == 1: + inputs = ['data_in'] + for idx, inputNode in enumerate(node.inputs): + self.operatorRepresentation[inputs[idx]] = ctxt.lookup(inputNode.name).name + for idx, outputNode in enumerate(node.outputs): + self.operatorRepresentation[outputs[idx]] = ctxt.lookup(outputNode.name).name + else: + data_in = ctxt.lookup(node.inputs[0].name) + data_out = ctxt.lookup(node.outputs[0].name) + self.operatorRepresentation['data_in'] = data_in.name + self.operatorRepresentation['data_out'] = data_out.name + # axes must be a constant; extract values + axes_buf = ctxt.lookup(node.inputs[1].name) + assert hasattr(axes_buf, 'values'), "Unsqueeze: expected constant 'axes' input for opset 13+" + axes_vals = np.array(axes_buf.values).astype(int).flatten().tolist() + self.operatorRepresentation['axes'] = axes_vals + # Do not deploy the axes tensor + axes_buf._live = False + axes_buf._deploy = False return ctxt, True diff --git a/DeeployTest/Tests/CCT/CCT_2_32_32_128_Opset20/inputs.npz b/DeeployTest/Tests/CCT/CCT_2_32_32_128_Opset20/inputs.npz new file mode 100644 index 0000000000..de35d4d758 Binary files /dev/null and b/DeeployTest/Tests/CCT/CCT_2_32_32_128_Opset20/inputs.npz differ diff --git a/DeeployTest/Tests/CCT/CCT_2_32_32_128_Opset20/network.onnx b/DeeployTest/Tests/CCT/CCT_2_32_32_128_Opset20/network.onnx new file mode 100644 index 0000000000..fefd0c2c6d Binary files /dev/null and b/DeeployTest/Tests/CCT/CCT_2_32_32_128_Opset20/network.onnx differ diff --git a/DeeployTest/Tests/CCT/CCT_2_32_32_128_Opset20/outputs.npz b/DeeployTest/Tests/CCT/CCT_2_32_32_128_Opset20/outputs.npz new file mode 100644 index 0000000000..9686a6345d Binary files /dev/null and b/DeeployTest/Tests/CCT/CCT_2_32_32_128_Opset20/outputs.npz differ