Paddle 【论文复现】paddle的Linear的结果与pytorch的Linear误差很大(在参数值非常大的时候),

vawmfj5a  于 2022-04-21  发布在  Java
关注(0)|答案(7)|浏览(250)

环境:CPU
版本:Paddle 2.1.1

可以发现在x1扩大10倍的条件下,该结果最大误差非常大!

import paddle
import torch
import numpy as np
paddle.set_device("cpu")
paddle.set_grad_enabled(False)
torch.set_grad_enabled(False)
a = paddle.nn.Linear(768,768)

######### 关注一下这个,我设置了权重,竟然之后误差那么大。

a.weight.set_value(paddle.randn(a.weight.shape))
a.bias.set_value(paddle.randn(a.bias.shape))

b = torch.nn.Linear(768,768)
b.weight.data = torch.tensor(a.weight.t().numpy())
b.bias.data = torch.tensor(a.bias.numpy())
x1 = paddle.randn((32,768)) * 10  # 参数扩大十倍
x2 = torch.tensor(x1.numpy())

o1 = a(x1).numpy()
o2 = b(x2).numpy()
print("amax ",np.abs(o1-o2).max())
print("amean ",np.abs(o1-o2).mean())
print(np.all(np.isclose(o1,o2 , atol=0, rtol=1.e-6)))

amax  0.00012207031
amean  7.3685546e-06
False

如果我把赋值权重的部分给注解掉,误差竟然正常了??

import paddle
import torch
import numpy as np
paddle.set_device("cpu")
paddle.set_grad_enabled(False)
torch.set_grad_enabled(False)
a = paddle.nn.Linear(768,768)

################################ 如果注解掉手动设置权重的

# a.weight.set_value(paddle.randn(a.weight.shape))

# a.bias.set_value(paddle.randn(a.bias.shape))

b = torch.nn.Linear(768,768)
b.weight.data = torch.tensor(a.weight.t().numpy())
b.bias.data = torch.tensor(a.bias.numpy())
x1 = paddle.randn((32,768))*10 # 参数扩大十倍
x2 = torch.tensor(x1.numpy())

o1 = a(x1).numpy()
o2 = b(x2).numpy()
print("amax ",np.abs(o1-o2).max())
print("amean ",np.abs(o1-o2).mean())
print(np.all(np.isclose(o1,o2 , atol=0, rtol=1.e-6)))

amax  0.0
amean  0.0
True

如果我先初始化pytorch的权重,然后把pytorch权重赋值给paddle。误差又有了。

import paddle
import torch
import numpy as np
paddle.set_device("cpu")
paddle.set_grad_enabled(False)
torch.set_grad_enabled(False)
b = torch.nn.Linear(768,768)
a = paddle.nn.Linear(768,768)
a.weight.set_value(paddle.to_tensor(b.weight.data.t().numpy()))
a.bias.set_value(paddle.to_tensor(b.bias.data.numpy()))

x1 = paddle.randn((32,768))*10
x2 = torch.tensor(x1.numpy())

o1 = a(x1).numpy()
o2 = b(x2).numpy()
print("amax ",np.abs(o1-o2).max())
print("amean ",np.abs(o1-o2).mean())
print(np.all(np.isclose(o1,o2 , atol=0, rtol=1.e-6)))
amax  1.9073486e-06
amean  1.5580031e-07
False
eh57zj3b

eh57zj3b1#

您好,我们已经收到了您的问题,会安排技术人员尽快解答您的问题,请耐心等待。请您再次检查是否提供了清晰的问题描述、复现代码、环境&版本、报错信息等。同时,您也可以通过查看官网API文档常见问题历史IssueAI社区来寻求解答。祝您生活愉快~

Hi! We've received your issue and please be patient to get responded. We will arrange technicians to answer your questions as soon as possible. Please make sure that you have posted enough message to demo your request. You may also check out the APIFAQGithub Issue and AI community to get the answer.Have a nice day!

epggiuax

epggiuax2#

