Repository navigation
[Accuracy diff No.95] Fix accuracy diff for paddle.incubate.nn.functional.fused_rotary_position_embedding API - #453
Conversation
|
Thanks for your contribution! |
|
以下给出了一个最小可复现代码,展示了 Paddle 和 Torch 在计算旋转位置编码反向时的不同。
正向计算: 反向计算的 Paddle 版本和正向计算一致,除了正负号相反。而 Torch 反向计算逻辑为 |
cangtianhuang
left a comment
There was a problem hiding this comment.
@LCStayingdullCircuit 同学也对 fused_rotary_position_embedding 的 Rule 进行了修改工作,麻烦邹同学也看看这个 pr~
相关工作:
此外,这份代码中对 np 对使用不正确,我正在进行修改😉:
| # Process None output | ||
| torch_output_not_None = [] | ||
| for i in range(len(torch_output)): | ||
| if torch_output[i] is not None: | ||
| torch_output_not_None.append(torch_output[i]) | ||
| if len(torch_output_not_None) < len(torch_output): | ||
| torch_output = torch_output_not_None | ||
| else: | ||
| del torch_output_not_None |
There was a problem hiding this comment.
能否修改 gen_torch_output_and_output_grad , 允许 None 值进入后续比较,这样做的可能好处有:
- 支持列表长度的比较,比如 paddle 与 torch 的输出都有三个,其中后两个是 None;
- 不同顺序的比较可以报错,比如 [1, None, 2] 与 [1, 2, None] 的比较
There was a problem hiding this comment.
尝试过如果在 gen_torch_output_and_output_grad 函数里允许 None 值进入后续处理,有多处例如 "xx.shape"、"xx.dtype" 需要一并修改以处理 None,修改会比较多。
|
更新了对 None 结果的处理方式。在 |
| for output in outputs: | ||
| if (output is not None) and (not isinstance(output, paddle.Tensor) or output.size != 0): | ||
| result_outputs.append(output) |
There was a problem hiding this comment.
| for output in outputs: | |
| if (output is not None) and (not isinstance(output, paddle.Tensor) or output.size != 0): | |
| result_outputs.append(output) | |
| result_outputs = [output for output in outputs | |
| if output is not None and isinstance(output, paddle.Tensor) and output.size != 0] |
| elif (paddle_out is None or paddle_out.size == 0) and torch_output is None: | ||
| pass |
There was a problem hiding this comment.
为什么需要检查 paddle_out.size == 0 呢?
| elif isinstance(outputs, tuple): | ||
| for output in outputs: | ||
| if isinstance(output, paddle.Tensor): | ||
| if isinstance(output, paddle.Tensor) and output.size != 0: |
| if output is None or output.size == 0: | ||
| continue |
| if numpy_tensor is None or numpy_tensor.size == 0: | ||
| continue |
| for output in outputs: | ||
| if output is not None: | ||
| result_outputs.append(output) |
There was a problem hiding this comment.
| for output in outputs: | |
| if output is not None: | |
| result_outputs.append(output) | |
| result_outputs = [output for output in outputs if output is not None] |
| if numpy_tensor is None: | ||
| continue |
本 PR 主要解决两个问题:
对 None 结果的处理
新增了对 None 结果的处理。动机来源于
fused_rotary_position_embedding可接受 Q、K、V 三个变量,后两个可以为 None。但无论是否有 None,Padlle 都将输出一个三个元素的 Tuple;如果某个变量传入为 None,那么该位置的输出为 Tensor(Not Initialized)。但目前框架未对 None 变量输出进行处理,导致在以下处抛出异常:。而在外层会接收该异常并不再继续进行 Torch 的 grad 操作,并只检查前向结果。这导致了原有测试有大量只通过了前向即输出 Pass 的测试。
因此本 PR 增加了对 None 结果的处理:
accuracy.py前向结果比较时, None 参与比较。base.py计算梯度时,None 结果不参与梯度计算。fused_rotary_position_embeddingAPI 精度问题统计发现所有测试用例的前向结果均能通过测试,而反向结果有错。经过源码分析发现 Paddle 实现正确,而 Torch 的反向结果有误。评论区将详细阐述。
本 PR 进行
tester/api_config/5_accuracy/accuracy_gpu_error_uncertain.txt中的 60 个测试: