【问题标题】:Avoid underflow using exp and minimum positive float128 in numpy在 numpy 中使用 exp 和最小正 float128 避免下溢
【发布时间】:2016-01-30 18:19:31
【问题描述】:

我正在尝试计算以下比率: w(i) / (sum(w(j)) 其中w 使用指数递减函数更新,即w(i) = w(i) * exp(-k)k 是一个正参数。所有的数字都是非负数。 然后将该比率用于公式(乘以常数并添加另一个常数)。不出所料,我很快就遇到了下溢问题。

我想这经常发生,但有人可以给我一些关于如何处理这个问题的参考吗?我没有找到合适的转换,所以我尝试做的一件事是将一些最小正数设置为安全阈值,但我没有设法找到最小正浮点数(我在 numpy.float128 中表示数字)。我如何才能在我的机器上实际获得最小 positive 这样的数字? 代码如下所示:

w = np.ones(n, dtype='float128')
lt = np.ones(n)
for t in range(T):
    p = (1-k) * w / w.sum() + (k/n)
    # Process a subset of the n elements, call it set I, j is some range()
    for i in I: 
        s = p[list(j[i])].sum()
        lt /= s
        w[s] *= np.exp(-k * lt)

其中 k 是 (0,1) 中的某个常数,n 是数组的长度

【问题讨论】:

  • numpy.float128 是一个非常具有误导性的名称 - 它的实际精度与 C 编译器调用的 long double 相同,在 x86 上为 80 位(为清楚起见,建议使用 @987654331 @alias 代替)。要获得最小的可表示正浮点数,您可以在我的机器上使用 np.finfo(numpy.float128).tiny,即 3.3621031431120935063e-4932,但更有用的阈值可能是机器 epsilon (eps)。
  • 你能告诉我们你的代码吗?我怀疑可能有更好的方法来计算该比率。
  • 谢谢@ali_m 我已经添加了代码的 sn-p,我无法全部添加,但我的想法是随着时间的推移我处理 ws 的不同子集并减少使用 np 的子集.exp().

标签: python numpy numerical-methods numerical-analysis underflow


【解决方案1】:

当处理指数级的小数字时,通常最好在日志空间中工作。例如,log(w*exp(-k)) = log(w) - k,除非 k 本身呈指数级大或 w 为零,否则不会出现任何上溢/下溢问题。而且,如果w 为零,numpy 将正确返回-inf。然后,在求和时,您会考虑出最大的项:

log_w = np.log(w) - k
max_log_w = np.max(log_w)
# Individual terms in the following may underflow, but then they wouldn't
# contribute to the sum anyways.
log_sum_w = max_log_w + np.log(np.sum(np.exp(log_w - max_log_w)))
log_ratio = log_w - log_sum_w

这可能不是您想要的,因为您可以完全排除 k(假设它是一个常量而不是数组),但它应该可以帮助您。

Scikit-learn 实现了与extmath.logsumexp 类似的东西,但与上面的基本相同。

【讨论】:

  • 不知道scipy.misc.logsumexp,这似乎对OP特别有用。谢谢!
  • np.logaddexp 也是一个 ufunc,因此您可以使用 np.logaddexp.reduce 沿数组的轴求和
猜你喜欢
  • 1970-01-01
  • 2012-08-09
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2015-06-19
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多