上面是一个数值精度合理值的问题

  1. 如果把数值放大10倍,同时改变了默认的参数的初始化(默认的参数初始化是一个正态分布,方差比较小), 上面第一部分的示例改变了参数的分布,参数的分布的scale放大,导致了数值精度的问题。
  2. 如果把数值放大10倍, 但是保持了原来的参数初始化的方式,由于参数的mean值的正态分布,同时方差比较小,因此matmul的操作数值diff比较小

如果按照默认初始化方式,linear层的数据输入不是特别大,一般和torch的精度diff会比较小,paddle这块也是监测并优化了相应的op的数值精度的问题。

qq24tv8q

qq24tv8q3#

@wawltor 好的谢谢,我理解了。这是我在复现论文进行精度对齐时候遇到的问题,同样的模型,如果采用方差比较小的正态分布mean=0,std=0.02初始化模型并进行精度对齐。发现误差正常!结果如下。

mean dif: tensor(8.7896e-07) 
max dif: tensor(4.7684e-06)

而如果加载了预训练权重,发现误差会达到快10-3级别。通过分析,我得出模型主要是在通过linear层后,最大误差突然变大。

mean dif: tensor(2.6582e-05) 
max dif: tensor(0.0009)

请问在这种情况下,能认为模型精度基本对齐吗?

8e2ybdfx

8e2ybdfx4#

还有这里的误差存在是只针对于可优化的Parameter吗?我使用tensor进行类似矩阵乘法的操作,并未产生误差。

(这除了自定义的weight和bias不可训练,基本等价于第一个例子)

import paddle
import torch
import numpy as np
paddle.set_device("cpu")
paddle.set_grad_enabled(False)
torch.set_grad_enabled(False)

# 假装我定义了类似paddle.nn.Linear使用randn进行初始化

pd_linear_weight = paddle.randn((768,768))
pd_linear_bias = paddle.randn((768,))

# 我也定义了类似torch.nn.Linear并使用paddle权重进行初始化

pt_linear_weight = torch.tensor(pd_linear_weight.t().numpy())
pt_linear_bias = torch.tensor(pd_linear_bias.numpy())

# 初始化输入

pd_inputs = paddle.randn((32,768)) * 10  # 参数扩大十倍
pt_inputs = torch.tensor(pd_inputs.numpy())

o1 = paddle.matmul(pd_inputs,pd_linear_weight,transpose_y=True) + pd_linear_bias
o2 = torch.matmul(pt_inputs,pt_linear_weight)  + pt_linear_bias
o1 = o1.numpy()
o2 = o2.numpy()

print("amax ",np.abs(o1-o2).max())
print("amean ",np.abs(o1-o2).mean())
print(np.all(np.isclose(o1,o2 , atol=0, rtol=1.e-6)))
amax  0.0
amean  0.0
True
v2g6jxz6

v2g6jxz65#

再来一个对比。这个让我很迷惑。

第一个例子forward方法手工matmul的对比

import paddle
import torch
import numpy as np

# 这是cpu环境下。修改成gpu再试试

device = "cuda"
paddle.set_device("gpu" if device=="cuda" else "cpu")

paddle.set_grad_enabled(False)
torch.set_grad_enabled(False)

# 定义模型

paddle_linear = paddle.nn.Linear(768,768)
paddle_linear.eval()
paddle_linear.weight.set_value(paddle.randn(paddle_linear.weight.shape))
paddle_linear.bias.set_value(paddle.randn(paddle_linear.bias.shape))

# 定义模型

torch_linear = torch.nn.Linear(768,768)
torch_linear.eval()
torch_linear.weight.data = torch.tensor(paddle_linear.weight.t().numpy())
torch_linear.bias.data = torch.tensor(paddle_linear.bias.numpy())
torch_linear.to(device)

# 定义输入

paddle_inputs = paddle.randn((32,768)) * 10 
torch_inputs = torch.tensor(paddle_inputs.numpy()).to(device)

# 前向输出

paddle_outputs = paddle_linear(paddle_inputs).numpy()
torch_outputs = torch_linear(torch_inputs).cpu().numpy()

print("使用forward方法。")
print("abs max:",np.abs(paddle_outputs-torch_outputs).max())
print("abs mean:",np.abs(paddle_outputs-torch_outputs).mean())
print("isclose:", np.all(np.isclose(paddle_outputs,torch_outputs , atol=0, rtol=1.e-6)))

