-
Notifications
You must be signed in to change notification settings - Fork 5.6k
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] test atleast_xd pir backward #59365
[Add] test atleast_xd pir backward #59365
Conversation
你的PR提交成功,感谢你对开源项目的贡献! |
关于refresh 的梯度问题, 该设置是为了解决用户在组网后设置的stopgradinet 不生效问题,建议测试在组网前进行设置。concat的stride 执行反向报错可能和stride 有关。从网络中间进行梯度传播是必要的吗 |
这要怎么写测试用例?
这两个测试程序的逻辑基本一样:x (或者 x 和 y) -> out = reshape/concat (x 或者 x, y) -> z = out * 123 然后测试从 z 往前的梯度回传 ~ 第二个测试用例的 import pdb
import numpy as np
import paddle
from paddle.pir_utils import test_with_pir_api
@test_with_pir_api
def test_static_api():
paddle.enable_static()
with paddle.static.program_guard(paddle.static.Program()):
x = paddle.static.data('x', (1, 2), 'float64')
y = paddle.static.data('y', (1, 2), 'float64')
# 这里不应该影响后面需要的梯度回传
# 在 pir 下,这里必须设置为 False,否则出错
# 在旧的静态图下没有问题
x.stop_gradient = False
y.stop_gradient = False
feed = {'x': np.random.rand(1, 2), 'y': np.random.rand(1, 2)}
# pdb.set_trace()
out = paddle.concat((x, y), axis=0)
out.stop_gradient = False
z = out * 123
fetch_list = [out]
if paddle.framework.in_pir_mode():
grads = paddle.autograd.ir_backward.grad(z, out)
out_grad = grads[0]
fetch_list.append(out_grad)
else:
paddle.static.append_backward(z)
out_grad = out.grad_name
fetch_list.append(out_grad)
exe = paddle.static.Executor()
# pdb.set_trace()
*res, res_grad = exe.run(feed=feed, fetch_list=fetch_list)
print(res, res[0].shape, res_grad)
if __name__ == '__main__':
test_static_api() 也是会报错的,不是从网络中间梯度回传 ~ 之前笔误不好意思 ~ |
如果确实有需求,x, y -> out -> z 网络只求z对out 的梯度,我们可以删除refresh操作。 |
我觉得最好是能够跟旧静态图保持一致,以保证兼容 ~ 官方文档也说,"如果静态图中某一层使用stop_gradient=True,那么这一层之前的层都会自动 stop_gradient=True,梯度不再回传。" 是比较合理的处理方式 ~
赞!:) @luotao1 帮忙看一下:
另外,这个 PR 先挂着等问题解决? 谢谢! |
关于stop gradient refresh的问题,已经删除了backward中的相关逻辑,后续PIR组网中需要在创建data的阶段标明stop gradient为false。目前pr还在CI中,待合入。# 59579 |
@xiaoguoguo626807 @changeyoung98 非常感谢二位帮忙定位问题 ~~~ 👍👍👍 平时写应用都是用动态图,所以静态图里面很多东西还不熟悉,还请谅解 ~~~ 🙏🙏🙏 这里还有几个小问题,烦请如果有时间的话帮忙看一下:
下列示例代码: with paddle.static.program_guard(paddle.static.Program()):
x = paddle.static.data('x', (), 'float64')
# A : 在 reshape 之前
feed = {'x': 123.0}
out = paddle.reshape(x, (1,))
# B : 在 reshape 之后
z = out * 123
# C : 在相乘之后
fetch_list = [out]
if paddle.framework.in_pir_mode():
grads = paddle.autograd.ir_backward.grad(z, out)
out_grad = grads[0]
fetch_list.append(out_grad)
OK!那我测试的时候把旧 IR 的跳过去 ~ 🤘🤘🤘 这里 为什么计算梯度的时候是 平时动态图都是这么写的,所以有点困惑,见笑了 ~~~ 😂😂😂 p.s. 如果是因为旧 IR 有问题的话,那就没问题了 ~ PIR 是不是可以写 非常感谢!!!🤗🤗🤗 |
Sorry to inform you that 36cf6e9's CIs have passed for more than 7 days. To prevent PR conflicts, you need to re-run all CIs manually. |
是可以这么写的,之前看program concat被剪掉了感觉有点问题,没注意你是只想要后面部分的梯度😂 另外关于stop gradient的设置问题,简单来说就是在某个需要设置stop gradient的变量创建之后设置即可,
这行代码的意思就是x通过调用.data API创建了出来且被加入了当前的program中去,既是创建也是组网。 |
关于单测里面不测试旧 ir 的梯度回传: # not check old ir
if paddle.framework.in_pir_mode():
# convert grad value to bool if dtype is bool
grad_value = 123.0 if dtypes[0] != 'bool' else True
np.testing.assert_allclose(
res_grad, np.ones_like(y) * grad_value
) 是因为,旧 ir 里面 unsqueeze 的梯度回传应该是有问题 ~ 以下面的测试用例来讲: import numpy as np
import paddle
from paddle.pir_utils import test_with_pir_api
@test_with_pir_api
def test_static_api():
paddle.enable_static()
with paddle.static.program_guard(paddle.static.Program()):
x = paddle.static.data('x', (2, 3), 'float64')
x.stop_gradient = False
feed = {'x': np.random.rand(2, 3).astype('float64')}
out = paddle.unsqueeze(x, [0, 2])
out.stop_gradient = False
z = out * 123
fetch_list = [out]
if paddle.framework.in_pir_mode():
grads = paddle.autograd.ir_backward.grad(z, x)
out_grad = grads[0]
fetch_list.append(out_grad)
else:
paddle.static.append_backward(z)
out_grad = x.grad_name
fetch_list.append(out_grad)
exe = paddle.static.Executor()
*res, res_grad = exe.run(feed=feed, fetch_list=fetch_list)
print(res, res_grad)
if __name__ == '__main__':
test_static_api() 运行后输出为: aistudio@jupyter-942478-6602454:~/test_atleast$ python test_us_pir.py
I1205 12:20:02.233194 679 program_interpreter.cc:212] New Executor is Running.
I1205 12:20:02.233871 679 interpreter_util.cc:624] Standalone Executor is Used.
[array([[[[0.67414195, 0.07585859, 0.11674783]],
[[0.39899884, 0.18764049, 0.25199186]]]])] [[1.23000000e+002 0.00000000e+000 0.00000000e+000]
[3.48520586e-316 3.45845952e-323 1.81776662e-306]]
I1205 12:20:02.243114 679 inplace_pass.cc:473] Apply inplace pass on lowering ::pir::Program to Kernel Dialect.
I1205 12:20:02.243461 679 pir_interpreter.cc:1193] New Executor is Running ...
I1205 12:20:02.243981 679 pir_interpreter.cc:1220] pir interpreter is running by multi-thread mode ...
[array([[[[0.31170326, 0.64944201, 0.60941779]],
[[0.62743311, 0.9468603 , 0.31616582]]]])] [[123. 123. 123.]
[123. 123. 123.]] 可以看到, 第二次的 pir 运行符合预期,梯度为 [[123. 123. 123.]
[123. 123. 123.]] 而旧 ir 的梯度有问题: [[1.23000000e+002 0.00000000e+000 0.00000000e+000]
[3.48520586e-316 3.45845952e-323 1.81776662e-306]] 之前说过,旧 ir 不再维护,因此,单测里面只测试了 pir 的梯度回传 ~ 请评审 ~ 谢谢! |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
LGTM
PR types
Others
PR changes
Others
Description
这个 PR 主要涉及两个部分:
对于 atleast_xd 中的输入为 tensor 的(Tensor, Variable, OpResult),不使用 to_tensor 新建一个
这样可以不改变 tensor 类型的输入,相应的 stop_gradient 等也就不需要重新设置。
之前使用 to_tensor 是因为,如果是 numpy 类似的输入,必定要新建 tensor,因此这里就统一用了 to_tensor 进行新建。
不过,参考 reshape 等方法,stop_gradient 等属性也继承下来了,因此,此处考虑对于 tensor 单独处理,而对于 numpy 等类型使用 to_tensor 进行新建。
请帮忙看一下是否合适?
增加单元测试中静态图的梯度回传测试
【Hackathon 5th No.31】为 Paddle 新增 column_stack / row_stack / dstack / hstack / vstack API -part #59127 这个 PR 里面添加静态图梯度回传的时候,发现目前 pir 下好像还有问题,因此考虑把:
涉及到的 api 都增加静态图梯度回传测试。
目前发现 reshape、concat 好像都有点问题 ~
以下测试环境,aistudio:
测试示例:
执行出错:
初步定位是 paddle/autograd/ir_backward.py 中的 block.refresh_stopgradient() 问题:
可以看到,在执行完 block.refresh_stopgradient() 后,原来 stop_gradient 为 False 的变为了 True,从而导致后续无法获得梯度。
如果将上面示例代码中的
# x.stop_gradient = False
注释打开,这样可以正常运行 ~ 但是这与旧的静态图以及动态图的行为不符 ~参考 https://www.paddlepaddle.org.cn/documentation/docs/zh/develop/faq/train_cn.html#stop-gradient-true ,x 的梯度回传不应该影响到后面的执行 ~
测试示例:
执行出错:
初步定位是 paddle/base/executor.py 中的 self._new_exe.run 问题:
在这个测试示例中,x/y 的 stop_gradient 都设置为 False,否则就会出现之前 reshape 的问题(无法梯度回传),但是设置之后仍然出现上述问题。
上述示例旧的静态图也有问题,只有一种情况可以正常运行:
@test_with_pir_api
注释掉这句,也就是只跑旧的静态图综上,目前我这边的这三个 PR 涉及到的 api 所依赖的 reshape、concat 的静态图梯度回传都有问题(之前测试到 split 的好像也有问题,但似乎这两天被解决了?)
还请帮忙看一下 ~ 非常感谢 ~
@luotao1