【问题标题】:Using np.expm1 to compute sigmoid function使用 np.expm1 计算 sigmoid 函数
【发布时间】:2018-04-25 16:04:53
【问题描述】:

在计算sigmoid function 时,由于缺乏浮点精度,x 的小值或大值将分别返回 0 和 1。在numpy 中,函数np.expm1 将计算exp(x)-1,对于x 的极值具有更高的精度。但是,不存在用于计算exp(x)+1(sigmoid 函数中的分母)的等效函数。我不知道如何使用np.expm1 来计算在极值处精度更高的 sigmoid。有办法吗?

1/(np.exp(-20)+1)==1.0
#False
1/(np.exp(-50)+1)==1.0
# True

【问题讨论】:

  • exp(x)-1 有一个特殊的例程,因为当 x 接近于零时,exp(x)-1 接近于零。根据浮点的性质,当 x 接近于零时,可以对其进行非常细微的更改,函数 exp(x)-1 反映了这些更改。相反,对于任何实数 x,exp(x)+1 永远不会接近零。 x 的非常细微的变化对计算结果没有影响,因为浮点格式无法表示当 x 发生微小变化时 exp(x)+1 中发生的微小变化。通过计算 exp(x) 并加 1,您将得到相同或几乎相同的结果。
  • 1/(exp(-50)+1) 的精确值的前 40 位是0.9999999999999999999998071250152036082216。可表示为 64 位浮点数的最接近值是 1.0。如果您需要比这更高的精度,则必须使用提供比标准 64 位浮点数更精确的数字表示的库。例如,我使用mpmath 来计算这 40 位数字。
  • 或者,当 x > 0 时不计算 sigmoid(x),只计算 1 和 sigmoid(x) 之间的差,根据对称性,是 sigmoid(-x)。例如,1 - sigmoid(50) = sigmoid(-50) = 1.928749...e-22。但是随后您必须修改其余代码以处理这种差异。这是否值得(甚至可能)取决于您将如何处理 sigmoid(x) 的值。
  • 顺便说一下,对于计算sigmoid函数,我推荐scipy.special.expit而不是基于exp创建自己的实现;例如,参见stackoverflow.com/questions/21106134/…
  • @EricPostpischil 好的,我现在明白了,所以显然这同样适用于np.log1p

标签: numpy floating-point


【解决方案1】:

np.expm1 减轻了在取两个几乎相等的数字之间的差时发生的显着性损失(因为许​​多显着位置会相互抵消,结果将具有比数据类型可以存储的更少显着位置)。

1/(np.exp(-50)+1)==1.0

是数据类型的限制,而不是算法的限制。 floats 无法解决与 1.0 小到 exp(-50) 的差异。事实上,1.0 左右最近的浮点数是

>>> np.nextafter(1.0, 0.0)
0.9999999999999999
>>> np.nextafter(1.0, 2.0)
1.0000000000000002

表示分辨率为 oom 10^-16,远不足以区分 11 +/- exp(-50)

【讨论】:

    猜你喜欢
    • 2016-12-05
    • 1970-01-01
    • 2015-07-19
    • 2012-07-22
    • 2021-02-16
    • 2018-06-06
    • 2019-07-13
    • 2020-09-14
    • 2017-10-08
    相关资源
    最近更新 更多