# paddle matmul与torch matmul对比

print("paddle matmul与torch matmul对比")
paddle_shougong_outputs = (paddle.matmul(paddle_inputs,paddle_linear.weight) + paddle_linear.bias).numpy()
torch_shougong_outputs = (torch.matmul(torch_inputs, torch_linear.weight.t()) + torch_linear.bias).cpu().numpy()
print("abs max:",np.abs(paddle_shougong_outputs-torch_shougong_outputs).max())
print("abs mean:",np.abs(paddle_shougong_outputs-torch_shougong_outputs).mean())
print("isclose:", np.all(np.isclose(paddle_shougong_outputs,torch_shougong_outputs, atol=0, rtol=1.e-6)))

# paddle forward与paddle matmul对比

print("paddle forward与paddle matmul对比")
print("abs max:",np.abs(paddle_shougong_outputs-paddle_outputs).max())
print("abs mean:",np.abs(paddle_shougong_outputs-paddle_outputs).mean())
print("isclose:", np.all(np.isclose(paddle_shougong_outputs,paddle_outputs, atol=0, rtol=1.e-6)))

# paddle forward与torch matmul对比

print("paddle forward与torch matmul对比")
print("abs max:",np.abs(paddle_outputs-torch_shougong_outputs).max())
print("abs mean:",np.abs(paddle_outputs-torch_shougong_outputs).mean())
print("isclose:", np.all(np.isclose(paddle_outputs,torch_shougong_outputs, atol=0, rtol=1.e-6)))

# torch forward与torch matmul对比

print("torch forward与torch matmul对比")
print("abs max:",np.abs(torch_outputs-torch_shougong_outputs).max())
print("abs mean:",np.abs(torch_outputs-torch_shougong_outputs).mean())
print("isclose:", np.all(np.isclose(torch_outputs,torch_shougong_outputs, atol=0, rtol=1.e-6)))

## 输出

##### cpu条件下

# 使用forward方法。

# abs max: 0.00012207031

# abs mean: 7.5253715e-06

# isclose: False

# paddle matmul与torch matmul对比

# abs max: 0.0

# abs mean: 0.0

# isclose: True

# paddle forward与paddle matmul对比

# abs max: 0.0

# abs mean: 0.0

# isclose: True

# paddle forward与torch matmul对比

# abs max: 0.0

# abs mean: 0.0

# isclose: True

# torch forward与torch matmul对比

# abs max: 0.00012207031

# abs mean: 7.5253715e-06

# isclose: False

### gpu条件下(RTX2060)

# 使用forward方法。

# abs max: 0.0

# abs mean: 0.0

# isclose: True

# paddle matmul与torch matmul对比

# abs max: 0.0

# abs mean: 0.0

# isclose: True

# paddle forward与paddle matmul对比

# abs max: 0.0

# abs mean: 0.0

# isclose: True

# paddle forward与torch matmul对比

# abs max: 0.0

# abs mean: 0.0

# isclose: True

# torch forward与torch matmul对比

# abs max: 0.0

# abs mean: 0.0

# isclose: True
pbossiut

pbossiut6#

@wawltor 好的谢谢,我理解了。这是我在复现论文进行精度对齐时候遇到的问题,同样的模型,如果采用方差比较小的正态分布mean=0,std=0.02初始化模型并进行精度对齐。发现误差正常!结果如下。

mean dif: tensor(8.7896e-07) 
max dif: tensor(4.7684e-06)

而如果加载了预训练权重,发现误差会达到快10-3级别。通过分析,我得出模型主要是在通过linear层后,最大误差突然变大。

mean dif: tensor(2.6582e-05) 
max dif: tensor(0.0009)

请问在这种情况下,能认为模型精度基本对齐吗?

目前在cpu的状态下,torch和paddle的matmul的实现方式不太一样,在数值scale比较大的情况下,目前存在不一样的情况;
判断是否对齐,可以做两个实验
1)在cuda的情况下 对齐情况如何,如果能对齐则可以任务收敛了
2)我理解现在是验证finetune的模型效果,可以验证一下finetune在各个数据集的效果,如果能对齐paper,也是可以认为收敛的

sg3maiej

sg3maiej7#

