Skip to content
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

Add ONNX support to KRCNNConvDeconvUpsampleHead #4315

Conversation

thiagocrepaldi
Copy link
Contributor

@thiagocrepaldi thiagocrepaldi commented Jun 6, 2022

In order to export KRCNNConvDeconvUpsampleHead to ONNX using torch.jit.script, changes to both PyTorch and detectron2:

  • Pytorch has a bug which prevents a tensor wrapped by a list as float. Refer to the required fix

  • detectron2/structures/keypoints.py::heatmaps_to_keypoints internally does advanced indexing on a squeezed tensor. The aforementioned squeeze fails rank inference due to the presence of onnx::If on its implementation (to support dynamic dims). The fix is replacing squeeze by reshape. A possible fix to squeeze on PyTorch side might be done too (TBD and would take some time), but the proposed change here does not bring any consequence to detectron2 while it enables ONNX support with scriptable KRCNNConvDeconvUpsampleHead .

After the proposed changes, the KRCNNConvDeconvUpsampleHead does include a Loop node to represent a for-loop inside the model and dynamic outputs, as shown below:

image

This PR has been tested with ONNX Runtime (this PR) to ensure the ONNX output matches PyTorch's for different gen_input(X, Y) combinations and it succeeded. The model was converted to ONNX once with a particular input and tested with inputs of different shapes and compared to equality to PyTorch's
Depends on: pytorch/pytorch#81386 and #4291

@facebook-github-bot facebook-github-bot added the CLA Signed This label is managed by the Facebook bot. Authors need to sign the CLA before a PR can be reviewed. label Jun 6, 2022
tests/test_export_onnx.py Outdated Show resolved Hide resolved
@thiagocrepaldi thiagocrepaldi force-pushed the thiagofc/export-onnx-KRCNNConvDeconvUpsampleHead branch from f2bc516 to d9a65ee Compare June 15, 2022 22:19
@thiagocrepaldi thiagocrepaldi requested a review from ppwwyyxx June 15, 2022 22:21
@thiagocrepaldi thiagocrepaldi force-pushed the thiagofc/export-onnx-KRCNNConvDeconvUpsampleHead branch from d9a65ee to b2aa17f Compare June 15, 2022 22:25
@thiagocrepaldi

This comment was marked as outdated.

@thiagocrepaldi

This comment was marked as outdated.

@thiagocrepaldi thiagocrepaldi force-pushed the thiagofc/export-onnx-KRCNNConvDeconvUpsampleHead branch 2 times, most recently from cb7c08b to d4d3ec2 Compare July 13, 2022 23:41
@thiagocrepaldi
Copy link
Contributor Author

thiagocrepaldi commented Jul 13, 2022

@ppwwyyxx @mcimpoi I've managed to export this model to ONNX using torch.jit.script.
See what you think :)

@thiagocrepaldi thiagocrepaldi force-pushed the thiagofc/export-onnx-KRCNNConvDeconvUpsampleHead branch 3 times, most recently from a7aa3b9 to b92ca14 Compare July 16, 2022 06:10
@thiagocrepaldi
Copy link
Contributor Author

@ppwwyyxx https://github.com/facebookresearch/detectron2/pull/4205/files#diff-7d768d0cd0f46e5999dcab0cb5f2f7a101611e771ff0483869568aa01e0b5240R95-R142 will test the correct dynamic axes behavior once both PRs are merged. Local testing verified it

@thiagocrepaldi thiagocrepaldi force-pushed the thiagofc/export-onnx-KRCNNConvDeconvUpsampleHead branch from b92ca14 to 5c356fe Compare August 11, 2022 19:53
@thiagocrepaldi
Copy link
Contributor Author

@ppwwyyxx @mcimpoi Could you review this one when you have some time? Thanks

@thiagocrepaldi
Copy link
Contributor Author

@ppwwyyxx @mcimpoi Could you review this one when you have some time? Thanks

gentle ping

@thiagocrepaldi thiagocrepaldi force-pushed the thiagofc/export-onnx-KRCNNConvDeconvUpsampleHead branch from 5c356fe to d969d8f Compare August 25, 2022 18:28
@thiagocrepaldi
Copy link
Contributor Author

@wat3rBro Could you review this one when you have some time? Thanks

@thiagocrepaldi thiagocrepaldi force-pushed the thiagofc/export-onnx-KRCNNConvDeconvUpsampleHead branch from d969d8f to ac7b413 Compare September 7, 2022 16:51
@thiagocrepaldi
Copy link
Contributor Author

Rebasing to allow up-to-date review

@thiagocrepaldi thiagocrepaldi force-pushed the thiagofc/export-onnx-KRCNNConvDeconvUpsampleHead branch from ac7b413 to dab1cf2 Compare September 20, 2022 15:50
@thiagocrepaldi thiagocrepaldi force-pushed the thiagofc/export-onnx-KRCNNConvDeconvUpsampleHead branch from dab1cf2 to 88a738c Compare October 3, 2022 13:48
@thiagocrepaldi thiagocrepaldi force-pushed the thiagofc/export-onnx-KRCNNConvDeconvUpsampleHead branch from 88a738c to f0e2bb7 Compare October 31, 2022 15:54
@thiagocrepaldi
Copy link
Contributor Author

@ppwwyyxx @mcimpoi @wat3rBro gentle ping

@thiagocrepaldi thiagocrepaldi force-pushed the thiagofc/export-onnx-KRCNNConvDeconvUpsampleHead branch from f0e2bb7 to 8a8ee8d Compare January 19, 2023 19:16
@martpie
Copy link

martpie commented Jan 24, 2023

@thiagocrepaldi Sorry for the delay, we're trying to ping people internally so they can have a look.

@thiagocrepaldi thiagocrepaldi force-pushed the thiagofc/export-onnx-KRCNNConvDeconvUpsampleHead branch from 8a8ee8d to b774488 Compare January 25, 2023 18:10
@thiagocrepaldi
Copy link
Contributor Author

@malfet FYI

Copy link
Contributor

@ppwwyyxx ppwwyyxx left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM, thanks!


# Although semantically equivalent, `reshape` is used instead of `squeeze` due
# to limitation during ONNX export of `squeeze` in scripting mode
roi_map = roi_map.reshape(roi_map.shape[1:]) # keypoints x H x W
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Would appreciate it if comment could link to an issue in pytorch or onnx

Copy link
Contributor

@wat3rBro wat3rBro left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

thanks!

@facebook-github-bot
Copy link
Contributor

@wat3rBro has imported this pull request. If you are a Meta employee, you can view this diff on Phabricator.

@facebook-github-bot
Copy link
Contributor

@thiagocrepaldi has updated the pull request. You must reimport the pull request before landing.

@wat3rBro
Copy link
Contributor

wat3rBro commented Feb 1, 2023

@thiagocrepaldi The newly added test fails in Meta's prod environment (pytorch 2.0 alpha + probably outdated ONNX version) due to AttributeError: 'int' object has no attribute 'onnx_type'.

