避免使用exp下溢和numpy中的最小正float128

时间:2015-10-30 10:41:13

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

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

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

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是数组的长度

1 个答案:

答案 0 :(得分:3)

使用指数小数字时,通常最好在日志空间中工作。例如,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-learnextmath.logsumexp实现类似的功能,但它基本上与上述相同。