gpt4 book ai didi

floating-point - 为什么 Octave 四舍五入到 1 'earlier' 而不是 0?

转载 作者:行者123 更新时间:2023-12-04 06:49:42 24 4
gpt4 key购买 nike

语境:

在 Octave 中,我为 Sigmoid 函数编写了代码,该函数返回 0 到 1 之间的值;在理想情况下,它只会为 -Inf 返回 0,为 +Inf 返回 1,但由于浮点不精确,非常接近其中任何一个的值都会被舍入。

问题:

我的问题是为什么会发生以下情况:四舍五入的边界对于 0 和 1 明显不同:

>> sigmoid(-709)
ans = 1.2168e-308
>> sigmoid(-710)
ans = 0
>> sigmoid(36)
ans = 1.00000
>> sigmoid(37)
ans = 1
>> (sigmoid(37)-1)==0
ans = 1
>> (sigmoid(36)-1)==0
ans = 0
>> sigmoid(-710)==0
ans = 1
>> sigmoid(-709)==0
ans = 0

在示例中,可以看到将输出四舍五入为 1 所需的值比四舍五入为 0 所需的值小得多。 37 与 -710 相比是一个非常大的差异,考虑到它们的大小应该相同,但是相反的符号...

我的代码:

也许这是我的功能的问题:
function [z] = sigmoid(x)
z = 1.0 ./(1.0+exp(-x));
endfunction

我试过的:

另一点是,我更改了函数以将 1 添加到结果中(基本上将图形向上平移 1),并且边界分别变为 2 和 1 的 +/- 37 - 这让我觉得这确实与 0 有关特别是,而不仅仅是函数及其下界。

如果这与我的电脑有关,那么什么会导致这样的事情?

最佳答案

首先回顾this brilliant answer by gnovice on floating-point representation .

顺便说一下,让我们看看你在这里看到的:你可以计算一个非常接近于零的值:sigmoid(-709)约等于 1.2e-308 ,但您无法计算出类似接近 1 的值:sigmoid(709)正好等于 1,而不是 1 - 1.2e-308 ,甚至 sigmoid(36) == 1 ,而不是略小于 1 的值。

但是当我们知道浮点数是如何存储在内存中时,我们就会意识到 1 - 1.2e-308无法准确表示。我们需要 308 个十进制数字来准确地表示这个数字。 double 浮点数(Octave 中的默认值)大约有 15 位十进制数字。即,1 - 1e-16可以表示,但是1 - 1e-17不能。
eps(1)的值是 2.2204e-16 ,这是我们可以用 double 浮点数编码的与 1 的最小差异。

但是接近 0 的值可以更精确地表示:eps(0)4.9407e-324 .那是因为诸如 1.2e-308 之类的值不需要表示 308 位十进制数字,只需 2 位,指数值为 -308。

在任何情况下,如果您依赖于离转换位置如此远的 sigmoid 函数的确切值,那么您的代码逻辑就有问题。

如果你想让这个函数对称,你所能做的就是降低低端的精度。有两种方法可以做到这一点:

  • 只需将非常小的值设置为零,这样 z==0到达与 z==1 相同的点另一方面:
    function z = sigmoid(x)
    z = 1.0 ./ (1.0+exp(-x));
    z(z < eps(1)) = 0;
    end
  • 总是计算函数的右半部分,然后折回负输入。这使得x=0两边的计算错误对称:
    function z = sigmoid(x)
    z = 1.0 ./ (1.0+exp(-abs(x)));
    I = x < 0;
    z(I) = 0.5 - z(I);
    end
  • 关于floating-point - 为什么 Octave 四舍五入到 1 'earlier' 而不是 0?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/54657058/

    24 4 0
    Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
    广告合作:1813099741@qq.com 6ren.com