环境:CPU
版本:Paddle 2.1.1

可以发现在x1扩大10倍的条件下,该结果最大误差非常大!

import paddle
import torch
import numpy as np
paddle.set_device("cpu")
paddle.set_grad_enabled(False)
torch.set_grad_enabled(False)
a = paddle.nn.Linear(768,768)

######### 关注一下这个,我设置了权重,竟然之后误差那么大。

a.weight.set_value(paddle.randn(a.weight.shape))
a.bias.set_value(paddle.randn(a.bias.shape))

b = torch.nn.Linear(768,768)
b.weight.data = torch.tensor(a.weight.t().numpy())
b.bias.data = torch.tensor(a.bias.numpy())
x1 = paddle.randn((32,768)) * 10  # 参数扩大十倍
x2 = torch.tensor(x1.numpy())

o1 = a(x1).numpy()
o2 = b(x2).numpy()
print("amax ",np.abs(o1-o2).max())
print("amean ",np.abs(o1-o2).mean())
print(np.all(np.isclose(o1,o2 , atol=0, rtol=1.e-6)))

amax  0.00012207031
amean  7.3685546e-06
False

如果我把赋值权重的部分给注解掉,误差竟然正常了??

import paddle
import torch
import numpy as np
paddle.set_device("cpu")
paddle.set_grad_enabled(False)
torch.set_grad_enabled(False)
a = paddle.nn.Linear(768,768)

################################ 如果注解掉手动设置权重的

# a.weight.set_value(paddle.randn(a.weight.shape))

# a.bias.set_value(paddle.randn(a.bias.shape))

b = torch.nn.Linear(768,768)
b.weight.data = torch.tensor(a.weight.t().numpy())
b.bias.data = torch.tensor(a.bias.numpy())
x1 = paddle.randn((32,768))*10 # 参数扩大十倍
x2 = torch.tensor(x1.numpy())

o1 = a(x1).numpy()
o2 = b(x2).numpy()
print("amax ",np.abs(o1-o2).max())
print("amean ",np.abs(o1-o2).mean())
print(np.all(np.isclose(o1,o2 , atol=0, rtol=1.e-6)))

amax  0.0
amean  0.0
True

如果我先初始化pytorch的权重,然后把pytorch权重赋值给paddle。误差又有了。

import paddle
import torch
import numpy as np
paddle.set_device("cpu")
paddle.set_grad_enabled(False)
torch.set_grad_enabled(False)
b = torch.nn.Linear(768,768)
a = paddle.nn.Linear(768,768)
a.weight.set_value(paddle.to_tensor(b.weight.data.t().numpy()))
a.bias.set_value(paddle.to_tensor(b.bias.data.numpy()))

x1 = paddle.randn((32,768))*10
x2 = torch.tensor(x1.numpy())

o1 = a(x1).numpy()
o2 = b(x2).numpy()
print("amax ",np.abs(o1-o2).max())
print("amean ",np.abs(o1-o2).mean())
print(np.all(np.isclose(o1,o2 , atol=0, rtol=1.e-6)))
amax  1.9073486e-06
amean  1.5580031e-07
False

我看了一下这个问题,来解释一下这三种现象:
(1)可以发现在x1扩大10倍的条件下,该结果最大误差非常大!
(2)如果我把赋值权重的部分给注解掉,误差竟然正常了??
(3)如果我先初始化pytorch的权重,然后把pytorch权重赋值给paddle。误差又有了。

首先1和2的区别是参数权重初始化的方式不一致,在1中,参数权重通过paddle.randn进行初始化,该OP返回均值为0,标准差为1的正态随机分布的随机Tensor;而在2中,参数权重通过paddle.nn.Linear进行初始化,该OP使用Xavier权重初始化方法,返回均值为0,标准差为sqrt(2.0/(fan_in+fan_out))的正态随机分布的随机Tensor。由于fan_in和fan_out很大(为768),所以在2中的参数权重标准差比1小很多,从而导致1误差偏大,2误差正常。

在3中,PyTorch中torch.nn.Linear的初始化方式为一个均匀分布U(−k, k),这个分布和正太随机分布相比,权重数值会更加分散,数值精度误差相对也会变大。

相关问题