onnx2tf 1.29.20__tar.gz → 1.29.22__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (216) hide show
  1. {onnx2tf-1.29.20 → onnx2tf-1.29.22}/PKG-INFO +29 -8
  2. {onnx2tf-1.29.20 → onnx2tf-1.29.22}/README.md +27 -6
  3. {onnx2tf-1.29.20 → onnx2tf-1.29.22}/onnx2tf/__init__.py +1 -1
  4. {onnx2tf-1.29.20 → onnx2tf-1.29.22}/onnx2tf/onnx2tf.py +31 -2
  5. {onnx2tf-1.29.20 → onnx2tf-1.29.22}/onnx2tf/ops/MaxPool.py +54 -0
  6. {onnx2tf-1.29.20 → onnx2tf-1.29.22}/onnx2tf/ops/ScatterElements.py +50 -1
  7. {onnx2tf-1.29.20 → onnx2tf-1.29.22}/onnx2tf/ops/Unique.py +71 -11
  8. {onnx2tf-1.29.20 → onnx2tf-1.29.22}/onnx2tf/utils/common_functions.py +99 -2
  9. {onnx2tf-1.29.20 → onnx2tf-1.29.22}/pyproject.toml +2 -2
  10. {onnx2tf-1.29.20 → onnx2tf-1.29.22}/onnx2tf/__main__.py +0 -0
  11. {onnx2tf-1.29.20 → onnx2tf-1.29.22}/onnx2tf/ops/Abs.py +0 -0
  12. {onnx2tf-1.29.20 → onnx2tf-1.29.22}/onnx2tf/ops/Acos.py +0 -0
  13. {onnx2tf-1.29.20 → onnx2tf-1.29.22}/onnx2tf/ops/Acosh.py +0 -0
  14. {onnx2tf-1.29.20 → onnx2tf-1.29.22}/onnx2tf/ops/Add.py +0 -0
  15. {onnx2tf-1.29.20 → onnx2tf-1.29.22}/onnx2tf/ops/AffineGrid.py +0 -0
  16. {onnx2tf-1.29.20 → onnx2tf-1.29.22}/onnx2tf/ops/And.py +0 -0
  17. {onnx2tf-1.29.20 → onnx2tf-1.29.22}/onnx2tf/ops/ArgMax.py +0 -0
  18. {onnx2tf-1.29.20 → onnx2tf-1.29.22}/onnx2tf/ops/ArgMin.py +0 -0
  19. {onnx2tf-1.29.20 → onnx2tf-1.29.22}/onnx2tf/ops/Asin.py +0 -0
  20. {onnx2tf-1.29.20 → onnx2tf-1.29.22}/onnx2tf/ops/Asinh.py +0 -0
  21. {onnx2tf-1.29.20 → onnx2tf-1.29.22}/onnx2tf/ops/Atan.py +0 -0
  22. {onnx2tf-1.29.20 → onnx2tf-1.29.22}/onnx2tf/ops/Atanh.py +0 -0
  23. {onnx2tf-1.29.20 → onnx2tf-1.29.22}/onnx2tf/ops/Attention.py +0 -0
  24. {onnx2tf-1.29.20 → onnx2tf-1.29.22}/onnx2tf/ops/AveragePool.py +0 -0
  25. {onnx2tf-1.29.20 → onnx2tf-1.29.22}/onnx2tf/ops/BatchNormalization.py +0 -0
  26. {onnx2tf-1.29.20 → onnx2tf-1.29.22}/onnx2tf/ops/Bernoulli.py +0 -0
  27. {onnx2tf-1.29.20 → onnx2tf-1.29.22}/onnx2tf/ops/BitShift.py +0 -0
  28. {onnx2tf-1.29.20 → onnx2tf-1.29.22}/onnx2tf/ops/BitwiseAnd.py +0 -0
  29. {onnx2tf-1.29.20 → onnx2tf-1.29.22}/onnx2tf/ops/BitwiseNot.py +0 -0
  30. {onnx2tf-1.29.20 → onnx2tf-1.29.22}/onnx2tf/ops/BitwiseOr.py +0 -0
  31. {onnx2tf-1.29.20 → onnx2tf-1.29.22}/onnx2tf/ops/BitwiseXor.py +0 -0
  32. {onnx2tf-1.29.20 → onnx2tf-1.29.22}/onnx2tf/ops/BlackmanWindow.py +0 -0
  33. {onnx2tf-1.29.20 → onnx2tf-1.29.22}/onnx2tf/ops/Cast.py +0 -0
  34. {onnx2tf-1.29.20 → onnx2tf-1.29.22}/onnx2tf/ops/Ceil.py +0 -0
  35. {onnx2tf-1.29.20 → onnx2tf-1.29.22}/onnx2tf/ops/Celu.py +0 -0
  36. {onnx2tf-1.29.20 → onnx2tf-1.29.22}/onnx2tf/ops/Clip.py +0 -0
  37. {onnx2tf-1.29.20 → onnx2tf-1.29.22}/onnx2tf/ops/Col2Im.py +0 -0
  38. {onnx2tf-1.29.20 → onnx2tf-1.29.22}/onnx2tf/ops/Compress.py +0 -0
  39. {onnx2tf-1.29.20 → onnx2tf-1.29.22}/onnx2tf/ops/Concat.py +0 -0
  40. {onnx2tf-1.29.20 → onnx2tf-1.29.22}/onnx2tf/ops/ConcatFromSequence.py +0 -0
  41. {onnx2tf-1.29.20 → onnx2tf-1.29.22}/onnx2tf/ops/Constant.py +0 -0
  42. {onnx2tf-1.29.20 → onnx2tf-1.29.22}/onnx2tf/ops/ConstantOfShape.py +0 -0
  43. {onnx2tf-1.29.20 → onnx2tf-1.29.22}/onnx2tf/ops/Conv.py +0 -0
  44. {onnx2tf-1.29.20 → onnx2tf-1.29.22}/onnx2tf/ops/ConvInteger.py +0 -0
  45. {onnx2tf-1.29.20 → onnx2tf-1.29.22}/onnx2tf/ops/ConvTranspose.py +0 -0
  46. {onnx2tf-1.29.20 → onnx2tf-1.29.22}/onnx2tf/ops/Cos.py +0 -0
  47. {onnx2tf-1.29.20 → onnx2tf-1.29.22}/onnx2tf/ops/Cosh.py +0 -0
  48. {onnx2tf-1.29.20 → onnx2tf-1.29.22}/onnx2tf/ops/CumProd.py +0 -0
  49. {onnx2tf-1.29.20 → onnx2tf-1.29.22}/onnx2tf/ops/CumSum.py +0 -0
  50. {onnx2tf-1.29.20 → onnx2tf-1.29.22}/onnx2tf/ops/DFT.py +0 -0
  51. {onnx2tf-1.29.20 → onnx2tf-1.29.22}/onnx2tf/ops/DeformConv.py +0 -0
  52. {onnx2tf-1.29.20 → onnx2tf-1.29.22}/onnx2tf/ops/DepthToSpace.py +0 -0
  53. {onnx2tf-1.29.20 → onnx2tf-1.29.22}/onnx2tf/ops/DequantizeLinear.py +0 -0
  54. {onnx2tf-1.29.20 → onnx2tf-1.29.22}/onnx2tf/ops/Det.py +0 -0
  55. {onnx2tf-1.29.20 → onnx2tf-1.29.22}/onnx2tf/ops/Div.py +0 -0
  56. {onnx2tf-1.29.20 → onnx2tf-1.29.22}/onnx2tf/ops/Dropout.py +0 -0
  57. {onnx2tf-1.29.20 → onnx2tf-1.29.22}/onnx2tf/ops/DynamicQuantizeLinear.py +0 -0
  58. {onnx2tf-1.29.20 → onnx2tf-1.29.22}/onnx2tf/ops/Einsum.py +0 -0
  59. {onnx2tf-1.29.20 → onnx2tf-1.29.22}/onnx2tf/ops/Elu.py +0 -0
  60. {onnx2tf-1.29.20 → onnx2tf-1.29.22}/onnx2tf/ops/Equal.py +0 -0
  61. {onnx2tf-1.29.20 → onnx2tf-1.29.22}/onnx2tf/ops/Erf.py +0 -0
  62. {onnx2tf-1.29.20 → onnx2tf-1.29.22}/onnx2tf/ops/Exp.py +0 -0
  63. {onnx2tf-1.29.20 → onnx2tf-1.29.22}/onnx2tf/ops/Expand.py +0 -0
  64. {onnx2tf-1.29.20 → onnx2tf-1.29.22}/onnx2tf/ops/EyeLike.py +0 -0
  65. {onnx2tf-1.29.20 → onnx2tf-1.29.22}/onnx2tf/ops/Flatten.py +0 -0
  66. {onnx2tf-1.29.20 → onnx2tf-1.29.22}/onnx2tf/ops/Floor.py +0 -0
  67. {onnx2tf-1.29.20 → onnx2tf-1.29.22}/onnx2tf/ops/FusedConv.py +0 -0
  68. {onnx2tf-1.29.20 → onnx2tf-1.29.22}/onnx2tf/ops/GRU.py +0 -0
  69. {onnx2tf-1.29.20 → onnx2tf-1.29.22}/onnx2tf/ops/Gather.py +0 -0
  70. {onnx2tf-1.29.20 → onnx2tf-1.29.22}/onnx2tf/ops/GatherElements.py +0 -0
  71. {onnx2tf-1.29.20 → onnx2tf-1.29.22}/onnx2tf/ops/GatherND.py +0 -0
  72. {onnx2tf-1.29.20 → onnx2tf-1.29.22}/onnx2tf/ops/Gelu.py +0 -0
  73. {onnx2tf-1.29.20 → onnx2tf-1.29.22}/onnx2tf/ops/Gemm.py +0 -0
  74. {onnx2tf-1.29.20 → onnx2tf-1.29.22}/onnx2tf/ops/GlobalAveragePool.py +0 -0
  75. {onnx2tf-1.29.20 → onnx2tf-1.29.22}/onnx2tf/ops/GlobalLpPool.py +0 -0
  76. {onnx2tf-1.29.20 → onnx2tf-1.29.22}/onnx2tf/ops/GlobalMaxPool.py +0 -0
  77. {onnx2tf-1.29.20 → onnx2tf-1.29.22}/onnx2tf/ops/Greater.py +0 -0
  78. {onnx2tf-1.29.20 → onnx2tf-1.29.22}/onnx2tf/ops/GreaterOrEqual.py +0 -0
  79. {onnx2tf-1.29.20 → onnx2tf-1.29.22}/onnx2tf/ops/GridSample.py +0 -0
  80. {onnx2tf-1.29.20 → onnx2tf-1.29.22}/onnx2tf/ops/GroupNorm.py +0 -0
  81. {onnx2tf-1.29.20 → onnx2tf-1.29.22}/onnx2tf/ops/HammingWindow.py +0 -0
  82. {onnx2tf-1.29.20 → onnx2tf-1.29.22}/onnx2tf/ops/HannWindow.py +0 -0
  83. {onnx2tf-1.29.20 → onnx2tf-1.29.22}/onnx2tf/ops/HardSigmoid.py +0 -0
  84. {onnx2tf-1.29.20 → onnx2tf-1.29.22}/onnx2tf/ops/HardSwish.py +0 -0
  85. {onnx2tf-1.29.20 → onnx2tf-1.29.22}/onnx2tf/ops/Hardmax.py +0 -0
  86. {onnx2tf-1.29.20 → onnx2tf-1.29.22}/onnx2tf/ops/Identity.py +0 -0
  87. {onnx2tf-1.29.20 → onnx2tf-1.29.22}/onnx2tf/ops/If.py +0 -0
  88. {onnx2tf-1.29.20 → onnx2tf-1.29.22}/onnx2tf/ops/ImageDecoder.py +0 -0
  89. {onnx2tf-1.29.20 → onnx2tf-1.29.22}/onnx2tf/ops/Input.py +0 -0
  90. {onnx2tf-1.29.20 → onnx2tf-1.29.22}/onnx2tf/ops/InstanceNormalization.py +0 -0
  91. {onnx2tf-1.29.20 → onnx2tf-1.29.22}/onnx2tf/ops/Inverse.py +0 -0
  92. {onnx2tf-1.29.20 → onnx2tf-1.29.22}/onnx2tf/ops/IsInf.py +0 -0
  93. {onnx2tf-1.29.20 → onnx2tf-1.29.22}/onnx2tf/ops/IsNaN.py +0 -0
  94. {onnx2tf-1.29.20 → onnx2tf-1.29.22}/onnx2tf/ops/LRN.py +0 -0
  95. {onnx2tf-1.29.20 → onnx2tf-1.29.22}/onnx2tf/ops/LSTM.py +0 -0
  96. {onnx2tf-1.29.20 → onnx2tf-1.29.22}/onnx2tf/ops/LayerNormalization.py +0 -0
  97. {onnx2tf-1.29.20 → onnx2tf-1.29.22}/onnx2tf/ops/LeakyRelu.py +0 -0
  98. {onnx2tf-1.29.20 → onnx2tf-1.29.22}/onnx2tf/ops/Less.py +0 -0
  99. {onnx2tf-1.29.20 → onnx2tf-1.29.22}/onnx2tf/ops/LessOrEqual.py +0 -0
  100. {onnx2tf-1.29.20 → onnx2tf-1.29.22}/onnx2tf/ops/Log.py +0 -0
  101. {onnx2tf-1.29.20 → onnx2tf-1.29.22}/onnx2tf/ops/LogSoftmax.py +0 -0
  102. {onnx2tf-1.29.20 → onnx2tf-1.29.22}/onnx2tf/ops/Loop.py +0 -0
  103. {onnx2tf-1.29.20 → onnx2tf-1.29.22}/onnx2tf/ops/LpNormalization.py +0 -0
  104. {onnx2tf-1.29.20 → onnx2tf-1.29.22}/onnx2tf/ops/LpPool.py +0 -0
  105. {onnx2tf-1.29.20 → onnx2tf-1.29.22}/onnx2tf/ops/MatMul.py +0 -0
  106. {onnx2tf-1.29.20 → onnx2tf-1.29.22}/onnx2tf/ops/MatMulInteger.py +0 -0
  107. {onnx2tf-1.29.20 → onnx2tf-1.29.22}/onnx2tf/ops/Max.py +0 -0
  108. {onnx2tf-1.29.20 → onnx2tf-1.29.22}/onnx2tf/ops/MaxRoiPool.py +0 -0
  109. {onnx2tf-1.29.20 → onnx2tf-1.29.22}/onnx2tf/ops/MaxUnpool.py +0 -0
  110. {onnx2tf-1.29.20 → onnx2tf-1.29.22}/onnx2tf/ops/Mean.py +0 -0
  111. {onnx2tf-1.29.20 → onnx2tf-1.29.22}/onnx2tf/ops/MeanVarianceNormalization.py +0 -0
  112. {onnx2tf-1.29.20 → onnx2tf-1.29.22}/onnx2tf/ops/MelWeightMatrix.py +0 -0
  113. {onnx2tf-1.29.20 → onnx2tf-1.29.22}/onnx2tf/ops/Min.py +0 -0
  114. {onnx2tf-1.29.20 → onnx2tf-1.29.22}/onnx2tf/ops/Mish.py +0 -0
  115. {onnx2tf-1.29.20 → onnx2tf-1.29.22}/onnx2tf/ops/Mod.py +0 -0
  116. {onnx2tf-1.29.20 → onnx2tf-1.29.22}/onnx2tf/ops/Mul.py +0 -0
  117. {onnx2tf-1.29.20 → onnx2tf-1.29.22}/onnx2tf/ops/Multinomial.py +0 -0
  118. {onnx2tf-1.29.20 → onnx2tf-1.29.22}/onnx2tf/ops/Neg.py +0 -0
  119. {onnx2tf-1.29.20 → onnx2tf-1.29.22}/onnx2tf/ops/NegativeLogLikelihoodLoss.py +0 -0
  120. {onnx2tf-1.29.20 → onnx2tf-1.29.22}/onnx2tf/ops/NonMaxSuppression.py +0 -0
  121. {onnx2tf-1.29.20 → onnx2tf-1.29.22}/onnx2tf/ops/NonZero.py +0 -0
  122. {onnx2tf-1.29.20 → onnx2tf-1.29.22}/onnx2tf/ops/Not.py +0 -0
  123. {onnx2tf-1.29.20 → onnx2tf-1.29.22}/onnx2tf/ops/OneHot.py +0 -0
  124. {onnx2tf-1.29.20 → onnx2tf-1.29.22}/onnx2tf/ops/OptionalGetElement.py +0 -0
  125. {onnx2tf-1.29.20 → onnx2tf-1.29.22}/onnx2tf/ops/OptionalHasElement.py +0 -0
  126. {onnx2tf-1.29.20 → onnx2tf-1.29.22}/onnx2tf/ops/Or.py +0 -0
  127. {onnx2tf-1.29.20 → onnx2tf-1.29.22}/onnx2tf/ops/PRelu.py +0 -0
  128. {onnx2tf-1.29.20 → onnx2tf-1.29.22}/onnx2tf/ops/Pad.py +0 -0
  129. {onnx2tf-1.29.20 → onnx2tf-1.29.22}/onnx2tf/ops/Pow.py +0 -0
  130. {onnx2tf-1.29.20 → onnx2tf-1.29.22}/onnx2tf/ops/QLinearAdd.py +0 -0
  131. {onnx2tf-1.29.20 → onnx2tf-1.29.22}/onnx2tf/ops/QLinearConcat.py +0 -0
  132. {onnx2tf-1.29.20 → onnx2tf-1.29.22}/onnx2tf/ops/QLinearConv.py +0 -0
  133. {onnx2tf-1.29.20 → onnx2tf-1.29.22}/onnx2tf/ops/QLinearLeakyRelu.py +0 -0
  134. {onnx2tf-1.29.20 → onnx2tf-1.29.22}/onnx2tf/ops/QLinearMatMul.py +0 -0
  135. {onnx2tf-1.29.20 → onnx2tf-1.29.22}/onnx2tf/ops/QLinearMul.py +0 -0
  136. {onnx2tf-1.29.20 → onnx2tf-1.29.22}/onnx2tf/ops/QLinearSigmoid.py +0 -0
  137. {onnx2tf-1.29.20 → onnx2tf-1.29.22}/onnx2tf/ops/QLinearSoftmax.py +0 -0
  138. {onnx2tf-1.29.20 → onnx2tf-1.29.22}/onnx2tf/ops/QuantizeLinear.py +0 -0
  139. {onnx2tf-1.29.20 → onnx2tf-1.29.22}/onnx2tf/ops/RMSNormalization.py +0 -0
  140. {onnx2tf-1.29.20 → onnx2tf-1.29.22}/onnx2tf/ops/RNN.py +0 -0
  141. {onnx2tf-1.29.20 → onnx2tf-1.29.22}/onnx2tf/ops/RandomNormal.py +0 -0
  142. {onnx2tf-1.29.20 → onnx2tf-1.29.22}/onnx2tf/ops/RandomNormalLike.py +0 -0
  143. {onnx2tf-1.29.20 → onnx2tf-1.29.22}/onnx2tf/ops/RandomUniform.py +0 -0
  144. {onnx2tf-1.29.20 → onnx2tf-1.29.22}/onnx2tf/ops/RandomUniformLike.py +0 -0
  145. {onnx2tf-1.29.20 → onnx2tf-1.29.22}/onnx2tf/ops/Range.py +0 -0
  146. {onnx2tf-1.29.20 → onnx2tf-1.29.22}/onnx2tf/ops/Reciprocal.py +0 -0
  147. {onnx2tf-1.29.20 → onnx2tf-1.29.22}/onnx2tf/ops/ReduceL1.py +0 -0
  148. {onnx2tf-1.29.20 → onnx2tf-1.29.22}/onnx2tf/ops/ReduceL2.py +0 -0
  149. {onnx2tf-1.29.20 → onnx2tf-1.29.22}/onnx2tf/ops/ReduceLogSum.py +0 -0
  150. {onnx2tf-1.29.20 → onnx2tf-1.29.22}/onnx2tf/ops/ReduceLogSumExp.py +0 -0
  151. {onnx2tf-1.29.20 → onnx2tf-1.29.22}/onnx2tf/ops/ReduceMax.py +0 -0
  152. {onnx2tf-1.29.20 → onnx2tf-1.29.22}/onnx2tf/ops/ReduceMean.py +0 -0
  153. {onnx2tf-1.29.20 → onnx2tf-1.29.22}/onnx2tf/ops/ReduceMin.py +0 -0
  154. {onnx2tf-1.29.20 → onnx2tf-1.29.22}/onnx2tf/ops/ReduceProd.py +0 -0
  155. {onnx2tf-1.29.20 → onnx2tf-1.29.22}/onnx2tf/ops/ReduceSum.py +0 -0
  156. {onnx2tf-1.29.20 → onnx2tf-1.29.22}/onnx2tf/ops/ReduceSumSquare.py +0 -0
  157. {onnx2tf-1.29.20 → onnx2tf-1.29.22}/onnx2tf/ops/RegexFullMatch.py +0 -0
  158. {onnx2tf-1.29.20 → onnx2tf-1.29.22}/onnx2tf/ops/Relu.py +0 -0
  159. {onnx2tf-1.29.20 → onnx2tf-1.29.22}/onnx2tf/ops/Reshape.py +0 -0
  160. {onnx2tf-1.29.20 → onnx2tf-1.29.22}/onnx2tf/ops/Resize.py +0 -0
  161. {onnx2tf-1.29.20 → onnx2tf-1.29.22}/onnx2tf/ops/ReverseSequence.py +0 -0
  162. {onnx2tf-1.29.20 → onnx2tf-1.29.22}/onnx2tf/ops/RoiAlign.py +0 -0
  163. {onnx2tf-1.29.20 → onnx2tf-1.29.22}/onnx2tf/ops/RotaryEmbedding.py +0 -0
  164. {onnx2tf-1.29.20 → onnx2tf-1.29.22}/onnx2tf/ops/Round.py +0 -0
  165. {onnx2tf-1.29.20 → onnx2tf-1.29.22}/onnx2tf/ops/STFT.py +0 -0
  166. {onnx2tf-1.29.20 → onnx2tf-1.29.22}/onnx2tf/ops/ScaleAndTranslate.py +0 -0
  167. {onnx2tf-1.29.20 → onnx2tf-1.29.22}/onnx2tf/ops/Scan.py +0 -0
  168. {onnx2tf-1.29.20 → onnx2tf-1.29.22}/onnx2tf/ops/Scatter.py +0 -0
  169. {onnx2tf-1.29.20 → onnx2tf-1.29.22}/onnx2tf/ops/ScatterND.py +0 -0
  170. {onnx2tf-1.29.20 → onnx2tf-1.29.22}/onnx2tf/ops/Selu.py +0 -0
  171. {onnx2tf-1.29.20 → onnx2tf-1.29.22}/onnx2tf/ops/SequenceAt.py +0 -0
  172. {onnx2tf-1.29.20 → onnx2tf-1.29.22}/onnx2tf/ops/SequenceConstruct.py +0 -0
  173. {onnx2tf-1.29.20 → onnx2tf-1.29.22}/onnx2tf/ops/SequenceEmpty.py +0 -0
  174. {onnx2tf-1.29.20 → onnx2tf-1.29.22}/onnx2tf/ops/SequenceErase.py +0 -0
  175. {onnx2tf-1.29.20 → onnx2tf-1.29.22}/onnx2tf/ops/SequenceInsert.py +0 -0
  176. {onnx2tf-1.29.20 → onnx2tf-1.29.22}/onnx2tf/ops/SequenceLength.py +0 -0
  177. {onnx2tf-1.29.20 → onnx2tf-1.29.22}/onnx2tf/ops/Shape.py +0 -0
  178. {onnx2tf-1.29.20 → onnx2tf-1.29.22}/onnx2tf/ops/Shrink.py +0 -0
  179. {onnx2tf-1.29.20 → onnx2tf-1.29.22}/onnx2tf/ops/Sigmoid.py +0 -0
  180. {onnx2tf-1.29.20 → onnx2tf-1.29.22}/onnx2tf/ops/Sign.py +0 -0
  181. {onnx2tf-1.29.20 → onnx2tf-1.29.22}/onnx2tf/ops/Sin.py +0 -0
  182. {onnx2tf-1.29.20 → onnx2tf-1.29.22}/onnx2tf/ops/Sinh.py +0 -0
  183. {onnx2tf-1.29.20 → onnx2tf-1.29.22}/onnx2tf/ops/Size.py +0 -0
  184. {onnx2tf-1.29.20 → onnx2tf-1.29.22}/onnx2tf/ops/Slice.py +0 -0
  185. {onnx2tf-1.29.20 → onnx2tf-1.29.22}/onnx2tf/ops/Softmax.py +0 -0
  186. {onnx2tf-1.29.20 → onnx2tf-1.29.22}/onnx2tf/ops/SoftmaxCrossEntropyLoss.py +0 -0
  187. {onnx2tf-1.29.20 → onnx2tf-1.29.22}/onnx2tf/ops/Softplus.py +0 -0
  188. {onnx2tf-1.29.20 → onnx2tf-1.29.22}/onnx2tf/ops/Softsign.py +0 -0
  189. {onnx2tf-1.29.20 → onnx2tf-1.29.22}/onnx2tf/ops/SpaceToDepth.py +0 -0
  190. {onnx2tf-1.29.20 → onnx2tf-1.29.22}/onnx2tf/ops/Split.py +0 -0
  191. {onnx2tf-1.29.20 → onnx2tf-1.29.22}/onnx2tf/ops/SplitToSequence.py +0 -0
  192. {onnx2tf-1.29.20 → onnx2tf-1.29.22}/onnx2tf/ops/Sqrt.py +0 -0
  193. {onnx2tf-1.29.20 → onnx2tf-1.29.22}/onnx2tf/ops/Squeeze.py +0 -0
  194. {onnx2tf-1.29.20 → onnx2tf-1.29.22}/onnx2tf/ops/StringConcat.py +0 -0
  195. {onnx2tf-1.29.20 → onnx2tf-1.29.22}/onnx2tf/ops/StringNormalizer.py +0 -0
  196. {onnx2tf-1.29.20 → onnx2tf-1.29.22}/onnx2tf/ops/StringSplit.py +0 -0
  197. {onnx2tf-1.29.20 → onnx2tf-1.29.22}/onnx2tf/ops/Sub.py +0 -0
  198. {onnx2tf-1.29.20 → onnx2tf-1.29.22}/onnx2tf/ops/Sum.py +0 -0
  199. {onnx2tf-1.29.20 → onnx2tf-1.29.22}/onnx2tf/ops/Tan.py +0 -0
  200. {onnx2tf-1.29.20 → onnx2tf-1.29.22}/onnx2tf/ops/Tanh.py +0 -0
  201. {onnx2tf-1.29.20 → onnx2tf-1.29.22}/onnx2tf/ops/TensorScatter.py +0 -0
  202. {onnx2tf-1.29.20 → onnx2tf-1.29.22}/onnx2tf/ops/ThresholdedRelu.py +0 -0
  203. {onnx2tf-1.29.20 → onnx2tf-1.29.22}/onnx2tf/ops/Tile.py +0 -0
  204. {onnx2tf-1.29.20 → onnx2tf-1.29.22}/onnx2tf/ops/TopK.py +0 -0
  205. {onnx2tf-1.29.20 → onnx2tf-1.29.22}/onnx2tf/ops/Transpose.py +0 -0
  206. {onnx2tf-1.29.20 → onnx2tf-1.29.22}/onnx2tf/ops/Trilu.py +0 -0
  207. {onnx2tf-1.29.20 → onnx2tf-1.29.22}/onnx2tf/ops/Unsqueeze.py +0 -0
  208. {onnx2tf-1.29.20 → onnx2tf-1.29.22}/onnx2tf/ops/Upsample.py +0 -0
  209. {onnx2tf-1.29.20 → onnx2tf-1.29.22}/onnx2tf/ops/Where.py +0 -0
  210. {onnx2tf-1.29.20 → onnx2tf-1.29.22}/onnx2tf/ops/Xor.py +0 -0
  211. {onnx2tf-1.29.20 → onnx2tf-1.29.22}/onnx2tf/ops/__init__.py +0 -0
  212. {onnx2tf-1.29.20 → onnx2tf-1.29.22}/onnx2tf/utils/__init__.py +0 -0
  213. {onnx2tf-1.29.20 → onnx2tf-1.29.22}/onnx2tf/utils/enums.py +0 -0
  214. {onnx2tf-1.29.20 → onnx2tf-1.29.22}/onnx2tf/utils/iterative_json_optimizer.py +0 -0
  215. {onnx2tf-1.29.20 → onnx2tf-1.29.22}/onnx2tf/utils/json_auto_generator.py +0 -0
  216. {onnx2tf-1.29.20 → onnx2tf-1.29.22}/onnx2tf/utils/logging.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: onnx2tf