Detailed Error Message
ONNX graph being constructed during exception:
graph(%0 : Float(*, *, *, *, strides=[784, 196, 14, 1], requires_grad=0, device=cpu),
      %predbox1.1 : Float(*, *, strides=[4, 1], requires_grad=0, device=cpu),
      %predbox2.1 : Float(*, *, strides=[4, 1], requires_grad=0, device=cpu),
      %model.model.conv_fcn1.weight : Float(4, 4, 3, 3, strides=[36, 9, 3, 1], requires_grad=1, device=cpu),
      %model.model.conv_fcn1.bias : Float(4, strides=[1], requires_grad=1, device=cpu),
      %model.model.score_lowres.weight : Float(4, 17, 4, 4, strides=[272, 16, 4, 1], requires_grad=1, device=cpu),
      %model.model.score_lowres.bias : Float(17, strides=[1], requires_grad=1, device=cpu)):
  %7 : Long(device=cpu) = onnx::Constant[value={6}](), scope: detectron2.export.flatten.TracingAdapter::/test_export_onnx.TestONNXTracingExport.testKeypointHead.<locals>.M::model
  %8 : Bool(device=cpu) = onnx::Constant[value={0}](), scope: detectron2.export.flatten.TracingAdapter::/test_export_onnx.TestONNXTracingExport.testKeypointHead.<locals>.M::model
  %9 : NoneType = prim::Constant(), scope: detectron2.export.flatten.TracingAdapter::/test_export_onnx.TestONNXTracingExport.testKeypointHead.<locals>.M::model
  %predbox1 : Float(*, *, strides=[4, 1], requires_grad=0, device=cpu) = onnx::Cast[to=1](%predbox1.1), scope: detectron2.export.flatten.TracingAdapter::/test_export_onnx.TestONNXTracingExport.testKeypointHead.<locals>.M::model # /<anonymous>/detectron2/tests/__test_export_onnx__/test_export_onnx#link-tree/detectron2/structures/boxes.py:150:0
  %predbox2 : Float(*, *, strides=[4, 1], requires_grad=0, device=cpu) = onnx::Cast[to=1](%predbox2.1), scope: detectron2.export.flatten.TracingAdapter::/test_export_onnx.TestONNXTracingExport.testKeypointHead.<locals>.M::model # /<anonymous>/detectron2/tests/__test_export_onnx__/test_export_onnx#link-tree/detectron2/structures/boxes.py:150:0
  %12 : Long(2, strides=[1], device=cpu) = onnx::Constant[value= 1  1 [ CPULongType{2} ]]()
  %13 : Long(2, strides=[1], device=cpu) = onnx::Constant[value= 0  0 [ CPULongType{2} ]]()
  %14 : Long(device=cpu) = onnx::Constant[value={1}](), scope: detectron2.export.flatten.TracingAdapter::/test_export_onnx.TestONNXTracingExport.testKeypointHead.<locals>.M::model/detectron2.modeling.roi_heads.keypoint_head.KRCNNConvDeconvUpsampleHead::model/detectron2.layers.wrappers.Conv2d::conv_fcn1
  %15 : Bool(device=cpu) = onnx::Constant[value={1}](), scope: detectron2.export.flatten.TracingAdapter::/test_export_onnx.TestONNXTracingExport.testKeypointHead.<locals>.M::model/detectron2.modeling.roi_heads.keypoint_head.KRCNNConvDeconvUpsampleHead::model/detectron2.layers.wrappers.Conv2d::conv_fcn1
  %input : Float(*, 4, *, *, strides=[784, 196, 14, 1], requires_grad=0, device=cpu) = onnx::Conv[dilations=[1, 1], group=1, kernel_shape=[3, 3], pads=[1, 1, 1, 1], strides=[1, 1]](%0, %model.model.conv_fcn1.weight, %model.model.conv_fcn1.bias), scope: detectron2.export.flatten.TracingAdapter::/test_export_onnx.TestONNXTracingExport.testKeypointHead.<locals>.M::model/detectron2.modeling.roi_heads.keypoint_head.KRCNNConvDeconvUpsampleHead::model/detectron2.layers.wrappers.Conv2d::conv_fcn1 # /<anonymous>/detectron2/tests/__test_export_onnx__/test_export_onnx#link-tree/detectron2/layers/wrappers.py:113:0
  %17 : Float(*, 4, *, *, strides=[784, 196, 14, 1], requires_grad=0, device=cpu) = onnx::Relu(%input), scope: detectron2.export.flatten.TracingAdapter::/test_export_onnx.TestONNXTracingExport.testKeypointHead.<locals>.M::model/detectron2.modeling.roi_heads.keypoint_head.KRCNNConvDeconvUpsampleHead::model/torch.nn.modules.activation.ReLU::conv_fcn_relu1 # /<anonymous>/detectron2/tests/__test_export_onnx__/test_export_onnx#link-tree/torch/nn/functional.py:1457:0
  %18 : Long(2, strides=[1], device=cpu) = onnx::Constant[value= 2  2 [ CPULongType{2} ]]()
  %x : Float(*, 17, *, *, strides=[13328, 784, 28, 1], requires_grad=0, device=cpu) = onnx::ConvTranspose[dilations=[1, 1], group=1, kernel_shape=[4, 4], pads=[1, 1, 1, 1], strides=[2, 2]](%17, %model.model.score_lowres.weight, %model.model.score_lowres.bias), scope: detectron2.export.flatten.TracingAdapter::/test_export_onnx.TestONNXTracingExport.testKeypointHead.<locals>.M::model/detectron2.modeling.roi_heads.keypoint_head.KRCNNConvDeconvUpsampleHead::model/torch.nn.modules.conv.ConvTranspose2d::score_lowres # /<anonymous>/detectron2/tests/__test_export_onnx__/test_export_onnx#link-tree/torch/nn/modules/conv.py:956:0
  %20 : Float(2, strides=[1], device=cpu) = onnx::Constant[value= 2  2 [ CPUFloatType{2} ]]()
  %21 : Float(2, strides=[1], device=cpu) = onnx::Constant[value= 1  1 [ CPUFloatType{2} ]](), scope: detectron2.export.flatten.TracingAdapter::/test_export_onnx.TestONNXTracingExport.testKeypointHead.<locals>.M::model/detectron2.modeling.roi_heads.keypoint_head.KRCNNConvDeconvUpsampleHead::model # /<anonymous>/detectron2/tests/__test_export_onnx__/test_export_onnx#link-tree/torch/nn/functional.py:3958:0
  %22 : Float(2, strides=[1], device=cpu) = onnx::Constant[value= 2  2 [ CPUFloatType{2} ]](), scope: detectron2.export.flatten.TracingAdapter::/test_export_onnx.TestONNXTracingExport.testKeypointHead.<locals>.M::model/detectron2.modeling.roi_heads.keypoint_head.KRCNNConvDeconvUpsampleHead::model # /<anonymous>/detectron2/tests/__test_export_onnx__/test_export_onnx#link-tree/torch/nn/functional.py:3958:0
  %23 : Float(4, strides=[1], device=cpu) = onnx::Concat[axis=0](%21, %22), scope: detectron2.export.flatten.TracingAdapter::/test_export_onnx.TestONNXTracingExport.testKeypointHead.<locals>.M::model/detectron2.modeling.roi_heads.keypoint_head.KRCNNConvDeconvUpsampleHead::model # /<anonymous>/detectron2/tests/__test_export_onnx__/test_export_onnx#link-tree/torch/nn/functional.py:3958:0
  %24 : Float(0, strides=[1], device=cpu) = onnx::Constant[value=[ CPUFloatType{0} ]](), scope: detectron2.export.flatten.TracingAdapter::/test_export_onnx.TestONNXTracingExport.testKeypointHead.<locals>.M::model/detectron2.modeling.roi_heads.keypoint_head.KRCNNConvDeconvUpsampleHead::model # /<anonymous>/detectron2/tests/__test_export_onnx__/test_export_onnx#link-tree/torch/nn/functional.py:3958:0
  %x.3 : Float(*, 17, *, *, strides=[53312, 3136, 56, 1], requires_grad=0, device=cpu) = onnx::Resize[coordinate_transformation_mode="half_pixel", cubic_coeff_a=-0.75, mode="linear", nearest_mode="floor"](%x, %24, %23), scope: detectron2.export.flatten.TracingAdapter::/test_export_onnx.TestONNXTracingExport.testKeypointHead.<locals>.M::model/detectron2.modeling.roi_heads.keypoint_head.KRCNNConvDeconvUpsampleHead::model # /<anonymous>/detectron2/tests/__test_export_onnx__/test_export_onnx#link-tree/torch/nn/functional.py:3958:0
  %26 : Tensor[] = prim::ListConstruct(%predbox1, %predbox2), scope: detectron2.export.flatten.TracingAdapter::/test_export_onnx.TestONNXTracingExport.testKeypointHead.<locals>.M::model/detectron2.modeling.roi_heads.keypoint_head.KRCNNConvDeconvUpsampleHead::model
  %27 : Long(device=cpu) = onnx::Constant[value={0}](), scope: detectron2.export.flatten.TracingAdapter::/test_export_onnx.TestONNXTracingExport.testKeypointHead.<locals>.M::model/detectron2.modeling.roi_heads.keypoint_head.KRCNNConvDeconvUpsampleHead::model
  %28 : Float(*, *, strides=[4, 1], requires_grad=0, device=cpu) = onnx::Concat[axis=0](%predbox1, %predbox2), scope: detectron2.export.flatten.TracingAdapter::/test_export_onnx.TestONNXTracingExport.testKeypointHead.<locals>.M::model/detectron2.modeling.roi_heads.keypoint_head.KRCNNConvDeconvUpsampleHead::model # /<anonymous>/detectron2/tests/__test_export_onnx__/test_export_onnx#link-tree/detectron2/layers/wrappers.py:46:0
  %29 : Long(device=cpu) = onnx::Constant[value={-1}]()
  %30 : UNKNOWN_SCALAR(device=cpu) = onnx::Constant[value="bicubic"]() # /<anonymous>/detectron2/tests/__test_export_onnx__/test_export_onnx#link-tree/detectron2/structures/keypoints.py:201:62
  %31 : Long(device=cpu) = onnx::Constant[value={2}]()
  %32 : Long(device=cpu) = onnx::Constant[value={3}]()
  %33 : Long(device=cpu) = onnx::Constant[value={4}]()
  %34 : Double(device=cpu) = onnx::Constant[value={0.5}]()
  %offset_x : Float(*, device=cpu) = onnx::Gather[axis=1](%28, %27) # /<anonymous>/detectron2/tests/__test_export_onnx__/test_export_onnx#link-tree/detectron2/structures/keypoints.py:183:15
  %offset_y : Float(*, device=cpu) = onnx::Gather[axis=1](%28, %14) # /<anonymous>/detectron2/tests/__test_export_onnx__/test_export_onnx#link-tree/detectron2/structures/keypoints.py:184:15
  %37 : Float(*, device=cpu) = onnx::Gather[axis=1](%28, %31) # /<anonymous>/detectron2/tests/__test_export_onnx__/test_export_onnx#link-tree/detectron2/structures/keypoints.py:186:14
  %38 : Float(*, device=cpu) = onnx::Sub(%37, %offset_x) # /<anonymous>/detectron2/tests/__test_export_onnx__/test_export_onnx#link-tree/detectron2/structures/keypoints.py:186:14
  %39 : Float(device=cpu) = onnx::Cast[to=1](%14) # /<anonymous>/detectron2/tests/__test_export_onnx__/test_export_onnx#link-tree/detectron2/structures/keypoints.py:186:14
  %40 : Float(device=cpu) = onnx::Cast[to=1](%39) # /<anonymous>/detectron2/tests/__test_export_onnx__/test_export_onnx#link-tree/detectron2/structures/keypoints.py:186:14
  %41 : Tensor? = prim::Constant() # /<anonymous>/detectron2/tests/__test_export_onnx__/test_export_onnx#link-tree/detectron2/structures/keypoints.py:186:14
  %widths : Float(*, device=cpu) = onnx::Clip(%38, %40, %41) # /<anonymous>/detectron2/tests/__test_export_onnx__/test_export_onnx#link-tree/detectron2/structures/keypoints.py:186:14
  %43 : Float(*, device=cpu) = onnx::Gather[axis=1](%28, %32) # /<anonymous>/detectron2/tests/__test_export_onnx__/test_export_onnx#link-tree/detectron2/structures/keypoints.py:187:15
  %44 : Float(*, device=cpu) = onnx::Sub(%43, %offset_y) # /<anonymous>/detectron2/tests/__test_export_onnx__/test_export_onnx#link-tree/detectron2/structures/keypoints.py:187:15
  %45 : Float(device=cpu) = onnx::Cast[to=1](%14) # /<anonymous>/detectron2/tests/__test_export_onnx__/test_export_onnx#link-tree/detectron2/structures/keypoints.py:187:15
  %46 : Float(device=cpu) = onnx::Cast[to=1](%45) # /<anonymous>/detectron2/tests/__test_export_onnx__/test_export_onnx#link-tree/detectron2/structures/keypoints.py:187:15
  %47 : Tensor? = prim::Constant() # /<anonymous>/detectron2/tests/__test_export_onnx__/test_export_onnx#link-tree/detectron2/structures/keypoints.py:187:15
  %heights : Float(*, device=cpu) = onnx::Clip(%44, %46, %47) # /<anonymous>/detectron2/tests/__test_export_onnx__/test_export_onnx#link-tree/detectron2/structures/keypoints.py:187:15
  %widths_ceil : Float(*, device=cpu) = onnx::Ceil(%widths) # /<anonymous>/detectron2/tests/__test_export_onnx__/test_export_onnx#link-tree/detectron2/structures/keypoints.py:188:18
  %heights_ceil : Float(*, device=cpu) = onnx::Ceil(%heights) # /<anonymous>/detectron2/tests/__test_export_onnx__/test_export_onnx#link-tree/detectron2/structures/keypoints.py:189:19
  %51 : Long(4, strides=[1], device=cpu) = onnx::Shape(%x.3) # <string>:13:9
  %52 : Long(1, strides=[1], device=cpu) = onnx::Constant[value={0}]() # /<anonymous>/detectron2/tests/__test_export_onnx__/test_export_onnx#link-tree/detectron2/structures/keypoints.py:191:30
  %53 : Long(1, strides=[1], device=cpu) = onnx::Constant[value={0}]() # /<anonymous>/detectron2/tests/__test_export_onnx__/test_export_onnx#link-tree/detectron2/structures/keypoints.py:191:30
  %54 : Long(1, strides=[1], device=cpu) = onnx::Constant[value={2}]() # /<anonymous>/detectron2/tests/__test_export_onnx__/test_export_onnx#link-tree/detectron2/structures/keypoints.py:191:30
  %55 : Long(1, strides=[1], device=cpu) = onnx::Constant[value={1}]() # /<anonymous>/detectron2/tests/__test_export_onnx__/test_export_onnx#link-tree/detectron2/structures/keypoints.py:191:30
  %56 : Long(2, strides=[1], device=cpu) = onnx::Slice(%51, %53, %54, %52, %55) # /<anonymous>/detectron2/tests/__test_export_onnx__/test_export_onnx#link-tree/detectron2/structures/keypoints.py:191:30
  %57 : Long(device=cpu) = onnx::Constant[value={0}]()
  %58 : Long(device=cpu) = onnx::Gather(%56, %57)
  %59 : Long(device=cpu) = onnx::Constant[value={1}]()
  %60 : Long(device=cpu) = onnx::Gather(%56, %59)
  %61 : Long(2, strides=[1], device=cpu) = onnx::Shape(%28) # <string>:13:9
  %62 : Long(1, strides=[1], device=cpu) = onnx::Constant[value={0}]() # /<anonymous>/detectron2/tests/__test_export_onnx__/test_export_onnx#link-tree/detectron2/structures/keypoints.py:192:30
  %63 : Long(device=cpu) = onnx::Constant[value={0}]() # /<anonymous>/detectron2/tests/__test_export_onnx__/test_export_onnx#link-tree/detectron2/structures/keypoints.py:192:30
  %64 : Long(device=cpu) = onnx::Gather[axis=0](%61, %63) # /<anonymous>/detectron2/tests/__test_export_onnx__/test_export_onnx#link-tree/detectron2/structures/keypoints.py:192:30
  %65 : int[] = prim::ListConstruct(%64, %60, %33)
  %xy_preds : Float(*, *, *, device=cpu) = onnx::ConstantOfShape[value={0}](%65) # /<anonymous>/detectron2/tests/__test_export_onnx__/test_export_onnx#link-tree/detectron2/structures/keypoints.py:192:15
  %width_corrections : Float(*, device=cpu) = onnx::Div(%widths, %widths_ceil) # /<anonymous>/detectron2/tests/__test_export_onnx__/test_export_onnx#link-tree/detectron2/structures/keypoints.py:194:24
  %height_corrections : Float(*, device=cpu) = onnx::Div(%heights, %heights_ceil) # /<anonymous>/detectron2/tests/__test_export_onnx__/test_export_onnx#link-tree/detectron2/structures/keypoints.py:195:25
  %69 : Device = prim::device(%x.3)
  %70 : Long(device=cpu) = onnx::Cast[to=7](%60) # /<anonymous>/detectron2/tests/__test_export_onnx__/test_export_onnx#link-tree/detectron2/structures/keypoints.py:197:20
  %71 : Long(device=cpu) = onnx::Constant[value={0}]() # /<anonymous>/detectron2/tests/__test_export_onnx__/test_export_onnx#link-tree/detectron2/structures/keypoints.py:197:20
  %72 : Long(device=cpu) = onnx::Constant[value={1}]() # /<anonymous>/detectron2/tests/__test_export_onnx__/test_export_onnx#link-tree/detectron2/structures/keypoints.py:197:20
  %keypoints_idx : Long(*, device=cpu) = onnx::Range(%71, %70, %72) # /<anonymous>/detectron2/tests/__test_export_onnx__/test_export_onnx#link-tree/detectron2/structures/keypoints.py:197:20
  %74 : Tensor = onnx::Loop(%58, %15, %xy_preds)
    block0(%i.1 : Long(device=cpu), %76 : Float(*, *, *, device=cpu)):
      %77 : Float(device=cpu) = onnx::Gather[axis=0](%heights_ceil, %i.1) # /<anonymous>/detectron2/tests/__test_export_onnx__/test_export_onnx#link-tree/detectron2/structures/keypoints.py:200:23
      %78 : Float(device=cpu) = onnx::Gather[axis=0](%widths_ceil, %i.1) # /<anonymous>/detectron2/tests/__test_export_onnx__/test_export_onnx#link-tree/detectron2/structures/keypoints.py:200:45
      %79 : int[] = prim::ListConstruct(%i.1)
      %80 : Long(1, strides=[1], device=cpu) = onnx::Constant[value={1}]()
      %81 : Long(1, strides=[1], device=cpu) = onnx::Constant[value={1}]()
      %82 : Long(*, strides=[1], device=cpu) = onnx::Reshape(%i.1, %81)
      -> ()
  return ()

