Summary
GlobalAveragePoolProcessor::infer_types sets the output type by cloning the input's TensorType, which copies the input's spatial dimensions into the output's static_shape. Per the ONNX spec every spatial dim of the output is 1.
The comment on the line already states the intended behavior:
// Output has the same type and rank as input (spatial dimensions become 1)
node.outputs[0].ty = ArgType::Tensor(input_tensor.clone());
crates/onnx-ir/src/node/global_avg_pool.rs:56-57
Reproduction
A GlobalAveragePool on a [1, 3, 8, 8] input, converted with onnx2burn. From the generated debug dump:
name: "globalaveragepool1_out1",
ty: Tensor(TensorType {
dtype: F32,
rank: 4,
static_shape: Some([Some(1), Some(3), Some(8), Some(8)]),
Expected [Some(1), Some(3), Some(1), Some(1)].
Impact
Rank and dtype are correct, so this does not break the node itself. It misleads anything that trusts static_shape: shape-dependent constant folding, Reshape/Expand/Slice inference, and the partitioner's shape reasoning.
I did not find an actual miscompile in a quick probe. A following Shape node falls back to a runtime dims() read rather than folding the static shape, so it does not surface there. Filing as a latent correctness issue rather than an active one.
Suggested fix
The same rule GlobalLpPool implements in crates/onnx-ir/src/node/global_lp_pool.rs: keep N and C, set every dim from index 2 on to Some(1), and take the length from rank so the shape cannot disagree with the rank field beside it. With two call sites, a small shared helper may be worth extracting.
Summary
GlobalAveragePoolProcessor::infer_typessets the output type by cloning the input'sTensorType, which copies the input's spatial dimensions into the output'sstatic_shape. Per the ONNX spec every spatial dim of the output is 1.The comment on the line already states the intended behavior:
crates/onnx-ir/src/node/global_avg_pool.rs:56-57Reproduction
A
GlobalAveragePoolon a[1, 3, 8, 8]input, converted withonnx2burn. From the generated debug dump:Expected
[Some(1), Some(3), Some(1), Some(1)].Impact
Rank and dtype are correct, so this does not break the node itself. It misleads anything that trusts
static_shape: shape-dependent constant folding, Reshape/Expand/Slice inference, and the partitioner's shape reasoning.I did not find an actual miscompile in a quick probe. A following
Shapenode falls back to a runtimedims()read rather than folding the static shape, so it does not surface there. Filing as a latent correctness issue rather than an active one.Suggested fix
The same rule GlobalLpPool implements in
crates/onnx-ir/src/node/global_lp_pool.rs: keep N and C, set every dim from index 2 on toSome(1), and take the length fromrankso the shape cannot disagree with therankfield beside it. With two call sites, a small shared helper may be worth extracting.