3
- Version: 1.29.20
3
+ Version: 1.29.22
4
4
  Summary: Self-Created Tools to convert ONNX files (NCHW) to TensorFlow/TFLite/Keras format (NHWC). The purpose of this tool is to solve the massive Transpose extrapolation problem in onnx-tensorflow (onnx-tf).
5
5
  Keywords: onnx,tensorflow,tflite,keras,deep-learning,machine-learning
6
6
  Author: Katsuya Hyodo
@@ -18,7 +18,7 @@ Classifier: Programming Language :: Python :: 3.11
18
18
  Classifier: Topic :: Scientific/Engineering :: Artificial Intelligence
19
19
  Requires-Dist: requests==2.32.5
20
20
  Requires-Dist: numpy==1.26.4
21
- Requires-Dist: onnx==1.19.0
21
+ Requires-Dist: onnx==1.19.1
22
22
  Requires-Dist: onnxruntime==1.23.0
23
23
  Requires-Dist: opencv-python==4.11.0.86
24
24
  Requires-Dist: onnxsim==0.4.36
@@ -365,7 +365,7 @@ Video speed is adjusted approximately 50 times slower than actual speed.
365
365
  docker run --rm -it \
366
366
  -v `pwd`:/workdir \
367
367
  -w /workdir \
368
- ghcr.io/pinto0309/onnx2tf:1.29.20
368
+ ghcr.io/pinto0309/onnx2tf:1.29.22
369
369
 
