{"record":{"id":"17416cf980c34957","repo":"tracel-ai/burn","slug":"can-t-differentiate-adaptive-avg-pool3d-backward","errorCode":null,"errorMessage":"Can't differentiate adaptive avg pool3d backward.","messagePattern":"Can't differentiate adaptive avg pool3d backward\\.","errorType":"panic","errorClass":null,"httpStatus":null,"severity":"error","filePath":"crates/burn-autodiff/src/ops/module.rs","lineNumber":1879,"sourceCode":"            .prepare::<C>([x.node.clone()])\n            .compute_bound()\n            .stateful()\n        {\n            OpsKind::Tracked(mut prep) => {\n                let x_state = prep.checkpoint(&x);\n                prep.finish(x_state, B::adaptive_avg_pool3d(x.primitive, output_size))\n            }\n            OpsKind::UnTracked(prep) => {\n                prep.finish(B::adaptive_avg_pool3d(x.primitive, output_size))\n            }\n        }\n    }\n\n    fn adaptive_avg_pool3d_backward(\n        _x: AutodiffTensor<B>,\n        _grad: AutodiffTensor<B>,\n    ) -> AutodiffTensor<B> {\n        panic!(\"Can't differentiate adaptive avg pool3d backward.\");\n    }\n\n    fn interpolate(\n        x: AutodiffTensor<B>,\n        output_size: [usize; 2],\n        options: InterpolateOptions,\n    ) -> AutodiffTensor<B> {\n        #[derive(Debug)]\n        struct Interpolate;\n        impl<B: Backend> Backward<B, 1> for Interpolate {\n            type State = (NodeId, [usize; 2], InterpolateOptions);\n\n            fn backward(\n                self,\n                ops: Ops<Self::State, 1>,\n                grads: &mut Gradients,\n                checkpointer: &mut Checkpointer,\n            ) {","sourceCodeStart":1861,"sourceCodeEnd":1897,"githubUrl":"https://github.com/tracel-ai/burn/blob/d16f7ba2ed0d41408189384044cc886fb4c8f957/crates/burn-autodiff/src/ops/module.rs#L1861-L1897","documentation":"adaptive_avg_pool3d_backward is a stub that panics: the autodiff backend provides no gradient rule for adaptive average pooling in 3D. The forward op works, but any training step that backpropagates through it fails at runtime.","triggerScenarios":"Backpropagating through adaptive_avg_pool3d (e.g. video or volumetric model heads pooling to a fixed output size) using the autodiff backend.","commonSituations":"3D CNNs (video classification, medical volume models) with adaptive pooling heads; converting PyTorch models using AdaptiveAvgPool3d to burn.","solutions":["Use a fixed-kernel avg_pool3d whose gradient is implemented, if input sizes allow","Reshape/volume-mean decomposition using supported ops (slice/reshape/mean) so autodiff can differentiate","Run the pooling forward on the inner backend and stop gradients at that boundary","Implement adaptive_avg_pool3d_backward in the backend using the burn-autodiff Backward framework"],"exampleFix":"// before\nlet pooled = adaptive_avg_pool3d(&x, [1, 4, 4]);\n// after\nlet pooled = avg_pool3d(&x, [2, 8, 8], [2, 8, 8], [0, 0, 0], true, false); // sizes known at compile time","handlingStrategy":"fallback","validationCode":"if model_uses_adaptive_avg_pool3d && is_training {\n    eprintln!(\"adaptive_avg_pool3d backward panics in burn-autodiff; use fixed avg_pool3d\");\n}","typeGuard":null,"tryCatchPattern":null,"preventionTips":["Use fixed-kernel avg_pool3d when input volumes have static shapes","Decompose pooling into supported ops (reshape/mean) when shapes permit","Detach at 3D pooling boundaries if gradients are not needed below it"],"tags":["rust","autodiff","unimplemented","backward-pass"],"backgroundTag":"unimplemented-op-backward","analyzedSha":"d16f7ba2ed0d41408189384044cc886fb4c8f957","analyzedAt":"2026-09-05T13:19:14.260Z","contentChangedAt":"2026-09-05T13:19:14.260Z","schemaVersion":2},"datasetVersion":"2026-09-12T17:17:11.597Z"}