23

我有一个大数据集的浮点数。我遍历它们并评估它们np.log(x)中的每一个。我明白了

RuntimeWarning: divide by zero encountered in log

如果发生此错误,我想解决此问题并返回 0。

我正在考虑定义一个新功能:

def safe_ln(x):
    #returns: ln(x) but replaces -inf with 0
    l = np.log(x)
    #if l = -inf:
    l = 0
    return l

基本上,我需要一种测试输出的方法,-inf但我不知道如何进行。感谢您的帮助!

4

7 回答 7

37

您正在使用 np 函数,所以我可以安全地猜测您正在处理 numpy 数组?那么最有效的方法是使用 where 函数而不是 for 循环

myarray= np.random.randint(10,size=10)
result = np.where(myarray>0, np.log(myarray), 0)

否则你可以简单地使用日志功能,然后修补漏洞:

myarray= np.random.randint(10,size=10)
result = np.log(myarray)
result[result==-np.inf]=0

np.log 函数在值 0 时正确返回 -inf,所以您确定要返回 0 吗?如果您必须在某个地方恢复到原始值,您将遇到一些问题,将零变为一...

于 2012-11-21T18:13:01.683 回答
25

由于logforx=0是负无穷大,我只需检查输入值是否为零并返回您想要的任何内容:

def safe_ln(x):
    if x <= 0:
        return 0
    return math.log(x)

编辑:小编辑:您应该检查所有小于或等于 0 的值。

编辑 2np.log当然是一个在 numpy 数组上计算的函数,对于你应该使用的单个值math.log。这是上面的函数在 numpy 中的样子:

def safe_ln(x, minval=0.0000000001):
    return np.log(x.clip(min=minval))
于 2012-11-21T16:43:05.820 回答
3

你可以这样做。

def safe_ln(x):
   try:
      l = np.log(x)
   except ZeroDivisionError:
      l = 0
   return l
于 2012-11-21T16:44:09.550 回答
2

Enrico 给出的答案很好,但两种解决方案都会导致警告:

RuntimeWarning: divide by zero encountered in log

作为替代方案,我们仍然可以使用该where函数,但只在适当的地方执行主计算:

# alternative implementation -- a bit more typing but avoids warnings.
loc = np.where(myarray>0)
result2 = np.zeros_like(myarray, dtype=float)
result2[loc] =np.log(myarray[loc])

# answer from Enrico...
myarray= np.random.randint(10,size=10)
result = np.where(myarray>0, np.log(myarray), 0)

# check it is giving right solution:
print(np.allclose(result, result2))

我的用例是除法,但原理显然是一样的:

x = np.random.randint(10, size=10)
divisor = np.ones(10,)
divisor[3] = 0 # make one divisor invalid

y = np.zeros_like(divisor, dtype=float)
loc = np.where(divisor>0) # (or !=0 if your data could have -ve values)
y[loc] = x[loc] / divisor[loc]
于 2018-09-24T18:00:07.443 回答
1

使用异常处理:

In [27]: def safe_ln(x):
    try:
        return math.log(x)
    except ValueError:       # np.log(x) might raise some other error though
        return float("-inf")
   ....:     

In [28]: safe_ln(0)
Out[28]: -inf

In [29]: safe_ln(1)
Out[29]: 0.0

In [30]: safe_ln(-100)
Out[30]: -inf
于 2012-11-21T16:43:44.573 回答
1

我喜欢使用sys.float_info.min如下:

>>> import numpy as np
>>> import sys
>>> arr = np.linspace(0.0, 1.0, 3)
>>> print(arr)
[0.  0.5 1. ]
>>> arr[arr < sys.float_info.min] = sys.float_info.min
>>> print(arr)
[2.22507386e-308 5.00000000e-001 1.00000000e+000]
>>> np.log10(arr)
array([-3.07652656e+02, -3.01029996e-01,  0.00000000e+00])

其他答案也引入了小的正值,但是当我为太小而无法处理的输入近似结果时,我更喜欢使用最小的有效输入。

于 2020-06-09T22:05:37.077 回答
0

你可以这样做:

def safe_ln(x):
    #returns: ln(x) but replaces -inf with 0
    try:
        l = np.log(x)
    except RunTimeWarning:
        l = 0
    return l
于 2012-11-21T16:42:17.323 回答