为日志定义boudned ufunc

时间:2014-08-12 21:43:16

标签: python numpy

我正在尝试定义一个函数log_bounded,它与numpy的log相同,用于正输入,但是它为非正输入提供了一个很大的负数。我需要它是一个可以接受数组作为输入的ufunc。

到目前为止,我有:

def log_bounded(x,verysmall=np.exp(-100)):
    return np.log(np.maximum(x,verysmall))

这样可行,返回-100表示​​否定输入:

>>> log_bounded(2.72)
1.000631880307906
>>> log_bounded(-5)
-100.0

但我希望它返回一个更低的值,比如-10 ** 10。我认为理想的是检查x的值并直接返回低值,而不是记录接近于零的值,例如

def log_bounded_if(x, verylow=-10**10):
    if x > 0:
        return np.log(x)
    else:
        return verylow

但是,这个不能在数组上进行元素操作,因为if试图为整个数组运行一次​​。

Scipy可以使用scipy.maximum(scipy.log(x),verylow)完成工作,因为scipy.log在非正输入上评估为负无穷大。但是,我需要使用numpy,因为这将与numba的autojit一起运行,scipy似乎消除了速度优势。

1 个答案:

答案 0 :(得分:0)

您可以通过logical indexing完成此操作。

最小解决方案:

import numpy as np

def log_bounded(x, verylow=-10**10):
    y = np.log(x)
    y[x <= 0] = verylow
    return y

print log_bounded(np.arange(-2, 3))

输出:[ -1.00000000e+10 -1.00000000e+10 -1.00000000e+10 0 6.93147181e-01]


更高级的替代方案:(处理标量;保存不必要的log次计算)

import numpy as np

def log_bounded(x, verylow=-10**10):
    if np.isscalar(x):               # handle scalars as well
        if x > 0:
            y = np.log(x)
        else:
            y = verylow
    else:
        y = np.empty_like(x)
        y[x > 0] = np.log(x[x > 0])  # compute log only where needed
        y[x <= 0] = verylow
    return y

print log_bounded(-3), log_bounded(np.arange(-2, 3)), log_bounded(3)

输出:-10000000000 [-10000000000 -10000000000 -10000000000 0 0] 1.09861228867