Skip to content

Conversation

@zrr1999
Copy link
Member

@zrr1999 zrr1999 commented Jul 16, 2025

PR Category

Operator Mechanism

PR Types

Bug fixes

Description

修复 paddle.nn.functional.adaptive_avg_pool2d 反向的精度问题。增加单测判断梯度和是否符合预期。

错误出现的原因在于 KernelPool2DGrad 中对 pool_size的计算错误,原本的 pool_size 由 pool_height(即 input_height / output_height 向上取整) 和 pool_width 乘积计算得出,但是实际上这样每个位置都会产生误差(除非 input_height 可以被 output_height整除),设Y=adaptive_avg_pool2d(X),对于这个算子我们期望 Y 反向传播回来的梯度可以均匀分配到输入X所有相关的元素上,也就是说X各元素的梯度和与Y各元素的梯度和应该相等,可以验证原本的算法是做不到这点的。

根据adaptive_avg_pool2d的定义我们可以知道,对于Y的每个元素 pool_size 是可能不同的,使用 input_height / output_height 向上取整这个定值是不对的。
正确的计算方法如下:
$\textbf{min} (\lceil \frac{(k+1) h_i}{h_o} \rceil , h_i)-\textbf{max} (\lfloor \frac{k h_i}{h_o} \rfloor, 0)$

可通过下列代码复现

import torch import paddle import numpy device = torch.device("cuda:0") torch.set_default_device(device) def init_input(numpy_tensor): paddle_x = paddle.to_tensor(numpy_tensor) torch_x = torch.tensor(numpy_tensor, requires_grad=True) paddle_x.stop_gradient = False numpy.testing.assert_allclose( paddle_x.numpy(), torch_x.cpu().detach().numpy(), 1e-10, 1e-10, err_msg='intput diff' ) return paddle_x, torch_x # paddle.diff(Tensor([2, 760567127],"float32"), n=1, axis=0, prepend=Tensor([3, 760567127],"float32"), append=None, ) input_tensor = (numpy.ones([1, 1, 7, 7])).astype("float32") paddle_input, torch_input = init_input(input_tensor) paddle_out = paddle.nn.functional.adaptive_avg_pool2d(paddle_input, output_size=(2, 5,), data_format="NCHW", name=None, ) torch_out = torch.nn.functional.adaptive_avg_pool2d(torch_input, output_size=(2, 5,)) print("input:", paddle_input[0][0]) print("torch shape:", torch_out.shape) print("paddle shape:", paddle_out.shape) print("paddle out:", paddle_out[0][0]) print("torch out:", torch_out[0][0]) numpy.testing.assert_allclose( torch_out.cpu().detach().numpy(), paddle_out.numpy(), 1e-2, 1e-2, err_msg='output diff' ) numpy_tensor = (numpy.ones([1, 1, 2, 5])).astype("float32") paddle_grad, torch_grad = init_input(numpy_tensor) torch_x_grad = torch.autograd.grad([torch_out], [torch_input], grad_outputs=torch_grad) paddle_x_grad = paddle.grad([paddle_out], [paddle_input], grad_outputs=paddle_grad, allow_unused=True) print(torch_x_grad[0], torch.sum(torch_x_grad[0])) print(paddle_x_grad[0], paddle.sum(paddle_x_grad[0])) numpy.testing.assert_allclose( torch_x_grad[0].cpu().detach().numpy(), paddle_x_grad[0].numpy(), 1e-2, 1e-2, err_msg='output diff' )

其他内容:
为了提升可读性,给 FastDivMod 结构体添加了 DivCeil方法,其他使用 Divmod 的代码后续也可以优化。

Pcard-67164

@paddle-bot
Copy link

paddle-bot bot commented Jul 16, 2025

你的PR提交成功,感谢你对开源项目的贡献!
请关注后续CI自动化测试结果,详情请参考Paddle-CI手册
Your PR has been submitted. Thanks for your contribution!
Please wait for the result of CI firstly. See Paddle CI Manual for details.

@zrr1999 zrr1999 changed the title [WIP] fix KernelPool2DGrad [Accuracy diff No.106] Fix accuracy diff for paddle.nn.functional.adaptive_avg_pool2d API Jul 17, 2025
@zrr1999 zrr1999 requested review from Copilot and huangjiyi and removed request for Copilot July 17, 2025 08:59
Copy link
Contributor

@wanghuancoder wanghuancoder left a comment

Choose a reason for hiding this comment

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

LGTM 这个让书豪Review一下吧

@zrr1999 zrr1999 merged commit 55face6 into PaddlePaddle:develop Jul 18, 2025
75 of 76 checks passed
@zrr1999 zrr1999 deleted the acc/adaptive_avg_pool branch July 18, 2025 02:19
co63oc pushed a commit to co63oc/Paddle that referenced this pull request Jul 18, 2025
…ptive_avg_pool2d API (PaddlePaddle#74077) * fix KernelPool2DGrad * fix pool2d * improve * add test
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

3 participants