370
370
  or
371
371
 
@@ -373,18 +373,18 @@ Video speed is adjusted approximately 50 times slower than actual speed.
373
373
  docker run --rm -it \
374
374
  -v `pwd`:/workdir \
375
375
  -w /workdir \
376
- docker.io/pinto0309/onnx2tf:1.29.20
376
+ docker.io/pinto0309/onnx2tf:1.29.22
377
377
 
378
378
  or
379
379
 
380
- pip install -U onnx==1.19.0 \
380
+ pip install -U onnx==1.19.1 \
381
381
  && pip install -U onnx-graphsurgeon==0.5.8 \
382
382
  && pip install -U onnxruntime==1.23.0 \
383
383
  && pip install -U onnxsim==0.4.36 \
384
384
  && pip install -U onnxoptimizer==0.4.2 \
385
385
  && pip install -U simple_onnx_processing_tools==1.1.32 \
386
- && pip install -U sne4onnx>=1.0.13 \
387
- && pip install -U sng4onnx>=1.0.4 \
386
+ && pip install -U sne4onnx==1.0.15 \
387
+ && pip install -U sng4onnx==1.0.5 \
388
388
  && pip install -U ai_edge_litert==1.2.0 \
389
389
  && pip install -U tensorflow==2.19.0 \
390
390
  && pip install -U protobuf==3.20.3 \
