首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >PyTorch梯度与手工计算的梯度不同

PyTorch梯度与手工计算的梯度不同
EN

Stack Overflow用户
提问于 2018-11-13 05:48:37
回答 1查看 1.3K关注 0票数 5

我试图计算1/x的梯度,而不使用Pytorch的自动梯度。我使用公式梯度(1/x,x) = -1/x**2。当我将我的结果与给出的梯度进行比较时,它们是不同的。

这是我的代码:

代码语言:javascript
复制
a = torch.tensor(np.random.randn(), dtype=dtype, requires_grad=True)
loss = 1/a
loss.backward()
print(a.grad - (-1/(a**2)))

产出如下:

代码语言:javascript
复制
tensor(5.9605e-08, grad_fn=<ThAddBackward>)

有人能向我解释一下是什么问题吗?

EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2018-11-13 10:27:34

所以我想结果是零。当你仔细观察时,你会发现它是相当接近的。当在二进制系统(计算机)上划分数字时,经常会出现舍入错误.

让我们看看您的示例,并添加了一个额外的print语句:

代码语言:javascript
复制
a = torch.tensor(np.random.randn(), requires_grad=True)
loss = 1/a
loss.backward()
print(a.grad, (-1/(a**2)))
print(a.grad - (-1/(a**2)))

因为您使用的是随机输入,输出当然也是随机的。

(所以你不会得到相同的数字,但只要重复这个实验,你就会有类似的例子)。

有时你会得到零作为结果。但在你最初的例子中,情况并非如此:

代码语言:javascript
复制
tensor(-0.9074) tensor(-0.9074, grad_fn=<MulBackward>)
tensor(5.9605e-08, grad_fn=<ThSubBackward>)

您可以看到,尽管两者都显示为相同的数字,但它们在小数点的最后一位中存在差异。这就是为什么当你把两者相减的时候,你会得到很小的差别。

这个问题作为计算机的一个普遍问题,有些分数只是有一个大的或无限的小数位数,但是你的计算机的内存却没有。所以他们在某个时候被切断了。

所以你在这里所经历的其实是缺乏精确性。精度取决于您所使用的数值数据类型(即torch.float32torch.float64)。

您还可以在这里查看更多信息:

https://en.wikipedia.org/wiki/Double-precision_floating-point_format

但是这并不是PyTorch特有的,这里有一个Python示例:

代码语言:javascript
复制
print(29/100*100)

在以下方面的成果:

代码语言:javascript
复制
28.999999999999996

编辑:

正如@HOANG所指出的,将方程改为-(1/a)*(1/a)效果很好,结果为零。这可能是因为用于计算梯度的计算非常类似(或相同) -(1/a)*(1/a)。因此,它有相同的舍入误差,因此差异为零。

因此,这里还有另一个比上面的例子更合适的例子。即使-(1/x)*(1/x)在数学上等价于-1/x^2,但根据x的值,在计算机上计算它时并不总是相同的。

代码语言:javascript
复制
import numpy as np
print('e1 == e2','x value', '\t'*2, 'round-off error', sep='\t')
print('='*70)
for i in range(10):
    x = np.random.randn()
    e1 = -(1/x)*(1/x)
    e2 = (-1/(x**2))
    print(e1 == e2, x, e1-e2, sep='\t\t')

输出:

代码语言:javascript
复制
e1 == e2    x value                 round-off error
======================================================================
True        0.2934154339948173      0.0
True        -1.2881863891014191     0.0
True        1.0463038021843876      0.0
True        -0.3388766143622498     0.0
True        -0.6915415747192347     0.0
False       1.3299049850551317      1.1102230246251565e-16
True        -1.2392046539563553     0.0
False       -0.42534236747121645    8.881784197001252e-16
True        1.407198823994324       0.0
False       -0.21798652132356966    3.552713678800501e-15

尽管舍入误差似乎要小一些(我尝试了不同的随机值,并且很少超过十分之二有舍入错误),但在计算1/x时仍然存在很小的差异。

代码语言:javascript
复制
import numpy as np
print('e1 == e2','x value', '\t'*2, 'round-off error', sep='\t')
print('='*70)
for i in range(10):
    x = np.random.randn()
    # calculate 1/x
    result = 1/x
    # apply inverse function
    reconstructed_x = 1/result
    # mathematically this should be the same as x
    print(x == reconstructed_x, x, x-reconstructed_x, sep='\t\t')

输出:

代码语言:javascript
复制
e1 == e2    x value             round-off error
======================================================================
False       0.9382823115235075      1.1102230246251565e-16
True        -0.5081217386356917     0.0
True        -0.04229436058156134    0.0
True        1.1121100294357302      0.0
False       0.4974618312372863      -5.551115123125783e-17
True        -0.20409933212316553    0.0
True        -0.6501652554924282     0.0
True        -3.048057937738731      0.0
True        1.6236075700470816      0.0
True        0.4936926651641918      0.0
票数 6
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/53274587

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档