Torch IR graph at exception: graph(%0 : Float(*, *, *, *, strides=[784, 196, 14, 1], requires_grad=0, device=cpu),
      %predbox1.1 : Float(*, *, strides=[4, 1], requires_grad=0, device=cpu),
      %predbox2.1 : Float(*, *, strides=[4, 1], requires_grad=0, device=cpu),
      %model.model.conv_fcn1.weight : Float(4, 4, 3, 3, strides=[36, 9, 3, 1], requires_grad=1, device=cpu),
      %model.model.conv_fcn1.bias : Float(4, strides=[1], requires_grad=1, device=cpu),
      %model.model.score_lowres.weight : Float(4, 17, 4, 4, strides=[272, 16, 4, 1], requires_grad=1, device=cpu),
      %model.model.score_lowres.bias : Float(17, strides=[1], requires_grad=1, device=cpu)):
  %1072 : Long(device=cpu) = prim::Constant[value={6}](), scope: detectron2.export.flatten.TracingAdapter::/test_export_onnx.TestONNXTracingExport.testKeypointHead.<locals>.M::model
  %1073 : Bool(device=cpu) = prim::Constant[value={0}](), scope: detectron2.export.flatten.TracingAdapter::/test_export_onnx.TestONNXTracingExport.testKeypointHead.<locals>.M::model
  %681 : NoneType = prim::Constant(), scope: detectron2.export.flatten.TracingAdapter::/test_export_onnx.TestONNXTracingExport.testKeypointHead.<locals>.M::model
  %predbox1 : Float(1, 4, strides=[4, 1], requires_grad=0, device=cpu) = aten::to(%predbox1.1, %1072, %1073, %1073, %681), scope: detectron2.export.flatten.TracingAdapter::/test_export_onnx.TestONNXTracingExport.testKeypointHead.<locals>.M::model # /<anonymous>/detectron2/tests/__test_export_onnx__/test_export_onnx#link-tree/detectron2/structures/boxes.py:150:0
  %predbox2 : Float(2, 4, strides=[4, 1], requires_grad=0, device=cpu) = aten::to(%predbox2.1, %1072, %1073, %1073, %681), scope: detectron2.export.flatten.TracingAdapter::/test_export_onnx.TestONNXTracingExport.testKeypointHead.<locals>.M::model # /<anonymous>/detectron2/tests/__test_export_onnx__/test_export_onnx#link-tree/detectron2/structures/boxes.py:150:0
  %1014 : int[] = prim::Constant[value=[1, 1]]()
  %1017 : int[] = prim::Constant[value=[0, 0]]()
  %1074 : Long(device=cpu) = prim::Constant[value={1}](), scope: detectron2.export.flatten.TracingAdapter::/test_export_onnx.TestONNXTracingExport.testKeypointHead.<locals>.M::model/detectron2.modeling.roi_heads.keypoint_head.KRCNNConvDeconvUpsampleHead::model/detectron2.layers.wrappers.Conv2d::conv_fcn1
  %1075 : Bool(device=cpu) = prim::Constant[value={1}](), scope: detectron2.export.flatten.TracingAdapter::/test_export_onnx.TestONNXTracingExport.testKeypointHead.<locals>.M::model/detectron2.modeling.roi_heads.keypoint_head.KRCNNConvDeconvUpsampleHead::model/detectron2.layers.wrappers.Conv2d::conv_fcn1
  %input : Float(3, 4, 14, 14, strides=[784, 196, 14, 1], requires_grad=0, device=cpu) = aten::_convolution(%0, %model.model.conv_fcn1.weight, %model.model.conv_fcn1.bias, %1014, %1014, %1014, %1073, %1017, %1074, %1073, %1073, %1075, %1075), scope: detectron2.export.flatten.TracingAdapter::/test_export_onnx.TestONNXTracingExport.testKeypointHead.<locals>.M::model/detectron2.modeling.roi_heads.keypoint_head.KRCNNConvDeconvUpsampleHead::model/detectron2.layers.wrappers.Conv2d::conv_fcn1 # /<anonymous>/detectron2/tests/__test_export_onnx__/test_export_onnx#link-tree/detectron2/layers/wrappers.py:113:0
  %741 : Float(3, 4, 14, 14, strides=[784, 196, 14, 1], requires_grad=0, device=cpu) = aten::relu(%input), scope: detectron2.export.flatten.TracingAdapter::/test_export_onnx.TestONNXTracingExport.testKeypointHead.<locals>.M::model/detectron2.modeling.roi_heads.keypoint_head.KRCNNConvDeconvUpsampleHead::model/torch.nn.modules.activation.ReLU::conv_fcn_relu1 # /<anonymous>/detectron2/tests/__test_export_onnx__/test_export_onnx#link-tree/torch/nn/functional.py:1457:0
  %1018 : int[] = prim::Constant[value=[2, 2]]()
  %x.17 : Float(3, 17, 28, 28, strides=[13328, 784, 28, 1], requires_grad=0, device=cpu) = aten::_convolution(%741, %model.model.score_lowres.weight, %model.model.score_lowres.bias, %1018, %1014, %1014, %1075, %1017, %1074, %1073, %1073, %1075, %1075), scope: detectron2.export.flatten.TracingAdapter::/test_export_onnx.TestONNXTracingExport.testKeypointHead.<locals>.M::model/detectron2.modeling.roi_heads.keypoint_head.KRCNNConvDeconvUpsampleHead::model/torch.nn.modules.conv.ConvTranspose2d::score_lowres # /<anonymous>/detectron2/tests/__test_export_onnx__/test_export_onnx#link-tree/torch/nn/modules/conv.py:956:0
  %1022 : float[] = prim::Constant[value=[2., 2.]]()
  %x : Float(3, 17, 56, 56, strides=[53312, 3136, 56, 1], requires_grad=0, device=cpu) = aten::upsample_bilinear2d(%x.17, %681, %1073, %1022), scope: detectron2.export.flatten.TracingAdapter::/test_export_onnx.TestONNXTracingExport.testKeypointHead.<locals>.M::model/detectron2.modeling.roi_heads.keypoint_head.KRCNNConvDeconvUpsampleHead::model # /<anonymous>/detectron2/tests/__test_export_onnx__/test_export_onnx#link-tree/torch/nn/functional.py:3958:0
  %767 : Tensor[] = prim::ListConstruct(%predbox1, %predbox2), scope: detectron2.export.flatten.TracingAdapter::/test_export_onnx.TestONNXTracingExport.testKeypointHead.<locals>.M::model/detectron2.modeling.roi_heads.keypoint_head.KRCNNConvDeconvUpsampleHead::model
  %1076 : Long(device=cpu) = prim::Constant[value={0}](), scope: detectron2.export.flatten.TracingAdapter::/test_export_onnx.TestONNXTracingExport.testKeypointHead.<locals>.M::model/detectron2.modeling.roi_heads.keypoint_head.KRCNNConvDeconvUpsampleHead::model
  %769 : Float(3, 4, strides=[4, 1], requires_grad=0, device=cpu) = aten::cat(%767, %1076), scope: detectron2.export.flatten.TracingAdapter::/test_export_onnx.TestONNXTracingExport.testKeypointHead.<locals>.M::model/detectron2.modeling.roi_heads.keypoint_head.KRCNNConvDeconvUpsampleHead::model # /<anonymous>/detectron2/tests/__test_export_onnx__/test_export_onnx#link-tree/detectron2/layers/wrappers.py:46:0
  %pred_keypoint_logits : Float(3, 17, 56, 56, strides=[53312, 3136, 56, 1], requires_grad=0, device=cpu) = aten::detach(%x), scope: detectron2.export.flatten.TracingAdapter::/test_export_onnx.TestONNXTracingExport.testKeypointHead.<locals>.M::model/detectron2.modeling.roi_heads.keypoint_head.KRCNNConvDeconvUpsampleHead::model # /<anonymous>/detectron2/tests/__test_export_onnx__/test_export_onnx#link-tree/detectron2/modeling/roi_heads/keypoint_head.py:120:0
  %771 : Float(3, 4, strides=[4, 1], requires_grad=0, device=cpu) = aten::detach(%769), scope: detectron2.export.flatten.TracingAdapter::/test_export_onnx.TestONNXTracingExport.testKeypointHead.<locals>.M::model/detectron2.modeling.roi_heads.keypoint_head.KRCNNConvDeconvUpsampleHead::model # /<anonymous>/detectron2/tests/__test_export_onnx__/test_export_onnx#link-tree/detectron2/modeling/roi_heads/keypoint_head.py:121:0
  %1077 : Long(device=cpu) = prim::Constant[value={-1}]()
  %897 : str = prim::Constant[value="bicubic"]() # /<anonymous>/detectron2/tests/__test_export_onnx__/test_export_onnx#link-tree/detectron2/structures/keypoints.py:201:62
  %1078 : Long(device=cpu) = prim::Constant[value={2}]()
  %1079 : Long(device=cpu) = prim::Constant[value={3}]()
  %1080 : Long(device=cpu) = prim::Constant[value={4}]()
  %1081 : Double(device=cpu) = prim::Constant[value={0.5}]()
  %907 : Tensor = aten::slice(%771, %1076, %681, %681, %1074) # /<anonymous>/detectron2/tests/__test_export_onnx__/test_export_onnx#link-tree/detectron2/structures/keypoints.py:183:15
  %offset_x.1 : Tensor = aten::select(%907, %1074, %1076) # /<anonymous>/detectron2/tests/__test_export_onnx__/test_export_onnx#link-tree/detectron2/structures/keypoints.py:183:15
  %offset_y.1 : Tensor = aten::select(%907, %1074, %1074) # /<anonymous>/detectron2/tests/__test_export_onnx__/test_export_onnx#link-tree/detectron2/structures/keypoints.py:184:15
  %912 : Tensor = aten::select(%907, %1074, %1078) # /<anonymous>/detectron2/tests/__test_export_onnx__/test_export_onnx#link-tree/detectron2/structures/keypoints.py:186:14
  %915 : Tensor = aten::sub(%912, %offset_x.1, %1074) # /<anonymous>/detectron2/tests/__test_export_onnx__/test_export_onnx#link-tree/detectron2/structures/keypoints.py:186:14
  %widths.1 : Tensor = aten::clamp(%915, %1074, %681) # /<anonymous>/detectron2/tests/__test_export_onnx__/test_export_onnx#link-tree/detectron2/structures/keypoints.py:186:14
  %918 : Tensor = aten::select(%907, %1074, %1079) # /<anonymous>/detectron2/tests/__test_export_onnx__/test_export_onnx#link-tree/detectron2/structures/keypoints.py:187:15
  %921 : Tensor = aten::sub(%918, %offset_y.1, %1074) # /<anonymous>/detectron2/tests/__test_export_onnx__/test_export_onnx#link-tree/detectron2/structures/keypoints.py:187:15
  %heights.1 : Tensor = aten::clamp(%921, %1074, %681) # /<anonymous>/detectron2/tests/__test_export_onnx__/test_export_onnx#link-tree/detectron2/structures/keypoints.py:187:15
  %widths_ceil.1 : Tensor = aten::ceil(%widths.1) # /<anonymous>/detectron2/tests/__test_export_onnx__/test_export_onnx#link-tree/detectron2/structures/keypoints.py:188:18
  %heights_ceil.1 : Tensor = aten::ceil(%heights.1) # /<anonymous>/detectron2/tests/__test_export_onnx__/test_export_onnx#link-tree/detectron2/structures/keypoints.py:189:19
  %925 : int[] = aten::size(%pred_keypoint_logits) # <string>:13:9
  %926 : int[] = aten::slice(%925, %681, %1078, %1074) # /<anonymous>/detectron2/tests/__test_export_onnx__/test_export_onnx#link-tree/detectron2/structures/keypoints.py:191:30
  %1068 : Tensor = onnx::Constant[value={0}]()
  %1069 : Tensor = onnx::Gather(%926, %1068)
  %1070 : Tensor = onnx::Constant[value={1}]()
  %1071 : Tensor = onnx::Gather(%926, %1070)
  %929 : int[] = aten::size(%771) # <string>:13:9
  %930 : Long(device=cpu) = aten::__getitem__(%929, %1076) # /<anonymous>/detectron2/tests/__test_export_onnx__/test_export_onnx#link-tree/detectron2/structures/keypoints.py:192:30
  %931 : int[] = prim::ListConstruct(%930, %1071, %1080)
  %xy_preds.1 : Tensor = aten::new_zeros(%pred_keypoint_logits, %931, %681, %681, %681, %681) # /<anonymous>/detectron2/tests/__test_export_onnx__/test_export_onnx#link-tree/detectron2/structures/keypoints.py:192:15
  %width_corrections.1 : Tensor = aten::div(%widths.1, %widths_ceil.1) # /<anonymous>/detectron2/tests/__test_export_onnx__/test_export_onnx#link-tree/detectron2/structures/keypoints.py:194:24
  %height_corrections.1 : Tensor = aten::div(%heights.1, %heights_ceil.1) # /<anonymous>/detectron2/tests/__test_export_onnx__/test_export_onnx#link-tree/detectron2/structures/keypoints.py:195:25
  %935 : Device = prim::device(%pred_keypoint_logits)
  %keypoints_idx.1 : Tensor = aten::arange(%1071, %681, %681, %935, %681) # /<anonymous>/detectron2/tests/__test_export_onnx__/test_export_onnx#link-tree/detectron2/structures/keypoints.py:197:20
  %1041 : Tensor = prim::Loop(%1069, %1075, %xy_preds.1) # /<anonymous>/detectron2/tests/__test_export_onnx__/test_export_onnx#link-tree/detectron2/structures/keypoints.py:199:4
    block0(%i.1 : Long(device=cpu), %1040 : Float(*, *, *, device=cpu)):
      %938 : Tensor = aten::select(%heights_ceil.1, %1076, %i.1) # /<anonymous>/detectron2/tests/__test_export_onnx__/test_export_onnx#link-tree/detectron2/structures/keypoints.py:200:23
      %940 : Tensor = aten::select(%widths_ceil.1, %1076, %i.1) # /<anonymous>/detectron2/tests/__test_export_onnx__/test_export_onnx#link-tree/detectron2/structures/keypoints.py:200:45
      %942 : int[] = prim::ListConstruct(%i.1)
      %943 : Tensor = aten::tensor(%942, %1080, %681, %1073)
      %944 : Tensor?[] = prim::ListConstruct(%943)
      %945 : Tensor = aten::index(%pred_keypoint_logits, %944) # /<anonymous>/detectron2/tests/__test_export_onnx__/test_export_onnx#link-tree/detectron2/structures/keypoints.py:201:32
      %946 : int[] = prim::ListConstruct(%938, %940)
      %roi_map.1 : Tensor = aten::__interpolate(%945, %946, %681, %897, %1073, %681, %1073) # /<anonymous>/detectron2/tests/__test_export_onnx__/test_export_onnx#link-tree/detectron2/structures/keypoints.py:201:18
      %948 : int[] = aten::size(%roi_map.1) # <string>:13:9
      %949 : int[] = aten::slice(%948, %1074, %681, %1074) # /<anonymous>/detectron2/tests/__test_export_onnx__/test_export_onnx#link-tree/detectron2/structures/keypoints.py:205:34
      %roi_map.7 : Tensor = aten::reshape(%roi_map.1, %949) # /<anonymous>/detectron2/tests/__test_export_onnx__/test_export_onnx#link-tree/detectron2/structures/keypoints.py:205:18
      %951 : int[] = prim::ListConstruct(%1071, %1077)
      %952 : Tensor = aten::view(%roi_map.7, %951) # /<anonymous>/detectron2/tests/__test_export_onnx__/test_export_onnx#link-tree/detectron2/structures/keypoints.py:208:23
      %max_score.1 : Tensor, %954 : Tensor = aten::max(%952, %1074, %1073) # /<anonymous>/detectron2/tests/__test_export_onnx__/test_export_onnx#link-tree/detectron2/structures/keypoints.py:208:23
      %955 : int[] = prim::ListConstruct(%1071, %1074, %1074)
      %max_score.5 : Tensor = aten::view(%max_score.1, %955) # /<anonymous>/detectron2/tests/__test_export_onnx__/test_export_onnx#link-tree/detectron2/structures/keypoints.py:209:20
      %957 : Tensor = aten::sub(%roi_map.7, %max_score.5, %1074) # /<anonymous>/detectron2/tests/__test_export_onnx__/test_export_onnx#link-tree/detectron2/structures/keypoints.py:210:31
      %1030 : Tensor = aten::exp(%957) # /<anonymous>/detectron2/tests/__test_export_onnx__/test_export_onnx#link-tree/detectron2/structures/keypoints.py:210:31
      %959 : Tensor = aten::select(%pred_keypoint_logits, %1076, %i.1) # /<anonymous>/detectron2/tests/__test_export_onnx__/test_export_onnx#link-tree/detectron2/structures/keypoints.py:211:31
      %960 : Tensor = aten::sub(%959, %max_score.5, %1074) # /<anonymous>/detectron2/tests/__test_export_onnx__/test_export_onnx#link-tree/detectron2/structures/keypoints.py:211:31
      %1031 : Tensor = aten::exp(%960) # /<anonymous>/detectron2/tests/__test_export_onnx__/test_export_onnx#link-tree/detectron2/structures/keypoints.py:211:31
      %1023 : int[] = prim::Constant[value=[1, 2]]()
      %963 : Tensor = aten::sum(%1031, %1023, %1075, %681) # /<anonymous>/detectron2/tests/__test_export_onnx__/test_export_onnx#link-tree/detectron2/structures/keypoints.py:214:47
      %roi_map_scores.1 : Tensor = aten::div(%1030, %963) # /<anonymous>/detectron2/tests/__test_export_onnx__/test_export_onnx#link-tree/detectron2/structures/keypoints.py:214:25
      %965 : int[] = aten::size(%roi_map.7) # <string>:13:9
      %w.1 : Long(device=cpu) = aten::__getitem__(%965, %1078) # /<anonymous>/detectron2/tests/__test_export_onnx__/test_export_onnx#link-tree/detectron2/structures/keypoints.py:216:12
      %pos.1 : Tensor = aten::argmax(%952, %1074, %1073) # /<anonymous>/detectron2/tests/__test_export_onnx__/test_export_onnx#link-tree/detectron2/structures/keypoints.py:217:14
      %x_int.1 : Tensor = aten::remainder(%pos.1, %w.1) # /<anonymous>/detectron2/tests/__test_export_onnx__/test_export_onnx#link-tree/detectron2/structures/keypoints.py:219:16
      %971 : Tensor = aten::sub(%pos.1, %x_int.1, %1074) # /<anonymous>/detectron2/tests/__test_export_onnx__/test_export_onnx#link-tree/detectron2/structures/keypoints.py:220:17
      %y_int.1 : Tensor = aten::floor_divide(%971, %w.1) # <string>:3:9
      %982 : Tensor = aten::to(%x_int.1, %1072, %1073, %1073, %681) # /<anonymous>/detectron2/tests/__test_export_onnx__/test_export_onnx#link-tree/detectron2/structures/keypoints.py:227:13
      %983 : Tensor = aten::add(%982, %1081, %1074) # /<anonymous>/detectron2/tests/__test_export_onnx__/test_export_onnx#link-tree/detectron2/structures/keypoints.py:227:13
      %984 : Tensor = aten::select(%width_corrections.1, %1076, %i.1) # /<anonymous>/detectron2/tests/__test_export_onnx__/test_export_onnx#link-tree/detectron2/structures/keypoints.py:227:36
      %x.1 : Tensor = aten::mul(%983, %984) # /<anonymous>/detectron2/tests/__test_export_onnx__/test_export_onnx#link-tree/detectron2/structures/keypoints.py:227:13
      %986 : Tensor = aten::to(%y_int.1, %1072, %1073, %1073, %681) # /<anonymous>/detectron2/tests/__test_export_onnx__/test_export_onnx#link-tree/detectron2/structures/keypoints.py:228:13
      %987 : Tensor = aten::add(%986, %1081, %1074) # /<anonymous>/detectron2/tests/__test_export_onnx__/test_export_onnx#link-tree/detectron2/structures/keypoints.py:228:13
      %988 : Tensor = aten::select(%height_corrections.1, %1076, %i.1) # /<anonymous>/detectron2/tests/__test_export_onnx__/test_export_onnx#link-tree/detectron2/structures/keypoints.py:228:36
      %y.1 : Tensor = aten::mul(%987, %988) # /<anonymous>/detectron2/tests/__test_export_onnx__/test_export_onnx#link-tree/detectron2/structures/keypoints.py:228:13
      %990 : Tensor = aten::select(%offset_x.1, %1076, %i.1) # /<anonymous>/detectron2/tests/__test_export_onnx__/test_export_onnx#link-tree/detectron2/structures/keypoints.py:230:32
      %991 : Tensor = aten::add(%x.1, %990, %1074) # /<anonymous>/detectron2/tests/__test_export_onnx__/test_export_onnx#link-tree/detectron2/structures/keypoints.py:230:28
      %992 : Tensor = aten::select(%1040, %1076, %i.1) # /<anonymous>/detectron2/tests/__test_export_onnx__/test_export_onnx#link-tree/detectron2/structures/keypoints.py:230:8
      %993 : Tensor = aten::slice(%992, %1076, %681, %681, %1074) # /<anonymous>/detectron2/tests/__test_export_onnx__/test_export_onnx#link-tree/detectron2/structures/keypoints.py:230:8
      %994 : Tensor = aten::select(%993, %1074, %1076) # /<anonymous>/detectron2/tests/__test_export_onnx__/test_export_onnx#link-tree/detectron2/structures/keypoints.py:230:8
      %1032 : Tensor?[] = prim::ListConstruct()
      %1033 : Tensor = aten::expand_as(%991, %994) # /<anonymous>/detectron2/tests/__test_export_onnx__/test_export_onnx#link-tree/detectron2/structures/keypoints.py:230:8
      %1035 : Tensor = onnx::Placeholder[name="index_put_"](%1040) # /<anonymous>/detectron2/tests/__test_export_onnx__/test_export_onnx#link-tree/detectron2/structures/keypoints.py:230:8
        block0():
          %1036 : Tensor = aten::select(%xy_preds.1, %1076, %i.1) # /<anonymous>/detectron2/tests/__test_export_onnx__/test_export_onnx#link-tree/detectron2/structures/keypoints.py:230:8
          %1037 : Tensor = aten::slice(%1036, %1076, %681, %681, %1074) # /<anonymous>/detectron2/tests/__test_export_onnx__/test_export_onnx#link-tree/detectron2/structures/keypoints.py:230:8
          %1038 : Tensor = aten::select(%1037, %1074, %1076) # /<anonymous>/detectron2/tests/__test_export_onnx__/test_export_onnx#link-tree/detectron2/structures/keypoints.py:230:8
          %1039 : Tensor = aten::index_put_(%1038, %1032, %1033, %1073) # /<anonymous>/detectron2/tests/__test_export_onnx__/test_export_onnx#link-tree/detectron2/structures/keypoints.py:230:8
          -> (%1039)
      %996 : Tensor = aten::select(%offset_y.1, %1076, %i.1) # /<anonymous>/detectron2/tests/__test_export_onnx__/test_export_onnx#link-tree/detectron2/structures/keypoints.py:231:32
      %997 : Tensor = aten::add(%y.1, %996, %1074) # /<anonymous>/detectron2/tests/__test_export_onnx__/test_export_onnx#link-tree/detectron2/structures/keypoints.py:231:28
      %998 : Tensor = aten::select(%1035, %1076, %i.1) # /<anonymous>/detectron2/tests/__test_export_onnx__/test_export_onnx#link-tree/detectron2/structures/keypoints.py:231:8
      %999 : Tensor = aten::slice(%998, %1076, %681, %681, %1074) # /<anonymous>/detectron2/tests/__test_export_onnx__/test_export_onnx#link-tree/detectron2/structures/keypoints.py:231:8
      %1000 : Tensor = aten::select(%999, %1074, %1074) # /<anonymous>/detectron2/tests/__test_export_onnx__/test_export_onnx#link-tree/detectron2/structures/keypoints.py:231:8
      %1042 : Tensor?[] = prim::ListConstruct()
      %1043 : Tensor = aten::expand_as(%997, %1000) # /<anonymous>/detectron2/tests/__test_export_onnx__/test_export_onnx#link-tree/detectron2/structures/keypoints.py:231:8
      %1045 : Tensor = onnx::Placeholder[name="index_put_"](%1035) # /<anonymous>/detectron2/tests/__test_export_onnx__/test_export_onnx#link-tree/detectron2/structures/keypoints.py:231:8
        block0():
          %1046 : Tensor = aten::select(%xy_preds.1, %1076, %i.1) # /<anonymous>/detectron2/tests/__test_export_onnx__/test_export_onnx#link-tree/detectron2/structures/keypoints.py:231:8
          %1047 : Tensor = aten::slice(%1046, %1076, %681, %681, %1074) # /<anonymous>/detectron2/tests/__test_export_onnx__/test_export_onnx#link-tree/detectron2/structures/keypoints.py:231:8
          %1048 : Tensor = aten::select(%1047, %1074, %1074) # /<anonymous>/detectron2/tests/__test_export_onnx__/test_export_onnx#link-tree/detectron2/structures/keypoints.py:231:8
          %1049 : Tensor = aten::index_put_(%1048, %1042, %1043, %1073) # /<anonymous>/detectron2/tests/__test_export_onnx__/test_export_onnx#link-tree/detectron2/structures/keypoints.py:231:8
          -> (%1049)
      %1002 : Tensor?[] = prim::ListConstruct(%keypoints_idx.1, %y_int.1, %x_int.1)
      %1003 : Tensor = aten::index(%roi_map.7, %1002) # /<anonymous>/detectron2/tests/__test_export_onnx__/test_export_onnx#link-tree/detectron2/structures/keypoints.py:232:28
      %1004 : Tensor = aten::select(%1045, %1076, %i.1) # /<anonymous>/detectron2/tests/__test_export_onnx__/test_export_onnx#link-tree/detectron2/structures/keypoints.py:232:8
      %1005 : Tensor = aten::slice(%1004, %1076, %681, %681, %1074) # /<anonymous>/detectron2/tests/__test_export_onnx__/test_export_onnx#link-tree/detectron2/structures/keypoints.py:232:8
      %1006 : Tensor = aten::select(%1005, %1074, %1078) # /<anonymous>/detectron2/tests/__test_export_onnx__/test_export_onnx#link-tree/detectron2/structures/keypoints.py:232:8
      %1050 : Tensor?[] = prim::ListConstruct()
      %1051 : Tensor = aten::expand_as(%1003, %1006) # /<anonymous>/detectron2/tests/__test_export_onnx__/test_export_onnx#link-tree/detectron2/structures/keypoints.py:232:8
      %1053 : Tensor = onnx::Placeholder[name="index_put_"](%1045) # /<anonymous>/detectron2/tests/__test_export_onnx__/test_export_onnx#link-tree/detectron2/structures/keypoints.py:232:8
        block0():
          %1054 : Tensor = aten::select(%xy_preds.1, %1076, %i.1) # /<anonymous>/detectron2/tests/__test_export_onnx__/test_export_onnx#link-tree/detectron2/structures/keypoints.py:232:8
          %1055 : Tensor = aten::slice(%1054, %1076, %681, %681, %1074) # /<anonymous>/detectron2/tests/__test_export_onnx__/test_export_onnx#link-tree/detectron2/structures/keypoints.py:232:8
          %1056 : Tensor = aten::select(%1055, %1074, %1078) # /<anonymous>/detectron2/tests/__test_export_onnx__/test_export_onnx#link-tree/detectron2/structures/keypoints.py:232:8
          %1057 : Tensor = aten::index_put_(%1056, %1050, %1051, %1073) # /<anonymous>/detectron2/tests/__test_export_onnx__/test_export_onnx#link-tree/detectron2/structures/keypoints.py:232:8
          -> (%1057)
      %1008 : Tensor?[] = prim::ListConstruct(%keypoints_idx.1, %y_int.1, %x_int.1)
      %1009 : Tensor = aten::index(%roi_map_scores.1, %1008) # /<anonymous>/detectron2/tests/__test_export_onnx__/test_export_onnx#link-tree/detectron2/structures/keypoints.py:233:28
      %1010 : Tensor = aten::select(%1053, %1076, %i.1) # /<anonymous>/detectron2/tests/__test_export_onnx__/test_export_onnx#link-tree/detectron2/structures/keypoints.py:233:8
      %1011 : Tensor = aten::slice(%1010, %1076, %681, %681, %1074) # /<anonymous>/detectron2/tests/__test_export_onnx__/test_export_onnx#link-tree/detectron2/structures/keypoints.py:233:8
      %1012 : Tensor = aten::select(%1011, %1074, %1079) # /<anonymous>/detectron2/tests/__test_export_onnx__/test_export_onnx#link-tree/detectron2/structures/keypoints.py:233:8
      %1058 : Tensor?[] = prim::ListConstruct()
      %1059 : Tensor = aten::expand_as(%1009, %1012) # /<anonymous>/detectron2/tests/__test_export_onnx__/test_export_onnx#link-tree/detectron2/structures/keypoints.py:233:8
      %1061 : Tensor = onnx::Placeholder[name="index_put_"](%1053) # /<anonymous>/detectron2/tests/__test_export_onnx__/test_export_onnx#link-tree/detectron2/structures/keypoints.py:233:8
        block0():
          %1062 : Tensor = aten::select(%xy_preds.1, %1076, %i.1) # /<anonymous>/detectron2/tests/__test_export_onnx__/test_export_onnx#link-tree/detectron2/structures/keypoints.py:233:8
          %1063 : Tensor = aten::slice(%1062, %1076, %681, %681, %1074) # /<anonymous>/detectron2/tests/__test_export_onnx__/test_export_onnx#link-tree/detectron2/structures/keypoints.py:233:8
          %1064 : Tensor = aten::select(%1063, %1074, %1079) # /<anonymous>/detectron2/tests/__test_export_onnx__/test_export_onnx#link-tree/detectron2/structures/keypoints.py:233:8
          %1065 : Tensor = aten::index_put_(%1064, %1058, %1059, %1073) # /<anonymous>/detectron2/tests/__test_export_onnx__/test_export_onnx#link-tree/detectron2/structures/keypoints.py:233:8
          -> (%1065)
      -> (%1075, %1061)
  %775 : Long(device=cpu) = aten::size(%predbox1, %1076), scope: detectron2.export.flatten.TracingAdapter::/test_export_onnx.TestONNXTracingExport.testKeypointHead.<locals>.M::model/detectron2.modeling.roi_heads.keypoint_head.KRCNNConvDeconvUpsampleHead::model # /<anonymous>/detectron2/tests/__test_export_onnx__/test_export_onnx#link-tree/detectron2/structures/boxes.py:240:0
  %783 : Long(device=cpu) = aten::size(%predbox2, %1076), scope: detectron2.export.flatten.TracingAdapter::/test_export_onnx.TestONNXTracingExport.testKeypointHead.<locals>.M::model/detectron2.modeling.roi_heads.keypoint_head.KRCNNConvDeconvUpsampleHead::model # /<anonymous>/detectron2/tests/__test_export_onnx__/test_export_onnx#link-tree/detectron2/structures/boxes.py:240:0
  %1082 : Long(device=cpu) = prim::Constant[value={9223372036854775807}](), scope: detectron2.export.flatten.TracingAdapter::/test_export_onnx.TestONNXTracingExport.testKeypointHead.<locals>.M::model/detectron2.modeling.roi_heads.keypoint_head.KRCNNConvDeconvUpsampleHead::model
  %794 : Float(3, 17, 4, strides=[68, 4, 1], requires_grad=0, device=cpu) = aten::slice(%1041, %1076, %1076, %1082, %1074), scope: detectron2.export.flatten.TracingAdapter::/test_export_onnx.TestONNXTracingExport.testKeypointHead.<locals>.M::model/detectron2.modeling.roi_heads.keypoint_head.KRCNNConvDeconvUpsampleHead::model # /<anonymous>/detectron2/tests/__test_export_onnx__/test_export_onnx#link-tree/detectron2/modeling/roi_heads/keypoint_head.py:123:0
  %799 : Float(3, 17, 4, strides=[68, 4, 1], requires_grad=0, device=cpu) = aten::slice(%794, %1074, %1076, %1082, %1074), scope: detectron2.export.flatten.TracingAdapter::/test_export_onnx.TestONNXTracingExport.testKeypointHead.<locals>.M::model/detectron2.modeling.roi_heads.keypoint_head.KRCNNConvDeconvUpsampleHead::model # /<anonymous>/detectron2/tests/__test_export_onnx__/test_export_onnx#link-tree/detectron2/modeling/roi_heads/keypoint_head.py:123:0
  %1028 : Long(3, strides=[1], requires_grad=0, device=cpu) = prim::Constant[value= 0  1  3 [ CPULongType{3} ]]()
  %1029 : Tensor[] = prim::ListConstruct(%681, %681, %1028)
  %810 : Float(3, 17, 3, strides=[51, 3, 1], requires_grad=0, device=cpu) = aten::index(%799, %1029), scope: detectron2.export.flatten.TracingAdapter::/test_export_onnx.TestONNXTracingExport.testKeypointHead.<locals>.M::model/detectron2.modeling.roi_heads.keypoint_head.KRCNNConvDeconvUpsampleHead::model # /<anonymous>/detectron2/tests/__test_export_onnx__/test_export_onnx#link-tree/detectron2/modeling/roi_heads/keypoint_head.py:123:0
  %811 : int[] = prim::ListConstruct(%775, %783), scope: detectron2.export.flatten.TracingAdapter::/test_export_onnx.TestONNXTracingExport.testKeypointHead.<locals>.M::model/detectron2.modeling.roi_heads.keypoint_head.KRCNNConvDeconvUpsampleHead::model
  %value.1 : Float(1, 17, 3, strides=[51, 3, 1], requires_grad=0, device=cpu), %value.5 : Float(2, 17, 3, strides=[51, 3, 1], requires_grad=0, device=cpu) = aten::split_with_sizes[_outputs=2](%810, %811, %1076), scope: detectron2.export.flatten.TracingAdapter::/test_export_onnx.TestONNXTracingExport.testKeypointHead.<locals>.M::model/detectron2.modeling.roi_heads.keypoint_head.KRCNNConvDeconvUpsampleHead::model # /<anonymous>/detectron2/tests/__test_export_onnx__/test_export_onnx#link-tree/torch/_tensor.py:799:0
  return (%value.1, %value.5)