@@ -630,7 +630,7 @@ After many upgrades, the need for JSON parameter correction has become much less
630
630
 
631
631
  `-ois` an option to overwrite the input OP to a static size if it has undefined dimensions. `-cotof` option checks the accuracy of all OPs one by one. `-cotoa` is the error value of the threshold for determining an accuracy error. If there are undefined dimensions in the input OP, it is better to fix them to the static geometry to improve the accuracy of the accuracy measurement.
632
632
 
633
- Also, you can use the `-cind` option to specify custom input for `-cotof`, instead of using the default dummy input. Otherwise, all input values will be set to 1. For more information about the `-cind` option, please refer to [here](#cli-parameter).
633
+ Also, you can use the `-cind` option to specify custom input for `-cotof`, instead of using the default dummy input. Otherwise, all input values will be set to 1. You can override the dummy input values with `--value_hints` (scalar only, `*:default` supported). For more information about the `-cind` option, please refer to [here](#cli-parameter).
634
634
 
635
635
  The `-cotof` option only compares the original ONNX and converted TensorFlow (Keras) models at Float32 precision, not at Float16 or INT8 precision.
636
636
 
@@ -644,6 +644,10 @@ onnx2tf -i mobilenetv2-12.onnx -b 1 -cotof -cotoa 1e-1
644
644
  or
645
645
 
646
646
  onnx2tf -i mobilenetv2-12.onnx -cotof -cotoa 1e-1 -cind "input" "/your/path/x.npy"
647
+
648
+ or
649
+
650
+ onnx2tf -i mobilenetv2-12.onnx -cotof -cotoa 1e-1 --value_hints "input:0.5" "*:1.0"
647
651
  ```
648
652
  ![image](https://user-images.githubusercontent.com/33194443/216901668-5fdb1e38-8670-46a4-b4b9-8a774fa7545e.png)
649
653
 
@@ -1826,6 +1830,14 @@ optional arguments:
1826
1830
  A value of 1 or more must be specified.
1827
1831
  Numerical values other than dynamic dimensions are ignored.
1828
1832
 
1833
+ -vh VALUE_HINTS [VALUE_HINTS ...], \
1834
+ --value_hints VALUE_HINTS [VALUE_HINTS ...]
1835
+ Value hints for dummy inference input tensors.
1836
+ The format is
1837
+ "input_name_1:value" "input_name_2:value" "*:default_value"
1838
+ "*" applies to all inputs not explicitly specified.
1839
+ Values are scalar only.
1840
+
1829
1841
  -nlt, --no_large_tensor
1830
1842
  Suppresses constant bloat caused by Tile OP when optimizing models in onnxsim.
1831
1843
  See: https://github.com/daquexian/onnx-simplifier/issues/178
@@ -2157,6 +2169,7 @@ convert(
2157
2169
  batch_size: Union[int, NoneType] = None,
2158
2170
  overwrite_input_shape: Union[List[str], NoneType] = None,
2159
2171
  shape_hints: Union[List[str], NoneType] = None,
2172
+ value_hints: Union[List[str], NoneType] = None,
2160
2173
  no_large_tensor: Optional[bool] = False,
2161
2174
  output_nms_with_dynamic_tensor: Optional[bool] = False,
2162
2175
  switch_nms_version: Optional[str] = 'v4',
@@ -2377,6 +2390,13 @@ convert(
2377
2390
  A value of 1 or more must be specified.
2378
2391
  Numerical values other than dynamic dimensions are ignored.
2379
2392
 
2393
+ value_hints: Optional[List[str]]
2394
+ Value hints for dummy inference input tensors.
2395
+ The format is
2396
+ ['input_name_1:value', 'input_name_2:value', '*:default_value']
2397
+ "*" applies to all inputs not explicitly specified.
2398
+ Values are scalar only.
2399
+
2380
2400
  no_large_tensor: Optional[bool]
2381
2401
  Suppresses constant bloat caused by Tile OP when optimizing models in onnxsim.
2382
2402
  See: https://github.com/daquexian/onnx-simplifier/issues/178
@@ -3032,6 +3052,7 @@ The above differences often cannot be dealt with by simply converting the model
3032
3052
  14. [nobuco](https://github.com/AlexanderLutsenko/nobuco)
3033
3053
  15. [onnx2torch](https://github.com/ENOT-AutoDL/onnx2torch)
3034
3054
  16. [ai-edge-torch](https://github.com/google-ai-edge/ai-edge-torch)
3055
+ 17. [LiteRT.js](https://ai.google.dev/edge/litert/web)
3035
3056
 
3036
3057
  ## Acknowledgement
3037
3058
  1. https://github.com/onnx/models
@@ -323,7 +323,7 @@ Video speed is adjusted approximately 50 times slower than actual speed.
323
323
  docker run --rm -it \
324
324
  -v `pwd`:/workdir \
325
325
  -w /workdir \
326
- ghcr.io/pinto0309/onnx2tf:1.29.20
326
+ ghcr.io/pinto0309/onnx2tf:1.29.22
327
327
 
328
328
  or
329
329
 
@@ -331,18 +331,18 @@ Video speed is adjusted approximately 50 times slower than actual speed.
331
331
  docker run --rm -it \
332
332
  -v `pwd`:/workdir \
333
333
  -w /workdir \
334
- docker.io/pinto0309/onnx2tf:1.29.20
334
+ docker.io/pinto0309/onnx2tf:1.29.22
335
335
 
336
336
  or
337
337
 
338
- pip install -U onnx==1.19.0 \
338
+ pip install -U onnx==1.19.1 \
339
339
  && pip install -U onnx-graphsurgeon==0.5.8 \
340
340
  && pip install -U onnxruntime==1.23.0 \
341
341
  && pip install -U onnxsim==0.4.36 \
342
342
  && pip install -U onnxoptimizer==0.4.2 \
343
343
  && pip install -U simple_onnx_processing_tools==1.1.32 \
344
- && pip install -U sne4onnx>=1.0.13 \
345
- && pip install -U sng4onnx>=1.0.4 \
344
+ && pip install -U sne4onnx==1.0.15 \
345
+ && pip install -U sng4onnx==1.0.5 \
346
346
  && pip install -U ai_edge_litert==1.2.0 \
347
347
  && pip install -U tensorflow==2.19.0 \
348
348
  && pip install -U protobuf==3.20.3 \
@@ -588,7 +588,7 @@ After many upgrades, the need for JSON parameter correction has become much less
588
588
 
589
589
  `-ois` an option to overwrite the input OP to a static size if it has undefined dimensions. `-cotof` option checks the accuracy of all OPs one by one. `-cotoa` is the error value of the threshold for determining an accuracy error. If there are undefined dimensions in the input OP, it is better to fix them to the static geometry to improve the accuracy of the accuracy measurement.
590
590
 
591
- Also, you can use the `-cind` option to specify custom input for `-cotof`, instead of using the default dummy input. Otherwise, all input values will be set to 1. For more information about the `-cind` option, please refer to [here](#cli-parameter).
591
+ Also, you can use the `-cind` option to specify custom input for `-cotof`, instead of using the default dummy input. Otherwise, all input values will be set to 1. You can override the dummy input values with `--value_hints` (scalar only, `*:default` supported). For more information about the `-cind` option, please refer to [here](#cli-parameter).
592
592
 
593
593
  The `-cotof` option only compares the original ONNX and converted TensorFlow (Keras) models at Float32 precision, not at Float16 or INT8 precision.
594
594
 
@@ -602,6 +602,10 @@ onnx2tf -i mobilenetv2-12.onnx -b 1 -cotof -cotoa 1e-1
602
602
  or
603
603
 
604
604
  onnx2tf -i mobilenetv2-12.onnx -cotof -cotoa 1e-1 -cind "input" "/your/path/x.npy"
605
+
606
+ or
607
+
608
+ onnx2tf -i mobilenetv2-12.onnx -cotof -cotoa 1e-1 --value_hints "input:0.5" "*:1.0"
605
609
  ```
606
610
  ![image](https://user-images.githubusercontent.com/33194443/216901668-5fdb1e38-8670-46a4-b4b9-8a774fa7545e.png)
607
611
 
@@ -1784,6 +1788,14 @@ optional arguments:
1784
1788
  A value of 1 or more must be specified.
1785
1789
  Numerical values other than dynamic dimensions are ignored.
1786
1790
 
1791
+ -vh VALUE_HINTS [VALUE_HINTS ...], \
1792
+ --value_hints VALUE_HINTS [VALUE_HINTS ...]
1793
+ Value hints for dummy inference input tensors.
1794
+ The format is
1795
+ "input_name_1:value" "input_name_2:value" "*:default_value"
1796
+ "*" applies to all inputs not explicitly specified.
1797
+ Values are scalar only.
1798
+
1787
1799
  -nlt, --no_large_tensor
1788
1800
  Suppresses constant bloat caused by Tile OP when optimizing models in onnxsim.
1789
1801
  See: https://github.com/daquexian/onnx-simplifier/issues/178
@@ -2115,6 +2127,7 @@ convert(
2115
2127
  batch_size: Union[int, NoneType] = None,
2116
2128
  overwrite_input_shape: Union[List[str], NoneType] = None,
2117
2129
  shape_hints: Union[List[str], NoneType] = None,
2130
+ value_hints: Union[List[str], NoneType] = None,
2118
2131
  no_large_tensor: Optional[bool] = False,
2119
2132
  output_nms_with_dynamic_tensor: Optional[bool] = False,
2120
2133
  switch_nms_version: Optional[str] = 'v4',
@@ -2335,6 +2348,13 @@ convert(
2335
2348
  A value of 1 or more must be specified.
2336
2349
  Numerical values other than dynamic dimensions are ignored.
2337
2350
 
2351
+ value_hints: Optional[List[str]]
2352
+ Value hints for dummy inference input tensors.
2353
+ The format is
2354
+ ['input_name_1:value', 'input_name_2:value', '*:default_value']
2355
+ "*" applies to all inputs not explicitly specified.
2356
+ Values are scalar only.
2357
+
2338
2358
  no_large_tensor: Optional[bool]
2339
2359
  Suppresses constant bloat caused by Tile OP when optimizing models in onnxsim.
2340
2360
  See: https://github.com/daquexian/onnx-simplifier/issues/178
@@ -2990,6 +3010,7 @@ The above differences often cannot be dealt with by simply converting the model
2990
3010
  14. [nobuco](https://github.com/AlexanderLutsenko/nobuco)
2991
3011
  15. [onnx2torch](https://github.com/ENOT-AutoDL/onnx2torch)
2992
3012
  16. [ai-edge-torch](https://github.com/google-ai-edge/ai-edge-torch)
3013
+ 17. [LiteRT.js](https://ai.google.dev/edge/litert/web)
2993
3014
 
2994
3015
  ## Acknowledgement
2995
3016
  1. https://github.com/onnx/models
@@ -1,3 +1,3 @@
1
1
  from onnx2tf.onnx2tf import convert, main
2
2
 
3
- __version__ = '1.29.20'
3
+ __version__ = '1.29.22'
@@ -43,6 +43,7 @@ from typing import Optional, List, Any, Dict
43
43
  from argparse import ArgumentParser
44
44
 
45
45
  import importlib
46
+ import onnx2tf.utils.common_functions as common_functions
46
47
  from onnx2tf.utils.common_functions import (
47
48
  dummy_onnx_inference,
48
49
  dummy_tf_inference,
@@ -639,6 +640,7 @@ def convert(
639
640
  batch_size: Optional[int] = None,
640
641
  overwrite_input_shape: Optional[List[str]] = None,
641
642
  shape_hints: Optional[List[str]] = None,
643
+ value_hints: Optional[List[str]] = None,
642
644
  no_large_tensor: Optional[bool] = False,
643
645
  output_nms_with_dynamic_tensor: Optional[bool] = False,
644
646
  switch_nms_version: Optional[str] = 'v4',
@@ -850,6 +852,15 @@ def convert(
850
852
  A value of 1 or more must be specified.\n
851
853
  Numerical values other than dynamic dimensions are ignored.
852
854
 
855
+ value_hints: Optional[List[str]]
856
+ Value hints for dummy inference input tensors.\n
857
+ The format is\n
858
+ ["input_name_1:value","input_name_2:value","*:default_value"].\n
859
+ "*" applies to all inputs not explicitly specified.\n
860
+ Values are scalar only.\n
861
+ e.g.\n
862
+ ['input0:0.5','mask:0','*:1.0']\n
863
+
853
864
  no_large_tensor: Optional[bool]
854
865
  Suppresses constant bloat caused by Tile OP when optimizing models in onnxsim.\n
855
866
  See: https://github.com/daquexian/onnx-simplifier/issues/178
@@ -1110,6 +1121,8 @@ def convert(
1110
1121
  if verbosity is None:
1111
1122
  verbosity = 'debug'
1112
1123
  set_log_level('error' if non_verbose else verbosity)
1124
+ common_functions.set_dummy_shape_hints(shape_hints)
1125
+ common_functions.set_dummy_value_hints(value_hints)
1113
1126
 
1114
1127
  # Either designation required
1115
1128
  if not input_onnx_file_path and not onnx_graph:
@@ -1326,6 +1339,10 @@ def convert(
1326
1339
  'Failed to optimize the onnx file.'
1327
1340
  )
1328
1341
 
1342
+ has_external_data = False
1343
+ if input_onnx_file_path and os.path.exists(input_onnx_file_path):
1344
+ has_external_data = check_has_external_data(input_onnx_file_path)
1345
+
1329
1346
  # Automatic generation of each OP name - sng4onnx
1330
1347
  if not not_use_opname_auto_generate:
1331
1348
  info('')
@@ -1357,9 +1374,7 @@ def convert(
1357
1374
 
1358
1375
  # Loading Graphs
1359
1376
  # onnx_graph If specified, onnx_graph is processed first
1360
- has_external_data = False
1361
1377
  if not onnx_graph:
1362
- has_external_data = check_has_external_data(input_onnx_file_path)
1363
1378
  onnx_graph = onnx.load(input_onnx_file_path)
1364
1379
 
1365
1380
  if not auto_split_model and onnx_graph is not None:
@@ -1686,6 +1701,7 @@ def convert(
1686
1701
  'batch_size': batch_size,
1687
1702
  'overwrite_input_shape': overwrite_input_shape,
1688
1703
  'shape_hints': shape_hints,
1704
+ 'value_hints': value_hints,
1689
1705
  'no_large_tensor': no_large_tensor,
1690
1706
  'output_nms_with_dynamic_tensor': output_nms_with_dynamic_tensor,
1691
1707
  'switch_nms_version': switch_nms_version,
@@ -3874,6 +3890,18 @@ def main():
3874
3890
  'Only applied to dynamic dimensions in inputs. \n' +
3875
3891
  'Only used when -cotof or -coto are specified.'
3876
3892
  )
3893
+ parser.add_argument(
3894
+ '-vh',
3895
+ '--value_hints',
3896
+ type=str,
3897
+ nargs='+',
3898
+ help=\
3899
+ 'Value hints for dummy inference input tensors. \n' +
3900
+ 'The format is\n' +
3901
+ '"input_name_1:value" "input_name_2:value" "*:default_value". \n' +
3902
+ '"*" applies to all inputs not explicitly specified. \n' +
3903
+ 'Values are scalar only.'
3904
+ )
3877
3905
  parser.add_argument(
3878
3906
  '-nlt',
3879
3907
  '--no_large_tensor',
@@ -4359,6 +4387,7 @@ def main():
4359
4387
  batch_size=args.batch_size,
4360
4388
  overwrite_input_shape=args.overwrite_input_shape,
4361
4389
  shape_hints=args.shape_hints,
4390
+ value_hints=args.value_hints,
4362
4391
  no_large_tensor=args.no_large_tensor,
4363
4392
  output_nms_with_dynamic_tensor=args.output_nms_with_dynamic_tensor,
4364
4393
  switch_nms_version=args.switch_nms_version,
@@ -1,6 +1,7 @@
1
1
  import random
2
2
  random.seed(0)
3
3
  import numpy as np
4
+ import itertools
4
5
  np.random.seed(0)
5
6
  import tensorflow as tf
6
7
  import tf_keras
@@ -119,6 +120,59 @@ def make_node(
119
120
  **kwargs,
120
121
  )
121
122
 
123
+ # Guard: brute-force axis alignment between NCHW and NHWC when batch dim mismatches.
124
+ # Only trigger when shapes are fully known to avoid destabilizing existing behavior.
125
+ def _shape_matches(shape_a, shape_b):
126
+ if shape_a is None or shape_b is None or len(shape_a) != len(shape_b):
127
+ return False
128
+ for dim_a, dim_b in zip(shape_a, shape_b):
129
+ if dim_a is None or dim_b is None:
130
+ continue
131
+ if dim_a != dim_b:
132
+ return False
133
+ return True
134
+
135
+ def _best_perm_to_match(cur_shape, target_shape):
136
+ rank = len(cur_shape)
137
+ best_perm = None
138
+ best_cost = None
139
+ for perm in itertools.permutations(range(rank)):
140
+ permuted = [cur_shape[i] for i in perm]
141
+ if not _shape_matches(permuted, target_shape):
142
+ continue
143
+ cost = sum(abs(i - perm[i]) for i in range(rank))
144
+ if best_cost is None or cost < best_cost:
145
+ best_cost = cost
146
+ best_perm = perm
147
+ return best_perm
148
+
149
+ try:
150
+ current_shape = input_tensor.shape.as_list()
151
+ except Exception:
152
+ current_shape = None
153
+
154
+ if onnx_input_shape is not None and current_shape is not None:
155
+ onnx_shape = [
156
+ dim if isinstance(dim, int) else None for dim in onnx_input_shape
157
+ ]
158
+ cur_shape = [
159
+ dim if isinstance(dim, int) else None for dim in current_shape
160
+ ]
161
+ if len(onnx_shape) in (3, 4, 5) \
162
+ and len(cur_shape) == len(onnx_shape) \
163
+ and None not in onnx_shape \
164
+ and None not in cur_shape:
165
+ expected_shape = [onnx_shape[0]] + onnx_shape[2:] + [onnx_shape[1]]
166
+ if cur_shape[0] != onnx_shape[0] \
167
+ and not _shape_matches(cur_shape, expected_shape):
168
+ perm = _best_perm_to_match(cur_shape, expected_shape)
169
+ if perm is not None:
170
+ input_tensor = transpose_with_flexing_deterrence(
171
+ input_tensor=input_tensor,
172
+ perm=list(perm),
173
+ **kwargs,
174
+ )
175
+
122
176
  filter = None
123
177
 
124
178
  auto_pad = graph_node.attrs.get('auto_pad', 'NOTSET')
@@ -146,6 +146,48 @@ def make_node(
146
146
  axis=axis,
147
147
  indices=indices_tensor,
148
148
  )
149
+ indices_rank = None
150
+ if hasattr(indices_tensor, "shape") and indices_tensor.shape is not None:
151
+ try:
152
+ indices_rank = len(indices_tensor.shape)
153
+ except TypeError:
154
+ indices_rank = indices_tensor.shape.rank
155
+ updates_rank = updates_tensor_rank
156
+ broadcast_shape = None
157
+ pad_rank = 0
158
+
159
+ def _pad_and_broadcast(target_tensor, pad_rank, target_shape):
160
+ tensor = target_tensor
161
+ if isinstance(tensor, np.ndarray):
162
+ tensor = tf.convert_to_tensor(tensor)
163
+ if pad_rank <= 0:
164
+ return tf.broadcast_to(tensor, target_shape)
165
+ tensor_shape = tf.shape(tensor)
166
+ new_shape = tf.concat(
167
+ [tf.ones([pad_rank], dtype=tf.int32), tensor_shape],
168
+ axis=0,
169
+ )
170
+ tensor = tf.reshape(tensor, new_shape)
171
+ return tf.broadcast_to(tensor, target_shape)
172
+
173
+ updates_tensor_for_scatter = updates_tensor
174
+ if indices_rank is not None and updates_rank is not None and indices_rank != updates_rank:
175
+ if indices_rank > updates_rank:
176
+ broadcast_shape = tf.shape(indices_tensor)
177
+ pad_rank = indices_rank - updates_rank
178
+ updates_tensor_for_scatter = _pad_and_broadcast(
179
+ updates_tensor,
180
+ pad_rank,
181
+ broadcast_shape,
182
+ )
183
+ else:
184
+ broadcast_shape = tf.shape(updates_tensor)
185
+ pad_rank = updates_rank - indices_rank
186
+ indices_tensor = _pad_and_broadcast(
187
+ indices_tensor,
188
+ pad_rank,
189
+ broadcast_shape,
190
+ )
149
191
  sparsified_dense_idx_shape = updates_tensor_shape
150
192
 
151
193
  if None not in sparsified_dense_idx_shape:
@@ -160,6 +202,13 @@ def make_node(
160
202
  ]
161
203
 
162
204
  idx_tensors_per_axis = tf.meshgrid(*idx_tensors_per_axis, indexing='ij')
205
+ if indices_rank is not None \
206
+ and updates_rank is not None \
207
+ and indices_rank > updates_rank:
208
+ idx_tensors_per_axis = [
209
+ _pad_and_broadcast(idx_tensor, pad_rank, broadcast_shape)
210
+ for idx_tensor in idx_tensors_per_axis
211
+ ]
163
212
  idx_tensors_per_axis[axis] = indices_tensor
164
213
  dim_expanded_idx_tensors_per_axis = [
165
214
  tf.expand_dims(idx_tensor, axis=-1)
@@ -194,7 +243,7 @@ def make_node(
194
243
  )
195
244
 
196
245
  indices = tf.reshape(coordinate, [-1, input_tensor_rank])
197
- updates = tf.reshape(updates_tensor, [-1])
246
+ updates = tf.reshape(updates_tensor_for_scatter, [-1])
198
247
  output = tf.tensor_scatter_nd_update(
199
248
  tensor=input_tensor,
200
249
  indices=indices,
@@ -14,6 +14,7 @@ from onnx2tf.utils.common_functions import (
14
14
  make_tf_node_info,
15
15
  get_replacement_parameter,
16
16
  pre_process_transpose,
17
+ convert_axis,
17
18
  )
18
19
  from onnx2tf.utils.logging import Color
19
20
 
@@ -69,8 +70,20 @@ def make_node(
69
70
  **kwargs,
70
71
  )
71
72
 
73
+ input_tensor_shape = input_tensor.shape
74
+ tensor_rank = len(input_tensor_shape) \
75
+ if input_tensor_shape != tf.TensorShape(None) else 1
76
+
72
77
  axis = graph_node.attrs.get('axis', None)
73
78
  sorted = graph_node.attrs.get('sorted', 1)
79
+ if axis is not None:
80
+ if isinstance(axis, np.ndarray) and axis.shape == ():
81
+ axis = int(axis)
82
+ axis = convert_axis(
83
+ axis=int(axis),
84
+ tensor_rank=tensor_rank,
85
+ before_op_output_shape_trans=before_op_output_shape_trans,
86
+ )
74
87
 
75
88
  # Preserving Graph Structure (Dict)
76
89
  for graph_node_output in graph_node_outputs:
@@ -101,17 +114,64 @@ def make_node(
101
114
 
102
115
  # tf unique returns unsorted tensor, need to sort if option is enabled
103
116
  if sorted:
104
- # TODO: implement sort
105
- error_msg = f'' + \
106
- Color.RED(f'WARNING:') + ' ' + \
107
- f'Sort option in Unique ops is not implemented yet.'
108
- print(error_msg)
109
- assert False, error_msg
110
-
111
- tf_layers_dict[graph_node_outputs[0].name]['tf_node'] = y
112
- tf_layers_dict[graph_node_outputs[1].name]['tf_node'] = indices
113
- tf_layers_dict[graph_node_outputs[2].name]['tf_node'] = inverse_indices
114
- tf_layers_dict[graph_node_outputs[3].name]['tf_node'] = count
117
+ # Sort unique outputs to match ONNX sorted behavior.
118
+ def _argsort_supported(dtype):
119
+ return dtype.is_floating or dtype.is_integer or dtype == tf.bool
120
+
121
+ y_rank = y.shape.rank
122
+ axis_ = axis
123
+ if axis_ is None:
124
+ axis_ = 0
125
+ if axis_ < 0 and y_rank is not None:
126
+ axis_ = axis_ + y_rank
127
+
128
+ def _lexsort_perm(flat_2d):
129
+ if not _argsort_supported(flat_2d.dtype):
130
+ return None
131
+ cols = flat_2d.shape[1]
132
+ if cols is None:
133
+ return None
134
+ order = tf.range(tf.shape(flat_2d)[0])
135
+ for col in reversed(range(cols)):
136
+ col_vals = tf.gather(flat_2d, order)[:, col]
137
+ if col_vals.dtype == tf.bool:
138
+ col_vals = tf.cast(col_vals, tf.int32)
139
+ order = tf.gather(order, tf.argsort(col_vals, stable=True))
140
+ return order
141
+
142
+ order = None
143
+ if y_rank is not None and y_rank == 1:
144
+ if _argsort_supported(y.dtype):
145
+ sort_vals = y
146
+ if sort_vals.dtype == tf.bool:
147
+ sort_vals = tf.cast(sort_vals, tf.int32)
148
+ order = tf.argsort(sort_vals, stable=True)
149
+ elif y_rank is not None and axis_ is not None and 0 <= axis_ < y_rank:
150
+ perm = [axis_] + [i for i in range(y_rank) if i != axis_]
151
+ y_t = tf.transpose(y, perm)
152
+ flat = tf.reshape(y_t, [tf.shape(y_t)[0], -1])
153
+ order = _lexsort_perm(flat)
154
+
155
+ if order is None:
156
+ warn_msg = f'' + \
157
+ Color.YELLOW(f'WARNING:') + ' ' + \
158
+ f'Unique sort fallback to unsorted due to dynamic shape or unsupported dtype.'
159
+ print(warn_msg)
160
+ else:
161
+ y = tf.gather(y, order, axis=axis_)
162
+ count = tf.gather(count, order)
163
+ indices = tf.gather(indices, order)
164
+ inv_order = tf.argsort(order)
165
+ inverse_indices = tf.gather(inv_order, inverse_indices)
166
+
167
+ if len(graph_node_outputs) >= 1:
168
+ tf_layers_dict[graph_node_outputs[0].name]['tf_node'] = y
169
+ if len(graph_node_outputs) >= 2:
170
+ tf_layers_dict[graph_node_outputs[1].name]['tf_node'] = indices
171
+ if len(graph_node_outputs) >= 3:
172
+ tf_layers_dict[graph_node_outputs[2].name]['tf_node'] = inverse_indices
173
+ if len(graph_node_outputs) >= 4:
174
+ tf_layers_dict[graph_node_outputs[3].name]['tf_node'] = count
115
175
 
116
176
  # Generation of Debug Info
117
177
  tf_outputs = {f"output{idx}": value for idx, value in enumerate([y, indices, inverse_indices, count])}