============= Diagnostic Run torch.onnx.export version 2.0.0a0+fb ==============
verbose: False, log level: Level.ERROR
======================= 0 NONE 0 NOTE 0 WARNING 0 ERROR ========================


/<anonymous>/detectron2/tests/__test_export_onnx__/test_export_onnx#link-tree/torch/_utils_internal.py:179: NCCL_DEBUG env var is set to None
/<anonymous>/detectron2/tests/__test_export_onnx__/test_export_onnx#link-tree/torch/_utils_internal.py:188: NCCL_DEBUG is INFO from /etc/nccl.conf
testKeypointHead (test_export_onnx.TestONNXTracingExport) ... /<anonymous>/detectron2/tests/__test_export_onnx__/test_export_onnx#link-tree/detectron2/structures/boxes.py:151: TracerWarning: Converting a tensor to a Python boolean might cause the trace to be incorrect. We can't record the data flow of Python values, so this value will be treated as a constant in the future. This means that the trace might not generalize to other inputs!
  if tensor.numel() == 0:
/<anonymous>/detectron2/tests/__test_export_onnx__/test_export_onnx#link-tree/detectron2/structures/boxes.py:155: TracerWarning: Converting a tensor to a Python boolean might cause the trace to be incorrect. We can't record the data flow of Python values, so this value will be treated as a constant in the future. This means that the trace might not generalize to other inputs!
  assert tensor.dim() == 2 and tensor.size(-1) == 4, tensor.size()
/<anonymous>/detectron2/tests/__test_export_onnx__/test_export_onnx#link-tree/detectron2/structures/boxes.py:151: TracerWarning: Converting a tensor to a Python boolean might cause the trace to be incorrect. We can't record the data flow of Python values, so this value will be treated as a constant in the future. This means that the trace might not generalize to other inputs!
  if tensor.numel() == 0:
/<anonymous>/detectron2/tests/__test_export_onnx__/test_export_onnx#link-tree/detectron2/structures/boxes.py:155: TracerWarning: Converting a tensor to a Python boolean might cause the trace to be incorrect. We can't record the data flow of Python values, so this value will be treated as a constant in the future. This means that the trace might not generalize to other inputs!
  assert tensor.dim() == 2 and tensor.size(-1) == 4, tensor.size()
ERROR

======================================================================
ERROR: testKeypointHead (test_export_onnx.TestONNXTracingExport)
----------------------------------------------------------------------
Traceback (most recent call last):
  File "/<anonymous>/detectron2/tests/__test_export_onnx__/test_export_onnx#link-tree/test_export_onnx.py", line 124, in testKeypointHead
    onnx_model = self._test_model(
  File "/<anonymous>/detectron2/tests/__test_export_onnx__/test_export_onnx#link-tree/test_export_onnx.py", line 185, in _test_model
    torch.onnx.export(
  File "/<anonymous>/detectron2/tests/__test_export_onnx__/test_export_onnx#link-tree/torch/onnx/utils.py", line 506, in export
    _export(
  File "/<anonymous>/detectron2/tests/__test_export_onnx__/test_export_onnx#link-tree/torch/onnx/utils.py", line 1533, in _export
    graph, params_dict, torch_out = _model_to_graph(
  File "/<anonymous>/detectron2/tests/__test_export_onnx__/test_export_onnx#link-tree/torch/onnx/utils.py", line 1117, in _model_to_graph
    graph = _optimize_graph(
  File "/<anonymous>/detectron2/tests/__test_export_onnx__/test_export_onnx#link-tree/torch/onnx/utils.py", line 665, in _optimize_graph
    graph = _C._jit_pass_onnx(graph, operator_export_type)
  File "/<anonymous>/detectron2/tests/__test_export_onnx__/test_export_onnx#link-tree/torch/onnx/utils.py", line 1868, in _run_symbolic_function
    return symbolic_fn(graph_context, *inputs, **attrs)
  File "/<anonymous>/detectron2/tests/__test_export_onnx__/test_export_onnx#link-tree/torch/onnx/symbolic_opset9.py", line 6678, in prim_loop
    torch._C._jit_pass_onnx_block(
  File "/<anonymous>/detectron2/tests/__test_export_onnx__/test_export_onnx#link-tree/torch/onnx/utils.py", line 1868, in _run_symbolic_function
    return symbolic_fn(graph_context, *inputs, **attrs)
  File "/<anonymous>/detectron2/tests/__test_export_onnx__/test_export_onnx#link-tree/torch/onnx/symbolic_opset9.py", line 3620, in tensor
    t = g.op("Cast", t, to_i=dtype.onnx_type())
AttributeError: 'int' object has no attribute 'onnx_type'

----------------------------------------------------------------------
Ran 1 test in 0.448s

FAILED (errors=1)

AttributeError: 'int' object has no attribute 'onnx_type'
  File "/<anonymous2>/python3.8/unittest/case.py", line 60, in testPartExecutor
    yield
  File "/<anonymous2>/python3.8/unittest/case.py", line 676, in run
    self._callTestMethod(testMethod)
  File "/<anonymous2>/python3.8/unittest/case.py", line 633, in _callTestMethod
    method()
  File "/<anonymous>/detectron2/tests/__test_export_onnx__/test_export_onnx#link-tree/test_export_onnx.py", line 124, in testKeypointHead
    onnx_model = self._test_model(
  File "/<anonymous>/detectron2/tests/__test_export_onnx__/test_export_onnx#link-tree/test_export_onnx.py", line 185, in _test_model
    torch.onnx.export(
  File "/<anonymous>/detectron2/tests/__test_export_onnx__/test_export_onnx#link-tree/torch/onnx/utils.py", line 506, in export
    _export(
  File "/<anonymous>/detectron2/tests/__test_export_onnx__/test_export_onnx#link-tree/torch/onnx/utils.py", line 1533, in _export
    graph, params_dict, torch_out = _model_to_graph(
  File "/<anonymous>/detectron2/tests/__test_export_onnx__/test_export_onnx#link-tree/torch/onnx/utils.py", line 1117, in _model_to_graph
    graph = _optimize_graph(
  File "/<anonymous>/detectron2/tests/__test_export_onnx__/test_export_onnx#link-tree/torch/onnx/utils.py", line 665, in _optimize_graph
    graph = _C._jit_pass_onnx(graph, operator_export_type)
  File "/<anonymous>/detectron2/tests/__test_export_onnx__/test_export_onnx#link-tree/torch/onnx/utils.py", line 1868, in _run_symbolic_function
    return symbolic_fn(graph_context, *inputs, **attrs)
  File "/<anonymous>/detectron2/tests/__test_export_onnx__/test_export_onnx#link-tree/torch/onnx/symbolic_opset9.py", line 6678, in prim_loop
    torch._C._jit_pass_onnx_block(
  File "/<anonymous>/detectron2/tests/__test_export_onnx__/test_export_onnx#link-tree/torch/onnx/utils.py", line 1868, in _run_symbolic_function
    return symbolic_fn(graph_context, *inputs, **attrs)
  File "/<anonymous>/detectron2/tests/__test_export_onnx__/test_export_onnx#link-tree/torch/onnx/symbolic_opset9.py", line 3620, in tensor
    t = g.op("Cast", t, to_i=dtype.onnx_type())

The error message comes from opset version 9 for prim::Loop, it is suspicious because 1): according to https://github.com/onnx/onnx/blob/b5fac2da36015729dfa42320db099fd26a38e68f/docs/Operators.md, the supported versions for Loop are 16, 13, 11, 1; and 2): the STABLE_ONNX_OPSET_VERSION is specified as 11 (it's used when calling torch.onnx.export). Do you know what goes wrong and how to fix it?

@thiagocrepaldi thiagocrepaldi force-pushed the thiagofc/export-onnx-KRCNNConvDeconvUpsampleHead branch from eee10cb to 7757576 Compare February 3, 2023 16:03
@facebook-github-bot
Copy link
Contributor

@thiagocrepaldi has updated the pull request. You must reimport the pull request before landing.

The fix involves changes to both PyTorch and detectron2:
	* Pytorch had a bug which prevented some tensors to be identified as float
	  (refer to pytorch/pytorch#81386)

	* `detectron2/structures/keypoints.py::heatmaps_to_keypoints` internally
	  does advanced indexing on a `squeeze`d `roi_map`.
	  The aforentioned `squeeze` fails rank inference due to the
	  presence of `onnx::If` on its composition to support dynamic
	  dims. By replacing `squeeze` by `replace` on
	  detectron's `heatmaps_to_keypoints`, shape inference succeeds,
	  allowing ONNX export to succeed with dynamic axes support.
@thiagocrepaldi thiagocrepaldi force-pushed the thiagofc/export-onnx-KRCNNConvDeconvUpsampleHead branch from 7757576 to 1a56083 Compare February 8, 2023 15:33
@facebook-github-bot
Copy link
Contributor

@thiagocrepaldi has updated the pull request. You must reimport the pull request before landing.

@thiagocrepaldi
Copy link
Contributor Author

thiagocrepaldi commented Feb 8, 2023

Yup, this is a regression from newer pytorch. pytorch/pytorch#94427 should fix it

Since yesterday, 2/7/2023, Torch uses ONNX 1.13.0, so the ONNX version shouldn't be an issue

@wat3rBro
Copy link
Contributor

wat3rBro commented Feb 8, 2023

Oh great! pytorch/pytorch#94427 actually solves other tests in test_export_onnx.py for meta prod environment and probably also linux_cpu_tests_pytorch_master from #4205. Thanks!

@thiagocrepaldi
Copy link
Contributor Author

It seems CI is green. Should we merge this before it breaks again? lol

@facebook-github-bot
Copy link
Contributor

@wat3rBro has imported this pull request. If you are a Meta employee, you can view this diff on Phabricator.

@wat3rBro
Copy link
Contributor

wat3rBro commented Feb 9, 2023

Saw the other fix in pytorch/pytorch#94427, now the entire test_export_onnx.py (including the added testKeypointHead) finally passes internally.

@facebook-github-bot
Copy link
Contributor

This pull request has been merged in 1523b3e.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
CLA Signed This label is managed by the Facebook bot. Authors need to sign the CLA before a PR can be reviewed. Merged
Projects
None yet
Development

Successfully merging this pull request may close these issues.

5 participants